[llvm] r317730 - Let replaceVTableHolder accept any type.

Adrian Prantl via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 8 14:04:43 PST 2017


Author: adrian
Date: Wed Nov  8 14:04:43 2017
New Revision: 317730

URL: http://llvm.org/viewvc/llvm-project?rev=317730&view=rev
Log:
Let replaceVTableHolder accept any type.

In Rust, a trait can be implemented for any type, and if a trait
object pointer is used for the type, then a virtual table will be
emitted for that trait/type combination.

We would like debuggers to be able to inspect trait objects, which
requires finding the concrete type associated with a given vtable.

This patch changes LLVM so that any type can be passed to
replaceVTableHolder. This allows the Rust compiler to emit the needed
debug info -- associating a vtable with the concrete type for which it
was emitted.

This is a DWARF extension: DWARF only specifies the meaning of
DW_AT_containing_type in one specific situation. This style of DWARF
extension is routine, though, and LLVM already has one such case for
DW_AT_containing_type.

Patch by Tom Tromey!

Differential Revision: https://reviews.llvm.org/D39503

Added:
    llvm/trunk/test/DebugInfo/Generic/containing-type-extension-rust.ll
    llvm/trunk/test/DebugInfo/Generic/containing-type-extension.ll
Modified:
    llvm/trunk/include/llvm/IR/DIBuilder.h
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
    llvm/trunk/lib/IR/DIBuilder.cpp
    llvm/trunk/unittests/IR/MetadataTest.cpp

Modified: llvm/trunk/include/llvm/IR/DIBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DIBuilder.h?rev=317730&r1=317729&r2=317730&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DIBuilder.h (original)
+++ llvm/trunk/include/llvm/IR/DIBuilder.h Wed Nov  8 14:04:43 2017
@@ -757,12 +757,12 @@ namespace llvm {
                                          const DILocation *DL,
                                          Instruction *InsertBefore);
 
