From b29f9e5c41ba6167b32091d818097d1e4f3a3af1 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Tue, 10 Nov 2015 21:31:05 +0000 Subject: [PATCH] dsymutil: Prune module forward decl DIEs if a uniquable definition was 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 | 19 +++++++++++-------- test/tools/dsymutil/X86/submodules.m | 2 -- tools/dsymutil/DwarfLinker.cpp | 24 ++++++++++++++++++------ 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/test/tools/dsymutil/X86/modules.m b/test/tools/dsymutil/X86/modules.m index b392c30d062..046a8c1304a 100644 --- a/test/tools/dsymutil/X86/modules.m +++ b/test/tools/dsymutil/X86/modules.m @@ -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 diff --git a/test/tools/dsymutil/X86/submodules.m b/test/tools/dsymutil/X86/submodules.m index 4cb5bcfaee2..b2425a91cbd 100644 --- a/test/tools/dsymutil/X86/submodules.m +++ b/test/tools/dsymutil/X86/submodules.m @@ -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" diff --git a/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp index 0225ea692ca..33be88c09c2 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/tools/dsymutil/DwarfLinker.cpp @@ -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; -- 2.34.1