DebugInfo: Fix ordering of members after r191928
authorDavid Blaikie <dblaikie@gmail.com>
Fri, 4 Oct 2013 01:39:59 +0000 (01:39 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Fri, 4 Oct 2013 01:39:59 +0000 (01:39 +0000)
In the case (shown in the attached test) where a member function
definition was emitted into debug info the following could occur:

1) build the debug info for the member function definition
2) in (1), build the debug info for the member function declaration
3) construct and add the member function declaration DIE
4) add it to its context
5) build its context (the type it is a member of)
6) construct the members and add them to the type
7) except don't add member functions because "getOrCreateSubprogram"
adds the function to its parent anyway
8) except we're only partway through building this subprogram
declaration so it hasn't been added yet - but we returned the partially
constructed DIE (since it's already in the MDNode->DIE mapping to avoid
infinitely recursing trying to create the member function DIE)
9) once the type is constructed, add the member function to it
10) now the members are out of order (the member function being defined
is listed as the last member, even though it was declared as the first)

To avoid this, construct the context of the subprogram DIE before we
query to see if it exists. That way we never end up creating it before
creating its context and ending up in this situation.

Alternatively, the type construction that visits/builds all the members
could call something like getOrCreateSubprogram, but that doesn't ever
do the "add to context" step. Then the type building code would always
be responsible for adding members (and the subprogram "addToContextDIE"
would no-op because the context building would have added the subprogram
declaration to the type/context DIE already).

(the test cases updated were overly-sensitive to offsets or abbreviation
numbers. We don't have a nice way to make these tests more robust as yet
- multiline FileCheck matches would be required)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191939 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
test/DebugInfo/X86/DW_AT_specification.ll
test/DebugInfo/X86/concrete_out_of_line.ll
test/DebugInfo/X86/pr11300.ll
test/DebugInfo/member-order.ll [new file with mode: 0644]

index c6bd7abebd3dd1842adaa9af0aca9669e3672f3b..95d97c66175a27c8558fa16378c70b72cc435a64 100644 (file)
@@ -1311,6 +1311,13 @@ DIE *CompileUnit::getOrCreateNameSpace(DINameSpace NS) {
 
 /// getOrCreateSubprogramDIE - Create new DIE using SP.
 DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
+  // Construct the context before querying for the existence of the DIE in case
+  // such construction creates the DIE (as is the case for member function
+  // declarations).
+  DIE *ContextDIE = getOrCreateContextDIE(SP.getContext());
+  if (!ContextDIE)
+    ContextDIE = CUDie.get();
+
   DIE *SPDie = DD->getSPDIE(SP);
   if (SPDie)
     return SPDie;
@@ -1327,7 +1334,7 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
   }
 
   // Add to context owner.
-  addToContextOwner(SPDie, SP.getContext());
+  ContextDIE->addChild(SPDie);
 
   // Add function template parameters.
   addTemplateParams(*SPDie, SP.getTemplateParams());
index f90d0fbf6ef1fbd215fae6e594438fae797e5f1e..4d630b16771bfecf389e59d4595746e0471a04c7 100644 (file)
@@ -3,8 +3,8 @@
 
 ; test that the DW_AT_specification is a back edge in the file.
 
-; CHECK: 0x0000003a: DW_TAG_subprogram [5] *
-; CHECK: DW_AT_specification [DW_FORM_ref4]      (cu + 0x003a => {0x0000003a})
+; CHECK: 0x0000[[OFFSET:[0-9a-f]*]]: DW_TAG_subprogram [5] *
+; CHECK: DW_AT_specification [DW_FORM_ref4]      (cu + 0x[[OFFSET]] => {0x0000[[OFFSET]]})
 
 
 @_ZZN3foo3barEvE1x = constant i32 0, align 4
index a7f785d8c158683346dd5eee05cc04b6731ea555..e3a25894c9ea25ca8bc9d78b5c3b626abc43a23d 100644 (file)
@@ -7,14 +7,14 @@
 ; first check that we have a TAG_subprogram at a given offset and it has
 ; AT_inline.
 
-; CHECK: 0x0000011e:   DW_TAG_subprogram [18]
+; CHECK: 0x0000011e:   DW_TAG_subprogram [17]
 ; CHECK-NEXT:     DW_AT_specification
 ; CHECK-NEXT:     DW_AT_inline
 
 
 ; and then that a TAG_subprogram refers to it with AT_abstract_origin.
 