-    /// Replace the vtable holder in the given composite type.
+    /// Replace the vtable holder in the given type.
     ///
     /// If this creates a self reference, it may orphan some unresolved cycles
     /// in the operands of \c T, so \a DIBuilder needs to track that.
     void replaceVTableHolder(DICompositeType *&T,
-                             DICompositeType *VTableHolder);
+                             DIType *VTableHolder);
 
     /// Replace arrays on a composite type.
     ///

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=317730&r1=317729&r2=317730&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp Wed Nov  8 14:04:43 2017
@@ -960,8 +960,9 @@ void DwarfUnit::constructTypeDIE(DIE &Bu
 
     // This is outside the DWARF spec, but GDB expects a DW_AT_containing_type
     // inside C++ composite types to point to the base class with the vtable.
-    if (auto *ContainingType =
-            dyn_cast_or_null<DICompositeType>(resolve(CTy->getVTableHolder())))
+    // Rust uses DW_AT_containing_type to link a vtable to the type
+    // for which it was created.
+    if (auto *ContainingType = resolve(CTy->getVTableHolder()))
       addDIEEntry(Buffer, dwarf::DW_AT_containing_type,
                   *getOrCreateTypeDIE(ContainingType));
 

Modified: llvm/trunk/lib/IR/DIBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DIBuilder.cpp?rev=317730&r1=317729&r2=317730&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DIBuilder.cpp (original)
+++ llvm/trunk/lib/IR/DIBuilder.cpp Wed Nov  8 14:04:43 2017
@@ -874,7 +874,7 @@ Instruction *DIBuilder::insertDbgValueIn
 }
 
 void DIBuilder::replaceVTableHolder(DICompositeType *&T,
-                                    DICompositeType *VTableHolder) {
+                                    DIType *VTableHolder) {
   {
     TypedTrackingMDRef<DICompositeType> N(T);
     N->replaceVTableHolder(VTableHolder);

Added: llvm/trunk/test/DebugInfo/Generic/containing-type-extension-rust.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/Generic/containing-type-extension-rust.ll?rev=317730&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/Generic/containing-type-extension-rust.ll (added)
+++ llvm/trunk/test/DebugInfo/Generic/containing-type-extension-rust.ll Wed Nov  8 14:04:43 2017
@@ -0,0 +1,125 @@
+; REQUIRES: object-emission
+
+; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
+; RUN: llvm-dwarfdump -v -debug-info %t | FileCheck %s
+
+; Check that any type can have a vtable holder.
+; CHECK: [[SP:.*]]: DW_TAG_structure_type
+; CHECK-NOT: TAG
+; CHECK: DW_AT_containing_type [DW_FORM_ref4]
+; CHECK: DW_AT_name [DW_FORM_strp] {{.*}}= "vtable")
+
+; This was compiled using
+; rustc -g --emit=llvm-ir t2.rs
+; ... and then edited by hand, because rustc is using a somewhat older llvm.
+;
+; t2.rs is:
+;
+; // trait object test case
+;
+; pub trait T {
+; }
+;
+; impl T for f64 {
+; }
+;
+; pub fn main() {
+;     let tu = &23.0f64 as &T;
+; }
+; t2.rs ends here ^^^
+
+; ModuleID = 't2.cgu-0.rs'
+source_filename = "t2.cgu-0.rs"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at ref.0 = internal unnamed_addr constant double 2.300000e+01, align 8
+ at vtable.1 = internal unnamed_addr constant { void (double*)*, i64, i64 } { void (double*)* @_ZN4core3ptr13drop_in_place17h2818a933abde117eE, i64 8, i64 8 }, align 8, !dbg !0
+ at __rustc_debug_gdb_scripts_section__ = linkonce_odr unnamed_addr constant [34 x i8] c"\01gdb_load_rust_pretty_printers.py\00", section ".debug_gdb_scripts", align 1
+
+; core::ptr::drop_in_place
+; Function Attrs: uwtable
+define internal void @_ZN4core3ptr13drop_in_place17h2818a933abde117eE(double*) unnamed_addr #0 !dbg !11 {
+start:
+  %arg0 = alloca double*
+  store double* %0, double** %arg0
+  call void @llvm.dbg.declare(metadata double** %arg0, metadata !20, metadata !22), !dbg !23
+  ret void, !dbg !24
+}
+
+; t2::main
+; Function Attrs: uwtable
+define internal void @_ZN2t24main17h6319e6ac7de3a097E() unnamed_addr #0 !dbg !25 {
+start:
+  %tu = alloca { i8*, void (i8*)** }
+  call void @llvm.dbg.declare(metadata { i8*, void (i8*)** }* %tu, metadata !29, metadata !22), !dbg !37
+  %0 = getelementptr inbounds { i8*, void (i8*)** }, { i8*, void (i8*)** }* %tu, i32 0, i32 0, !dbg !37
+  store i8* bitcast (double* @ref.0 to i8*), i8** %0, !dbg !37
+  %1 = getelementptr inbounds { i8*, void (i8*)** }, { i8*, void (i8*)** }* %tu, i32 0, i32 1, !dbg !37
+  store void (i8*)** bitcast ({ void (double*)*, i64, i64 }* @vtable.1 to void (i8*)**), void (i8*)*** %1, !dbg !37
+  ret void, !dbg !38
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+define i32 @main(i32, i8**) unnamed_addr #2 {
+top:
+  %2 = load volatile i8, i8* getelementptr inbounds ([34 x i8], [34 x i8]* @__rustc_debug_gdb_scripts_section__, i32 0, i32 0), align 1
+  %3 = sext i32 %0 to i64
+; call std::rt::lang_start
+  %4 = call i64 @_ZN3std2rt10lang_start17h2626caf1112a00beE(void ()* @_ZN2t24main17h6319e6ac7de3a097E, i64 %3, i8** %1)
+  %5 = trunc i64 %4 to i32
+  ret i32 %5
+}
+
+; std::rt::lang_start
+declare i64 @_ZN3std2rt10lang_start17h2626caf1112a00beE(void ()*, i64, i8**) unnamed_addr #3
+
+attributes #0 = { uwtable "no-frame-pointer-elim"="true" "probe-stack"="__rust_probestack" }
+attributes #1 = { nounwind readnone }
+attributes #2 = { "no-frame-pointer-elim"="true" }
+attributes #3 = { "no-frame-pointer-elim"="true" "probe-stack"="__rust_probestack" }
+
+!llvm.module.flags = !{!6, !7}
+!llvm.dbg.cu = !{!8}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "vtable", scope: null, file: !2, type: !3, isLocal: true, isDefinition: true)
+!2 = !DIFile(filename: "<unknown>", directory: "")
+!3 = !DICompositeType(tag: DW_TAG_structure_type, name: "vtable", file: !2, size: 64, align: 64, flags: DIFlagArtificial, elements: !4, vtableHolder: !5, identifier: "vtable")
+!4 = !{}
+!5 = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float)
+!6 = !{i32 1, !"PIE Level", i32 2}
+!7 = !{i32 2, !"Debug Info Version", i32 3}
+!8 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !9, producer: "clang LLVM (rustc version 1.22.0-dev)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !10)
+!9 = !DIFile(filename: "t2.rs", directory: "/home/tromey/Rust")
+!10 = !{!0}
+!11 = distinct !DISubprogram(name: "drop_in_place<f64>", linkageName: "_ZN4core3ptr18drop_in_place<f64>E", scope: !13, file: !12, line: 59, type: !15, isLocal: false, isDefinition: true, scopeLine: 59, flags: DIFlagPrototyped, isOptimized: false, unit: !8, templateParams: !18, variables: !4)
+!12 = !DIFile(filename: "/home/tromey/Rust/rust/src/libcore/ptr.rs", directory: "")
+!13 = !DINamespace(name: "ptr", scope: !14)
+!14 = !DINamespace(name: "core", scope: null)
+!15 = !DISubroutineType(types: !16)
+!16 = !{null, !17}
+!17 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "*mut f64", baseType: !5, size: 64, align: 64)
+!18 = !{!19}
+!19 = !DITemplateTypeParameter(name: "T", type: !5)
+!20 = !DILocalVariable(arg: 1, scope: !11, file: !21, line: 1, type: !17)
+!21 = !DIFile(filename: "t2.rs", directory: "")
+!22 = !DIExpression()
+!23 = !DILocation(line: 1, scope: !11)
+!24 = !DILocation(line: 59, scope: !11)
+!25 = distinct !DISubprogram(name: "main", linkageName: "_ZN2t24mainE", scope: !26, file: !9, line: 9, type: !27, isLocal: true, isDefinition: true, scopeLine: 9, flags: DIFlagPrototyped | DIFlagMainSubprogram, isOptimized: false, unit: !8, templateParams: !4, variables: !4)
+!26 = !DINamespace(name: "t2", scope: null)
+!27 = !DISubroutineType(types: !28)
+!28 = !{null}
+!29 = !DILocalVariable(name: "tu", scope: !30, file: !9, line: 10, type: !31, align: 8)
+!30 = distinct !DILexicalBlock(scope: !25, file: !9, line: 10, column: 4)
+!31 = !DICompositeType(tag: DW_TAG_structure_type, name: "&T", scope: !26, file: !2, size: 128, align: 64, elements: !32, identifier: "b9f642b757d8ad3984c1e721e3ce6016d14d9322")
+!32 = !{!33, !36}
+!33 = !DIDerivedType(tag: DW_TAG_member, name: "pointer", scope: !31, file: !2, baseType: !34, size: 64, align: 64, flags: DIFlagArtificial)
+!34 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "*const u8", baseType: !35, size: 64, align: 64)
+!35 = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
+!36 = !DIDerivedType(tag: DW_TAG_member, name: "vtable", scope: !31, file: !2, baseType: !34, size: 64, align: 64, offset: 64, flags: DIFlagArtificial)
+!37 = !DILocation(line: 10, scope: !30)
+!38 = !DILocation(line: 11, scope: !25)

