]> granicus.if.org Git - llvm/commitdiff
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 eca930c905c47c7dd176d4cd9d1c558858739577..ef368b85d8fcaddfc27d8cdcfea2dc86bc134b20 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 046a8c1304a0d6e2e02bf15f666084a408690ba6..f693ef9019b5ccd981703ea32011a9ad7e87e2ad 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 94428bcab516307cce389540235a32075312181d..d82149e50b456e34b0cda310deb3b5a82ee24b8b 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;