dsymutil: Prune module forward decl DIEs if a uniquable definition was
authorAdrian Prantl <aprantl@apple.com>
Tue, 10 Nov 2015 21:31:05 +0000 (21:31 +0000)
committerAdrian Prantl <aprantl@apple.com>
Tue, 10 Nov 2015 21:31:05 +0000 (21:31 +0000)
already emitted and fix a latent bug in DIECloner where the DW_CHILDREN_yes
flag is set based on the number of children in the input DIE rather than
the number of children that are actually being cloned.

rdar://problem/23439845

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

test/tools/dsymutil/X86/modules.m
test/tools/dsymutil/X86/submodules.m
tools/dsymutil/DwarfLinker.cpp

index b392c30..046a8c1 100644 (file)
@@ -58,6 +58,13 @@ struct PruneMeNot;
 // CHECK-NEXT:              DW_AT_name{{.*}}"Foo"
 // CHECK-NOT:               DW_TAG
 // CHECK:                   DW_TAG_typedef
+// CHECK-NOT:                 DW_TAG
+// CHECK:                     DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[BAR]])
+// CHECK:                   DW_TAG_structure_type
+// CHECK-NEXT:                DW_AT_name{{.*}}"S"
+// CHECK-NOT:                 DW_TAG
+// CHECK: 0x0[[INTERFACE:.*]]: DW_TAG_structure_type
+// CHECK-NEXT:                DW_AT_name{{.*}}"Foo"
 
 @import Bar;
 typedef struct Bar Bar;
@@ -72,19 +79,15 @@ struct S {};
 #else
 // ---------------------------------------------------------------------
 
-// CHECK:   DW_TAG_compile_unit
-// CHECK:     DW_TAG_module
-// CHECK-NEXT:  DW_AT_name{{.*}}"Bar"
+// CHECK:  DW_TAG_compile_unit
+// CHECK:    DW_AT_low_pc
+// CHECK-NOT:DW_TAG
 // CHECK:     DW_TAG_module
 // CHECK-NEXT:  DW_AT_name{{.*}}"Foo"
 // CHECK-NOT:   DW_TAG
 // CHECK:       DW_TAG_typedef
 // CHECK-NOT:     DW_TAG
-// CHECK:         DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[BAR]])
-// CHECK: 0x0[[INTERFACE:.*]]: DW_TAG_structure_type
-// CHECK-NOT:     DW_TAG
-// CHECK:         DW_AT_name{{.*}}"Foo"
-
+// CHECK:       NULL
 //
 // CHECK:   DW_TAG_imported_declaration
 // CHECK-NOT: DW_TAG
index 4cb5bcf..b2425a9 100644 (file)
@@ -42,8 +42,6 @@ struct PruneMeNot;
 // CHECK:            DW_TAG_compile_unit
 // CHECK:              DW_TAG_module
 // CHECK-NEXT:           DW_AT_name{{.*}}"Parent"
-// CHECK:              DW_TAG_module
-// CHECK-NEXT:           DW_AT_name{{.*}}"Child"
 // CHECK: 0x0[[EMPTY:.*]]: DW_TAG_module
 // CHECK-NEXT:             DW_AT_name{{.*}}"Empty"
 
index 0225ea6..33be88c 100644 (file)
@@ -2195,7 +2195,11 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr,
           Info.Ctxt->getCanonicalDIEOffset() && isODRAttribute(AttrSpec.Attr))
         continue;
 
-      Info.Prune = false;
+      // Keep a module forward declaration if there is no definition.
+      if (!(isODRAttribute(AttrSpec.Attr) && Info.Ctxt &&
+            Info.Ctxt->getCanonicalDIEOffset()))
+        Info.Prune = false;
+
       unsigned ODRFlag = UseODR ? TF_ODR : 0;
       lookForDIEsToKeep(RelocMgr, *RefDIE, DMO, *ReferencedCU,
                         TF_Keep | TF_DependencyWalk | ODRFlag);
@@ -2767,11 +2771,19 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
     Unit.addTypeAccelerator(Die, AttrInfo.Name, AttrInfo.NameOffset);
   }
 
+  // Determine whether there are any children that we want to keep.
+  bool HasChildren = false;
+  for (auto *Child = InputDIE.getFirstChild(); Child && !Child->isNULL();
+       Child = Child->getSibling()) {
+    unsigned Idx = U.getDIEIndex(Child);
+    if (Unit.getInfo(Idx).Keep) {
+      HasChildren = true;
+      break;
+    }
+  }
+
   DIEAbbrev NewAbbrev = Die->generateAbbrev();
-  // If a scope DIE is kept, we must have kept at least one child. If
-  // it's not the case, we'll just be emitting one wasteful end of
-  // children marker, but things won't break.
-  if (InputDIE.hasChildren())
+  if (HasChildren)
     NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
   // Assign a permanent abbrev number
   Linker.AssignAbbrev(NewAbbrev);
@@ -2780,7 +2792,7 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
   // Add the size of the abbreviation number to the output offset.
   OutOffset += getULEB128Size(Die->getAbbrevNumber());
 
-  if (!Abbrev->hasChildren()) {
+  if (!HasChildren) {
     // Update our size.
     Die->setSize(OutOffset - Die->getOffset());
     return Die;