Added: llvm/trunk/test/DebugInfo/Generic/containing-type-extension.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/Generic/containing-type-extension.ll?rev=317730&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/Generic/containing-type-extension.ll (added)
+++ llvm/trunk/test/DebugInfo/Generic/containing-type-extension.ll Wed Nov  8 14:04:43 2017
@@ -0,0 +1,39 @@
+; REQUIRES: object-emission
+
+; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
+; RUN: llvm-dwarfdump -v -debug-info %t | FileCheck %s
+
+; Check that any type can have a vtable holder.
+; CHECK: [[SP:.*]]: DW_TAG_structure_type
+; CHECK-NOT: TAG
+; CHECK: DW_AT_containing_type [DW_FORM_ref4]
+; CHECK: DW_AT_name [DW_FORM_strp] {{.*}}= "vtable")
+
+; The code doesn't actually matter.
+define i32 @main() #0 !dbg !4 {
+entry:
+  %retval = alloca i32, align 4
+  store i32 0, i32* %retval
+  ret i32 0, !dbg !10
+}
+
+attributes #0 = { nounwind uwtable }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9, !11}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_Rust, producer: "clang version 3.4 (trunk 185475)", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !15, imports: !2)
+!1 = !DIFile(filename: "CodeGen/dwarf-version.c", directory: "test")
+!2 = !{}
+!4 = distinct !DISubprogram(name: "main", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped | DIFlagMainSubprogram, isOptimized: false, unit: !0, scopeLine: 6, file: !1, scope: !5, type: !6, variables: !2)
+!5 = !DIFile(filename: "CodeGen/dwarf-version.c", directory: "test")
+!6 = !DISubroutineType(types: !7)
+!7 = !{!8}
+!8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!9 = !{i32 2, !"Dwarf Version", i32 4}
+!10 = !DILocation(line: 7, scope: !4)
+!11 = !{i32 1, !"Debug Info Version", i32 3}
+!12 = !DICompositeType(tag: DW_TAG_structure_type, name: "vtable", size: 8, align: 8, elements: !2, identifier: "vtable", vtableHolder: !8)
+!13 = !DIGlobalVariableExpression(var: !14, expr: !DIExpression())
+!14 = !DIGlobalVariable(name: "vtable", linkageName: "vtable", scope: null, file: !1, line: 1, type: !12, isLocal: true, isDefinition: true)
+!15 = !{!13}

Modified: llvm/trunk/unittests/IR/MetadataTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=317730&r1=317729&r2=317730&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/MetadataTest.cpp (original)
+++ llvm/trunk/unittests/IR/MetadataTest.cpp Wed Nov  8 14:04:43 2017
@@ -1314,6 +1314,11 @@ TEST_F(DICompositeTypeTest, replaceOpera
   EXPECT_EQ(nullptr, N->getVTableHolder());
   N->replaceVTableHolder(VTableHolder);
   EXPECT_EQ(VTableHolder, N->getVTableHolder());
+  // As an extension, the containing type can be anything.  This is
+  // used by Rust to associate vtables with their concrete type.
+  DIType *BasicType = getBasicType("basic");
+  N->replaceVTableHolder(BasicType);
+  EXPECT_EQ(BasicType, N->getVTableHolder());
   N->replaceVTableHolder(nullptr);
   EXPECT_EQ(nullptr, N->getVTableHolder());
 




More information about the llvm-commits mailing list