OSDN Git Service

dsymutil: strip unused types from imported DW_TAG_modules
authorAdrian Prantl <aprantl@apple.com>
Fri, 21 Jul 2017 02:07:33 +0000 (02:07 +0000)
committerAdrian Prantl <aprantl@apple.com>
Fri, 21 Jul 2017 02:07:33 +0000 (02:07 +0000)
This patch teaches dsymutil to strip types from the imported
DW_TAG_module inside of an object file (not inside the PCM) if they
can be resolved to the full definition inside the PCM. This reduces
the size of the .dSYM from WebCore from webkit.org by almost 2/3.

<rdar://problem/33047213>

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

test/tools/dsymutil/Inputs/modules/1.o
test/tools/dsymutil/Inputs/modules/2.o [new file with mode: 0644]
test/tools/dsymutil/X86/modules.m
tools/dsymutil/DwarfLinker.cpp

index eca930c..ef368b8 100644 (file)
Binary files a/test/tools/dsymutil/Inputs/modules/1.o and b/test/tools/dsymutil/Inputs/modules/1.o differ
diff --git a/test/tools/dsymutil/Inputs/modules/2.o b/test/tools/dsymutil/Inputs/modules/2.o
new file mode 100644 (file)
index 0000000..0a7100f
Binary files /dev/null and b/test/tools/dsymutil/Inputs/modules/2.o differ
index 046a8c1..f693ef9 100644 (file)
 EOF
    clang -D BAR_H -E -o Bar.h modules.m
    clang -D FOO_H -E -o Foo.h modules.m
-   clang -cc1 -emit-obj -fmodules -fmodule-map-file=modules.modulemap \
-     -fmodule-format=obj -g -dwarf-ext-refs -fmodules-cache-path=. \
-     -fdisable-module-hash modules.m -o 1.o
+   clang -D ODR_VIOLATION_C -E -o odr_violation.c modules.m
+   clang -c -fmodules -fmodule-map-file=modules.modulemap \
+     -g -gmodules -fmodules-cache-path=. \
+     -Xclang -fdisable-module-hash modules.m -o 1.o
+   clang -c -g odr_violation.c -o 2.o
 */
 
 // RUN: llvm-dsymutil -f -oso-prepend-path=%p/../Inputs/modules \
@@ -57,7 +59,7 @@ struct PruneMeNot;
 // CHECK: 0x0[[FOO:.*]]:  DW_TAG_module
 // CHECK-NEXT:              DW_AT_name{{.*}}"Foo"
 // CHECK-NOT:               DW_TAG
-// CHECK:                   DW_TAG_typedef
+// CHECK: 0x0[[BARTD:.*]]: DW_TAG_typedef
 // CHECK-NOT:                 DW_TAG
 // CHECK:                     DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[BAR]])
 // CHECK:                   DW_TAG_structure_type
@@ -75,19 +77,25 @@ struct S {};
 }
 @end
 
+#else
+// ---------------------------------------------------------------------
+#ifdef ODR_VIOLATION_C
+// ---------------------------------------------------------------------
+
+struct Bar {
+  int i;
+};
+typedef struct Bar Bar;
+Bar odr_violation = { 42 };
+
 // ---------------------------------------------------------------------
 #else
 // ---------------------------------------------------------------------
 
 // 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:       NULL
+// CHECK-NOT:  DW_TAG_module
+// CHECK-NOT:  DW_TAG_typedef
 //
 // CHECK:   DW_TAG_imported_declaration
 // CHECK-NOT: DW_TAG
@@ -97,6 +105,10 @@ struct S {};
 // CHECK:     DW_AT_name {{.*}}"main"
 //
 // CHECK:     DW_TAG_variable
+// CHECK-NOT:   DW_TAG
+// CHECK:       DW_AT_name{{.*}}"bar"
+// CHECK-NOT:   DW_TAG
+// CHECK:       DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[BARTD]]
 // CHECK:     DW_TAG_variable
 // CHECK-NOT:   DW_TAG
 // CHECK:       DW_AT_name{{.*}}"foo"
@@ -105,13 +117,26 @@ struct S {};
 //
 // CHECK: 0x{{0*}}[[PTR]]: DW_TAG_pointer_type
 // CHECK-NEXT   DW_AT_type [DW_FORM_ref_addr] {0x{{0*}}[[INTERFACE]])
+extern int odr_violation;
 
 @import Foo;
 int main(int argc, char **argv) {
   Bar bar;
   Foo *foo = 0;
-  bar.value = 42;
+  bar.value = odr_violation;
   return bar.value;
 }
 #endif
 #endif
