From d7f88bede7e3f059afaac8897f6e54fd80b7d8e3 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Wed, 24 Apr 2019 18:09:44 +0000 Subject: [PATCH] DebugInfo: Emit only declarations (not whole definitions) of non-unit user defined types into type units While this doesn't come up in reasonable cases currently (the only user defined types not in type units are ones without linkage - which makes for near-ODR violations, because it'd be a type with linkage referencing a type without linkage - such a type can't be validly defined in more than one TU, so arguably it shouldn't be in a type unit to begin with - but it's a convenient way to demonstrate an issue that will become more revalent with homed modular debug info type definitions - which also don't need to be in type units but more legitimately so). Precursor to the Clang change to de-type-unit (by omitting the 'identifier') types homed due to strong linkage vtables. (making that change without this one would lead to major type duplication in type units) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359122 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 4 ++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 2 + lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 16 ++++++ lib/CodeGen/AsmPrinter/DwarfDebug.h | 13 +++++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 22 +++++-- lib/CodeGen/AsmPrinter/DwarfUnit.h | 19 ++++--- test/DebugInfo/X86/tu-to-non-tu.ll | 63 +++++++++++++++++++++ 7 files changed, 126 insertions(+), 13 deletions(-) create mode 100644 test/DebugInfo/X86/tu-to-non-tu.ll diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 0a06dfdae06..d6e8ae1590a 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -1201,6 +1201,10 @@ bool DwarfCompileUnit::isDwoUnit() const { return DD->useSplitDwarf() && Skeleton; } +void DwarfCompileUnit::finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) { + constructTypeDIE(D, CTy); +} + bool DwarfCompileUnit::includeMinimalInlineScopes() const { return getCUNode()->getEmissionKind() == DICompileUnit::LineTablesOnly || (DD->useSplitDwarf() && !Skeleton); diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 4d66447ec3a..ea980dfda17 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -100,6 +100,8 @@ class DwarfCompileUnit final : public DwarfUnit { return DU->getAbstractEntities(); } + void finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) override; + public: DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 816dd5b66e1..e31b1e5c3ad 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -2749,6 +2749,22 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, CU.addDIETypeSignature(RefDie, Signature); } +DwarfDebug::NonTypeUnitContext::NonTypeUnitContext(DwarfDebug *DD) + : DD(DD), + TypeUnitsUnderConstruction(std::move(DD->TypeUnitsUnderConstruction)) { + DD->TypeUnitsUnderConstruction.clear(); + assert(TypeUnitsUnderConstruction.empty() || !DD->AddrPool.hasBeenUsed()); +} + +DwarfDebug::NonTypeUnitContext::~NonTypeUnitContext() { + DD->TypeUnitsUnderConstruction = std::move(TypeUnitsUnderConstruction); + DD->AddrPool.resetUsedFlag(); +} + +DwarfDebug::NonTypeUnitContext DwarfDebug::enterNonTypeUnitContext() { + return NonTypeUnitContext(this); +} + // Add the Name along with its companion DIE to the appropriate accelerator // table (for AccelTableKind::Dwarf it's always AccelDebugNames, for // AccelTableKind::Apple, we use the table we got as an argument). If diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index a8cadaa60eb..2c2e6bf54c3 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -606,6 +606,19 @@ public: void addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier, DIE &Die, const DICompositeType *CTy); + friend class NonTypeUnitContext; + class NonTypeUnitContext { + DwarfDebug *DD; + decltype(DwarfDebug::TypeUnitsUnderConstruction) TypeUnitsUnderConstruction; + friend class DwarfDebug; + NonTypeUnitContext(DwarfDebug *DD); + public: + NonTypeUnitContext(NonTypeUnitContext&&) = default; + ~NonTypeUnitContext(); + }; + + NonTypeUnitContext enterNonTypeUnitContext(); + /// Add a label so that arange data can be generated for it. void addArangeLabel(SymbolCU SCU) { ArangeLabels.push_back(SCU); } diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index b14eadd2559..cace8f06992 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -608,7 +608,7 @@ DIE *DwarfUnit::getOrCreateContextDIE(const DIScope *Context) { return getDIE(Context); } -DIE *DwarfTypeUnit::createTypeDIE(const DICompositeType *Ty) { +DIE *DwarfUnit::createTypeDIE(const DICompositeType *Ty) { auto *Context = resolve(Ty->getScope()); DIE *ContextDIE = getOrCreateContextDIE(Context); @@ -636,12 +636,16 @@ DIE *DwarfUnit::createTypeDIE(const DIScope *Context, DIE &ContextDIE, else if (auto *STy = dyn_cast(Ty)) constructTypeDIE(TyDIE, STy); else if (auto *CTy = dyn_cast(Ty)) { - if (DD->generateTypeUnits() && !Ty->isForwardDecl()) - if (MDString *TypeId = CTy->getRawIdentifier()) { + if (DD->generateTypeUnits() && !Ty->isForwardDecl()) { + // Skip updating the accelerator tables since this is not the full type. + if (MDString *TypeId = CTy->getRawIdentifier()) DD->addDwarfTypeUnitType(getCU(), TypeId->getString(), TyDIE, CTy); - // Skip updating the accelerator tables since this is not the full type. - return &TyDIE; + else { + auto X = DD->enterNonTypeUnitContext(); + finishNonUnitTypeDIE(TyDIE, CTy); } + return &TyDIE; + } constructTypeDIE(TyDIE, CTy); } else { constructTypeDIE(TyDIE, cast(Ty)); @@ -1689,3 +1693,11 @@ void DwarfUnit::addLoclistsBase() { DU->getLoclistsTableBaseSym(), TLOF.getDwarfLoclistsSection()->getBeginSymbol()); } + +void DwarfTypeUnit::finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) { + addFlag(D, dwarf::DW_AT_declaration); + StringRef Name = CTy->getName(); + if (!Name.empty()) + addString(D, dwarf::DW_AT_name, Name); + getCU().createTypeDIE(CTy); +} diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.h b/lib/CodeGen/AsmPrinter/DwarfUnit.h index f19f6d035e0..14a1373aee4 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -298,6 +298,9 @@ public: /// allocated in the MCContext. Optional getMD5AsBytes(const DIFile *File) const; + /// Get context owner's DIE. + DIE *createTypeDIE(const DICompositeType *Ty); + protected: ~DwarfUnit(); @@ -314,11 +317,6 @@ protected: return Ref.resolve(); } - /// If this is a named finished type then include it in the list of types for - /// the accelerator tables. - void updateAcceleratorTables(const DIScope *Context, const DIType *Ty, - const DIE &TyDIE); - /// Emit the common part of the header for this unit. void emitCommonHeader(bool UseOffsets, dwarf::UnitType UT); @@ -346,6 +344,13 @@ private: /// Set D as anonymous type for index which can be reused later. void setIndexTyDie(DIE *D) { IndexTyDie = D; } + virtual void finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) = 0; + + /// If this is a named finished type then include it in the list of types for + /// the accelerator tables. + void updateAcceleratorTables(const DIScope *Context, const DIType *Ty, + const DIE &TyDIE); + virtual bool isDwoUnit() const = 0; const MCSymbol *getCrossSectionRelativeBaseAddress() const override; }; @@ -358,6 +363,7 @@ class DwarfTypeUnit final : public DwarfUnit { bool UsedLineTable = false; unsigned getOrCreateSourceID(const DIFile *File) override; + void finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) override; bool isDwoUnit() const override; public: @@ -367,9 +373,6 @@ public: void setTypeSignature(uint64_t Signature) { TypeSignature = Signature; } void setType(const DIE *Ty) { this->Ty = Ty; } - /// Get context owner's DIE. - DIE *createTypeDIE(const DICompositeType *Ty); - /// Emit the header for this unit, not including the initial length field. void emitHeader(bool UseOffsets) override; unsigned getHeaderSize() const override { diff --git a/test/DebugInfo/X86/tu-to-non-tu.ll b/test/DebugInfo/X86/tu-to-non-tu.ll new file mode 100644 index 00000000000..67d0fab26f0 --- /dev/null +++ b/test/DebugInfo/X86/tu-to-non-tu.ll @@ -0,0 +1,63 @@ +; REQUIRES: object-emission + +; RUN: llc -filetype=obj -O0 -generate-type-units -mtriple=x86_64-unknown-linux-gnu < %s \ +; RUN: | llvm-dwarfdump -debug-info -debug-types - | FileCheck %s + +; Test that a type unit referencing a non-type unit (in this case, it's +; bordering on an ODR violation - a type with linkage references a type without +; linkage, so there's no way for the first type to be defined in more than one +; translation unit, so there's no need for it to be in a type unit - but this +; is quirky/rare and an easy way to test a broader issue). The type unit should +; not end up with a whole definition of the referenced type - instead it should +; have a declaration of the type, while the definition remains in the primary +; CU. +; (again, arguably in this instance - since the type is only referenced once, it +; could go in the TU only - but that requires tracking usage & then deciding +; where to put types, which isn't worthwhile right now) + +; CHECK: Type Unit: + +; CHECK: DW_TAG_structure_type +; CHECK-NEXT: DW_AT_name {{.*}}"bar" + +; CHECK: DW_TAG_namespace +; CHECK-NOT: {{DW_AT_name|DW_TAG}} +; CHECK: DW_TAG_structure_type +; CHECK-NEXT: DW_AT_declaration +; CHECK-NEXT: DW_AT_name {{.*}}"foo" + +; CHECK: Compile Unit: + +; CHECK: DW_TAG_structure_type +; CHECK-NEXT: DW_AT_declaration +; CHECK-NEXT: DW_AT_signature + +; CHECK: DW_TAG_namespace +; CHECK-NOT: {{DW_AT_name|DW_TAG}} +; CHECK: DW_TAG_structure_type +; CHECK-NEXT: DW_AT_name {{.*}}"foo" +; CHECK-NEXT: DW_AT_byte_size + +%struct.bar = type { %"struct.(anonymous namespace)::foo" } +%"struct.(anonymous namespace)::foo" = type { i8 } + +@b = global %struct.bar zeroinitializer, align 1, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!11, !13} +!llvm.ident = !{!12} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 8, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 5.0.0 (trunk 294954) (llvm/trunk 294959)", isOptimized: false, runtimeVersion: 0, splitDebugFilename: "tu-to-non-tu.dwo", emissionKind: FullDebug, enums: !4, globals: !5) +!3 = !DIFile(filename: "tu.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch") +!4 = !{} +!5 = !{!0} +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "bar", file: !3, line: 5, size: 8, elements: !7, identifier: "_ZTS3bar") +!7 = !{!8} +!8 = !DIDerivedType(tag: DW_TAG_member, name: "f", scope: !6, file: !3, line: 6, baseType: !9, size: 8) +!9 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", scope: !10, file: !3, line: 2, size: 8, elements: !4) +!10 = !DINamespace(scope: null) +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{!"clang version 5.0.0 (trunk 294954) (llvm/trunk 294959)"} +!13 = !{i32 2, !"Dwarf Version", i32 5} -- 2.50.1