Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 51f104b

Browse files
authored
Merge pull request #97 from tromey/trait-object-debug
Let replaceVTableHolder accept any type.
2 parents b48f77c + 660c65a commit 51f104b

File tree

6 files changed

+175
-5
lines changed

6 files changed

+175
-5
lines changed

include/llvm/IR/DIBuilder.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -743,12 +743,12 @@ namespace llvm {
743743
const DILocation *DL,
744744
Instruction *InsertBefore);
745745

746-
/// Replace the vtable holder in the given composite type.
746+
/// Replace the vtable holder in the given type.
747747
///
748748
/// If this creates a self reference, it may orphan some unresolved cycles
749749
/// in the operands of \c T, so \a DIBuilder needs to track that.
750750
void replaceVTableHolder(DICompositeType *&T,
751-
DICompositeType *VTableHolder);
751+
DIType *VTableHolder);
752752

753753
/// Replace arrays on a composite type.
754754
///

lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -955,8 +955,9 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
955955

956956
// This is outside the DWARF spec, but GDB expects a DW_AT_containing_type
957957
// inside C++ composite types to point to the base class with the vtable.
958-
if (auto *ContainingType =
959-
dyn_cast_or_null<DICompositeType>(resolve(CTy->getVTableHolder())))
958+
// Rust uses DW_AT_containing_type to link a vtable to the type
959+
// for which it was created.
960+
if (auto *ContainingType = resolve(CTy->getVTableHolder()))
960961
addDIEEntry(Buffer, dwarf::DW_AT_containing_type,
961962
*getOrCreateTypeDIE(ContainingType));
962963

lib/IR/DIBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,7 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,
858858
}
859859