-; CHECK: 0x0000015f:   DW_TAG_subprogram [20]
+; CHECK: 0x0000015f:   DW_TAG_subprogram [19]
 ; CHECK-NEXT: DW_AT_abstract_origin [DW_FORM_ref4]    (cu + 0x011e => {0x0000011e})
 
 define i32 @_ZN17nsAutoRefCnt7ReleaseEv() {
index 423a5e7e2f81112f4296afd1570251e2e499c927..cdd5a743d3036c8650ff38abb8b47cb3b75a7cbc 100644 (file)
@@ -3,7 +3,7 @@
 
 ; test that the DW_AT_specification is a back edge in the file.
 
-; CHECK: [[BACK:0x[0-9a-f]*]]:     DW_TAG_subprogram [5]
+; CHECK: [[BACK:0x[0-9a-f]*]]:     DW_TAG_subprogram [6]
 ; CHECK:                 DW_AT_specification [DW_FORM_ref4]      (cu + {{.*}} => {[[BACK]]})
 
 %struct.foo = type { i8 }
diff --git a/test/DebugInfo/member-order.ll b/test/DebugInfo/member-order.ll
new file mode 100644 (file)
index 0000000..b751fff
--- /dev/null
@@ -0,0 +1,65 @@
+; REQUIRES: object-emission
+
+; RUN: llc -filetype=obj -O0 < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s
+
+; generated by clang from:
+; struct foo {
+;   void f1();
+;   void f2();
+; };
+;
+; void foo::f1() {
+; }
+
+; CHECK: DW_TAG_structure_type
+; CHECK-NEXT: DW_AT_name {{.*}} "foo"
+; CHECK-NOT: NULL
+; CHECK: DW_TAG_subprogram
+; CHECK-NOT: NULL
+; CHECK: DW_AT_name {{.*}} "f1"
+; CHECK: DW_TAG_subprogram
+; CHECK-NOT: NULL
+; CHECK: DW_AT_name {{.*}} "f2"
+
+
+%struct.foo = type { i8 }
+
+; Function Attrs: nounwind uwtable
+define void @_ZN3foo2f1Ev(%struct.foo* %this) #0 align 2 {
+entry:
+  %this.addr = alloca %struct.foo*, align 8
+  store %struct.foo* %this, %struct.foo** %this.addr, align 8
+  call void @llvm.dbg.declare(metadata !{%struct.foo** %this.addr}, metadata !16), !dbg !18
+  %this1 = load %struct.foo** %this.addr
+  ret void, !dbg !19
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata) #1
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!15}
+
+!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.4 ", i1 false, metadata !"", i32 0, metadata !2, metadata !3, metadata !13, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/tmp/dbginfo/member-order.cpp] [DW_LANG_C_plus_plus]
+!1 = metadata !{metadata !"member-order.cpp", metadata !"/tmp/dbginfo"}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{i32 786451, metadata !1, null, metadata !"foo", i32 1, i64 8, i64 8, i32 0, i32 0, null, metadata !5, i32 0, null, null, metadata !"_ZTS3foo"} ; [ DW_TAG_structure_type ] [foo] [line 1, size 8, align 8, offset 0] [def] [from ]
+!5 = metadata !{metadata !6, metadata !11}
+!6 = metadata !{i32 786478, metadata !1, metadata !4, metadata !"f1", metadata !"f1", metadata !"_ZN3foo2f1Ev", i32 2, metadata !7, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 false, null, null, i32 0, metadata !10, i32 2} ; [ DW_TAG_subprogram ] [line 2] [f1]
+!7 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!8 = metadata !{null, metadata !9}
+!9 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 1088, metadata !"_ZTS3foo"} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [artificial] [from _ZTS3foo]
+!10 = metadata !{i32 786468}
+!11 = metadata !{i32 786478, metadata !1, metadata !4, metadata !"f2", metadata !"f2", metadata !"_ZN3foo2f2Ev", i32 3, metadata !7, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 false, null, null, i32 0, metadata !12, i32 3} ; [ DW_TAG_subprogram ] [line 3] [f2]
+!12 = metadata !{i32 786468}
+!13 = metadata !{metadata !14}
+!14 = metadata !{i32 786478, metadata !1, null, metadata !"f1", metadata !"f1", metadata !"_ZN3foo2f1Ev", i32 6, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (%struct.foo*)* @_ZN3foo2f1Ev, null, metadata !6, metadata !2, i32 6} ; [ DW_TAG_subprogram ] [line 6] [def] [f1]
+!15 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
+!16 = metadata !{i32 786689, metadata !14, metadata !"this", null, i32 16777216, metadata !17, i32 1088, i32 0} ; [ DW_TAG_arg_variable ] [this] [line 0]
+!17 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !"_ZTS3foo"} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from _ZTS3foo]
+!18 = metadata !{i32 0, i32 0, metadata !14, null}
+!19 = metadata !{i32 7, i32 0, metadata !14, null}