+#endif
+
+// CHECK: DW_TAG_compile_unit
+// CHECK:   DW_AT_name {{.*}}"odr_violation.c"
+// CHECK: DW_TAG_variable
+// CHECK:   DW_AT_name {{.*}}"odr_violation"
+// CHECK:   DW_AT_type [DW_FORM_ref4] ({{.*}}{0x{{0*}}[[BAR2:.*]]})
+// CHECK: 0x{{0*}}[[BAR2]]: DW_TAG_typedef
+// CHECK:   DW_AT_type [DW_FORM_ref4] ({{.*}}{0x{{0*}}[[BAR3:.*]]})
+// CHECK:   DW_AT_name {{.*}}"Bar"
+// CHECK: 0x{{0*}}[[BAR3]]: DW_TAG_structure_type
+// CHECK-NEXT:   DW_AT_name {{.*}}"Bar"
index 94428bc..d82149e 100644 (file)
@@ -98,6 +98,7 @@ class DeclContext {
   uint32_t Line;
   uint32_t ByteSize;
   uint16_t Tag;
+  unsigned DefinedInClangModule : 1;
   StringRef Name;
   StringRef File;
   const DeclContext &Parent;
@@ -112,15 +113,17 @@ public:
 
   DeclContext()
       : QualifiedNameHash(0), Line(0), ByteSize(0),
-        Tag(dwarf::DW_TAG_compile_unit), Name(), File(), Parent(*this),
-        LastSeenDIE(), LastSeenCompileUnitID(0), CanonicalDIEOffset(0) {}
+        Tag(dwarf::DW_TAG_compile_unit), DefinedInClangModule(0), Name(),
+        File(), Parent(*this), LastSeenDIE(), LastSeenCompileUnitID(0),
+        CanonicalDIEOffset(0) {}
 
   DeclContext(unsigned Hash, uint32_t Line, uint32_t ByteSize, uint16_t Tag,
               StringRef Name, StringRef File, const DeclContext &Parent,
               DWARFDie LastSeenDIE = DWARFDie(), unsigned CUId = 0)
       : QualifiedNameHash(Hash), Line(Line), ByteSize(ByteSize), Tag(Tag),
-        Name(Name), File(File), Parent(Parent), LastSeenDIE(LastSeenDIE),
-        LastSeenCompileUnitID(CUId), CanonicalDIEOffset(0) {}
+        DefinedInClangModule(0), Name(Name), File(File), Parent(Parent),
+        LastSeenDIE(LastSeenDIE), LastSeenCompileUnitID(CUId),
+        CanonicalDIEOffset(0) {}
 
   uint32_t getQualifiedNameHash() const { return QualifiedNameHash; }
 
@@ -129,6 +132,9 @@ public:
   uint32_t getCanonicalDIEOffset() const { return CanonicalDIEOffset; }
   void setCanonicalDIEOffset(uint32_t Offset) { CanonicalDIEOffset = Offset; }
 
+  bool isDefinedInClangModule() const { return DefinedInClangModule; }
+  void setDefinedInClangModule(bool Val) { DefinedInClangModule = Val; }
+
   uint16_t getTag() const { return Tag; }
   StringRef getName() const { return Name; }
 };
@@ -1801,6 +1807,8 @@ static bool analyzeContextInfo(const DWARFDie &DIE,
       CurrentDeclContext = PtrInvalidPair.getPointer();
       Info.Ctxt =
           PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();
+      if (Info.Ctxt)
+        Info.Ctxt->setDefinedInClangModule(InClangModule);
     } else
       Info.Ctxt = CurrentDeclContext = nullptr;
   }
@@ -2172,7 +2180,6 @@ unsigned DwarfLinker::shouldKeepDIE(RelocationManager &RelocMgr,
     return shouldKeepVariableDIE(RelocMgr, DIE, Unit, MyInfo, Flags);
   case dwarf::DW_TAG_subprogram:
     return shouldKeepSubprogramDIE(RelocMgr, DIE, Unit, MyInfo, Flags);
-  case dwarf::DW_TAG_module:
   case dwarf::DW_TAG_imported_module:
   case dwarf::DW_TAG_imported_declaration:
   case dwarf::DW_TAG_imported_unit:
@@ -2232,6 +2239,8 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr,
             resolveDIEReference(*this, Units, Val, Unit, Die, ReferencedCU)) {
       uint32_t RefIdx = ReferencedCU->getOrigUnit().getDIEIndex(RefDIE);
       CompileUnit::DIEInfo &Info = ReferencedCU->getInfo(RefIdx);
+      bool IsModuleRef = Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset() &&
+                         Info.Ctxt->isDefinedInClangModule();
       // If the referenced DIE has a DeclContext that has already been
       // emitted, then do not keep the one in this CU. We'll link to
       // the canonical DIE in cloneDieReferenceAttribute.
@@ -2240,7 +2249,8 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr,
       // ReferencedCU->hasODR() && CU.hasODR().
       // FIXME: compatibility with dsymutil-classic. There is no
       // reason not to unique ref_addr references.
-      if (AttrSpec.Form != dwarf::DW_FORM_ref_addr && UseODR && Info.Ctxt &&
+      if (AttrSpec.Form != dwarf::DW_FORM_ref_addr && (UseODR || IsModuleRef) &&
+          Info.Ctxt &&
           Info.Ctxt != ReferencedCU->getInfo(Info.ParentIdx).Ctxt &&
           Info.Ctxt->getCanonicalDIEOffset() && isODRAttribute(AttrSpec.Attr))
         continue;