860860
void DIBuilder::replaceVTableHolder(DICompositeType *&T,
861-
DICompositeType *VTableHolder) {
861+
DIType *VTableHolder) {
862862
{
863863
TypedTrackingMDRef<DICompositeType> N(T);
864864
N->replaceVTableHolder(VTableHolder);
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
; REQUIRES: object-emission
2+
3+
; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
4+
; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s
5+
6+
; Check that any type can have a vtable holder.
7+
; CHECK: [[SP:.*]]: DW_TAG_structure_type
8+
; CHECK-NOT: TAG
9+
; CHECK: DW_AT_containing_type [DW_FORM_ref4]
10+
; CHECK: DW_AT_name [DW_FORM_strp] {{.*}}= "vtable")
11+
12+
; This was compiled using
13+
; rustc -g --emit=llvm-ir t2.rs
14+
; ... and then edited by hand, because rustc is using a somewhat older llvm.
15+
;
16+
; t2.rs is:
17+
;
18+
; // trait object test case
19+
;
20+
; pub trait T {
21+
; }
22+
;
23+
; impl T for f64 {
24+
; }
25+
;
26+
; pub fn main() {
27+
; let tu = &23.0f64 as &T;
28+
; }
29+
; t2.rs ends here ^^^
30+
31+
; ModuleID = 't2.cgu-0.rs'
32+
source_filename = "t2.cgu-0.rs"
33+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
34+
target triple = "x86_64-unknown-linux-gnu"
35+
36+
@ref.0 = internal unnamed_addr constant double 2.300000e+01, align 8
37+
@vtable.1 = internal unnamed_addr constant { void (double*)*, i64, i64 } { void (double*)* @_ZN4core3ptr13drop_in_place17h2818a933abde117eE, i64 8, i64 8 }, align 8, !dbg !0
38+
@__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
39+
40+
; core::ptr::drop_in_place
41+
; Function Attrs: uwtable
42+
define internal void @_ZN4core3ptr13drop_in_place17h2818a933abde117eE(double*) unnamed_addr #0 !dbg !11 {
43+
start:
44+
%arg0 = alloca double*
45+
store double* %0, double** %arg0
46+
call void @llvm.dbg.declare(metadata double** %arg0, metadata !20, metadata !22), !dbg !23
47+
ret void, !dbg !24
48+
}
49+
50+
; t2::main
51+
; Function Attrs: uwtable
52+
define internal void @_ZN2t24main17h6319e6ac7de3a097E() unnamed_addr #0 !dbg !25 {
53+
start:
54+
%tu = alloca { i8*, void (i8*)** }
55+
call void @llvm.dbg.declare(metadata { i8*, void (i8*)** }* %tu, metadata !29, metadata !22), !dbg !37
56+
%0 = getelementptr inbounds { i8*, void (i8*)** }, { i8*, void (i8*)** }* %tu, i32 0, i32 0, !dbg !37
57+
store i8* bitcast (double* @ref.0 to i8*), i8** %0, !dbg !37
58+
%1 = getelementptr inbounds { i8*, void (i8*)** }, { i8*, void (i8*)** }* %tu, i32 0, i32 1, !dbg !37
59+
store void (i8*)** bitcast ({ void (double*)*, i64, i64 }* @vtable.1 to void (i8*)**), void (i8*)*** %1, !dbg !37
60+
ret void, !dbg !38
61+
}
62+
63+
; Function Attrs: nounwind readnone
64+
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
65+
66+
define i32 @main(i32, i8**) unnamed_addr #2 {
67+
top:
68+
%2 = load volatile i8, i8* getelementptr inbounds ([34 x i8], [34 x i8]* @__rustc_debug_gdb_scripts_section__, i32 0, i32 0), align 1
69+
%3 = sext i32 %0 to i64
70+
; call std::rt::lang_start
71+
%4 = call i64 @_ZN3std2rt10lang_start17h2626caf1112a00beE(void ()* @_ZN2t24main17h6319e6ac7de3a097E, i64 %3, i8** %1)
72+
%5 = trunc i64 %4 to i32
73+
ret i32 %5
74+
}
75+
76+
; std::rt::lang_start
77+
declare i64 @_ZN3std2rt10lang_start17h2626caf1112a00beE(void ()*, i64, i8**) unnamed_addr #3
78+
79+
attributes #0 = { uwtable "no-frame-pointer-elim"="true" "probe-stack"="__rust_probestack" }
80+
attributes #1 = { nounwind readnone }
81+
attributes #2 = { "no-frame-pointer-elim"="true" }
82+
attributes #3 = { "no-frame-pointer-elim"="true" "probe-stack"="__rust_probestack" }
83+
84+
!llvm.module.flags = !{!6, !7}
85+
!llvm.dbg.cu = !{!8}
86+
87+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
88+
!1 = distinct !DIGlobalVariable(name: "vtable", scope: null, file: !2, type: !3, isLocal: true, isDefinition: true)
89+
!2 = !DIFile(filename: "<unknown>", directory: "")
90+
!3 = !DICompositeType(tag: DW_TAG_structure_type, name: "vtable", file: !2, size: 64, align: 64, flags: DIFlagArtificial, elements: !4, vtableHolder: !5, identifier: "vtable")
91+
!4 = !{}
92+
!5 = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float)
93+
!6 = !{i32 1, !"PIE Level", i32 2}
94+
!7 = !{i32 2, !"Debug Info Version", i32 3}
95+
!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)
96+
!9 = !DIFile(filename: "t2.rs", directory: "/home/tromey/Rust")
97+
!10 = !{!0}
98+
!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)
99+
!12 = !DIFile(filename: "/home/tromey/Rust/rust/src/libcore/ptr.rs", directory: "")
100+
!13 = !DINamespace(name: "ptr", scope: !14)
101+
!14 = !DINamespace(name: "core", scope: null)
102+
!15 = !DISubroutineType(types: !16)
103+
!16 = !{null, !17}
104+
!17 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "*mut f64", baseType: !5, size: 64, align: 64)
105+
!18 = !{!19}
106+
!19 = !DITemplateTypeParameter(name: "T", type: !5)
107+
!20 = !DILocalVariable(arg: 1, scope: !11, file: !21, line: 1, type: !17)
108+
!21 = !DIFile(filename: "t2.rs", directory: "")
109+
!22 = !DIExpression()
110+
!23 = !DILocation(line: 1, scope: !11)
111+
!24 = !DILocation(line: 59, scope: !11)
112+
!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)
113+
!26 = !DINamespace(name: "t2", scope: null)
114+
!27 = !DISubroutineType(types: !28)
115+
!28 = !{null}
116+
!29 = !DILocalVariable(name: "tu", scope: !30, file: !9, line: 10, type: !31, align: 8)
117+
!30 = distinct !DILexicalBlock(scope: !25, file: !9, line: 10, column: 4)
118+
!31 = !DICompositeType(tag: DW_TAG_structure_type, name: "&T", scope: !26, file: !2, size: 128, align: 64, elements: !32, identifier: "b9f642b757d8ad3984c1e721e3ce6016d14d9322")
119+
!32 = !{!33, !36}
120+
!33 = !DIDerivedType(tag: DW_TAG_member, name: "pointer", scope: !31, file: !2, baseType: !34, size: 64, align: 64, flags: DIFlagArtificial)
121+
!34 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "*const u8", baseType: !35, size: 64, align: 64)
122+
!35 = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
123+
!36 = !DIDerivedType(tag: DW_TAG_member, name: "vtable", scope: !31, file: !2, baseType: !34, size: 64, align: 64, offset: 64, flags: DIFlagArtificial)
124+
!37 = !DILocation(line: 10, scope: !30)
125+
!38 = !DILocation(line: 11, scope: !25)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; REQUIRES: object-emission
2+
3+
; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
4+
; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s
5+
6+
; Check that any type can have a vtable holder.
7+
; CHECK: [[SP:.*]]: DW_TAG_structure_type
8+
; CHECK-NOT: TAG
9+
; CHECK: DW_AT_containing_type [DW_FORM_ref4]
10+
; CHECK: DW_AT_name [DW_FORM_strp] {{.*}}= "vtable")
11+
12+
; The code doesn't actually matter.
13+
define i32 @main() #0 !dbg !4 {
14+
entry:
15+
%retval = alloca i32, align 4
16+
store i32 0, i32* %retval
17+
ret i32 0, !dbg !10
18+
}
19+
20+
attributes #0 = { nounwind uwtable }
21+
22+
!llvm.dbg.cu = !{!0}
23+
!llvm.module.flags = !{!9, !11}
24+
25+
!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)
26+
!1 = !DIFile(filename: "CodeGen/dwarf-version.c", directory: "test")
27+
!2 = !{}
28+
!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)
29+
!5 = !DIFile(filename: "CodeGen/dwarf-version.c", directory: "test")
30+
!6 = !DISubroutineType(types: !7)
31+
!7 = !{!8}
32+
!8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
33+
!9 = !{i32 2, !"Dwarf Version", i32 4}
34+
!10 = !DILocation(line: 7, scope: !4)
35+
!11 = !{i32 1, !"Debug Info Version", i32 3}
36+
!12 = !DICompositeType(tag: DW_TAG_structure_type, name: "vtable", size: 8, align: 8, elements: !2, identifier: "vtable", vtableHolder: !8)
37+
!13 = !DIGlobalVariableExpression(var: !14, expr: !DIExpression())
38+
!14 = !DIGlobalVariable(name: "vtable", linkageName: "vtable", scope: null, file: !1, line: 1, type: !12, isLocal: true, isDefinition: true)
39+
!15 = !{!13}

unittests/IR/MetadataTest.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,6 +1304,11 @@ TEST_F(DICompositeTypeTest, replaceOperands) {
13041304
EXPECT_EQ(nullptr, N->getVTableHolder());
13051305
N->replaceVTableHolder(VTableHolder);
13061306
EXPECT_EQ(VTableHolder, N->getVTableHolder());
1307+
// As an extension, the containing type can be anything. This is
1308+
// used by Rust to associate vtables with their concrete type.
1309+
DIType *BasicType = getBasicType("basic");
1310+
N->replaceVTableHolder(BasicType);
1311+
EXPECT_EQ(BasicType, N->getVTableHolder());
13071312
N->replaceVTableHolder(nullptr);
13081313
EXPECT_EQ(nullptr, N->getVTableHolder());
13091314

0 commit comments

Comments
 (0)