};
//===--------------------------------------------------------------------===//
-/// \brief A signature reference to a type unit.
-class DIETypeSignature {
- const DwarfTypeUnit *Unit;
-
- DIETypeSignature() = delete;
-
-public:
- explicit DIETypeSignature(const DwarfTypeUnit &Unit) : Unit(&Unit) {}
-
- void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
- unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
- assert(Form == dwarf::DW_FORM_ref_sig8);
- return 8;
- }
-
- void print(raw_ostream &O) const;
-};
-
-//===--------------------------------------------------------------------===//
/// DIELocList - Represents a pointer to a location list in the debug_loc
/// section.
//
/// All values that aren't standard layout (or are larger than 8 bytes)
/// should be stored by reference instead of by value.
typedef AlignedCharArrayUnion<DIEInteger, DIEString, DIEExpr, DIELabel,
- DIEDelta *, DIEEntry, DIETypeSignature,
- DIEBlock *, DIELoc *, DIELocList> ValTy;
+ DIEDelta *, DIEEntry, DIEBlock *, DIELoc *,
+ DIELocList>
+ ValTy;
static_assert(sizeof(ValTy) <= sizeof(uint64_t) ||
sizeof(ValTy) <= sizeof(void *),
"Expected all large types to be stored via pointer");
HANDLE_DIEVALUE_SMALL(Label)
HANDLE_DIEVALUE_LARGE(Delta)
HANDLE_DIEVALUE_SMALL(Entry)
-HANDLE_DIEVALUE_SMALL(TypeSignature)
HANDLE_DIEVALUE_LARGE(Block)
HANDLE_DIEVALUE_LARGE(Loc)
HANDLE_DIEVALUE_SMALL(LocList)
}
//===----------------------------------------------------------------------===//
-// DIETypeSignature Implementation
-//===----------------------------------------------------------------------===//
-void DIETypeSignature::EmitValue(const AsmPrinter *Asm,
- dwarf::Form Form) const {
- assert(Form == dwarf::DW_FORM_ref_sig8);
- Asm->OutStreamer->EmitIntValue(Unit->getTypeSignature(), 8);
-}
-
-LLVM_DUMP_METHOD
-void DIETypeSignature::print(raw_ostream &O) const {
- O << format("Type Unit: 0x%lx", Unit->getTypeSignature());
-}
-
-//===----------------------------------------------------------------------===//
// DIELoc Implementation
//===----------------------------------------------------------------------===//
case DIEValue::isExpr:
case DIEValue::isLabel:
case DIEValue::isDelta:
- case DIEValue::isTypeSignature:
llvm_unreachable("Add support for additional value types.");
}
}
DwarfCompileUnit::DwarfCompileUnit(unsigned UID, const DICompileUnit *Node,
AsmPrinter *A, DwarfDebug *DW,
DwarfFile *DWU)
- : DwarfUnit(UID, dwarf::DW_TAG_compile_unit, Node, A, DW, DWU),
+ : DwarfUnit(dwarf::DW_TAG_compile_unit, Node, A, DW, DWU), UniqueID(UID),
Skeleton(nullptr), BaseAddress(nullptr) {
insertDIE(Node, &getUnitDie());
MacroLabelBegin = Asm->createTempSymbol("cu_macro_begin");
class LexicalScope;
class DwarfCompileUnit : public DwarfUnit {
+ /// A numeric ID unique among all CUs in the module
+ unsigned UniqueID;
+
+ /// Offset of the UnitDie from beginning of debug info section.
+ unsigned DebugInfoOffset = 0;
+
/// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding
/// the need to search for it in applyStmtList.
DIE::value_iterator StmtListValue;
DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, AsmPrinter *A,
DwarfDebug *DW, DwarfFile *DWU);
+ unsigned getUniqueID() const { return UniqueID; }
+ unsigned getDebugInfoOffset() const { return DebugInfoOffset; }
+ void setDebugInfoOffset(unsigned DbgInfoOff) { DebugInfoOffset = DbgInfoOff; }
+
DwarfCompileUnit *getSkeleton() const {
return Skeleton;
}
}
// Sort the CU list (again, to ensure consistent output order).
- std::sort(CUs.begin(), CUs.end(), [](const DwarfUnit *A, const DwarfUnit *B) {
- return A->getUniqueID() < B->getUniqueID();
- });
+ std::sort(CUs.begin(), CUs.end(),
+ [](const DwarfCompileUnit *A, const DwarfCompileUnit *B) {
+ return A->getUniqueID() < B->getUniqueID();
+ });
// Emit an arange table for each CU we used.
for (DwarfCompileUnit *CU : CUs) {
// DWARF5 Experimental Separate Dwarf emitters.
void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die,
- std::unique_ptr<DwarfUnit> NewU) {
+ std::unique_ptr<DwarfCompileUnit> NewU) {
NewU->addString(Die, dwarf::DW_AT_GNU_dwo_name,
U.getCUNode()->getSplitDebugFilename());
if (!TypeUnitsUnderConstruction.empty() && AddrPool.hasBeenUsed())
return;
- const DwarfTypeUnit *&TU = DwarfTypeUnits[CTy];
- if (TU) {
- CU.addDIETypeSignature(RefDie, *TU);
+ auto Ins = TypeSignatures.insert(std::make_pair(CTy, 0));
+ if (!Ins.second) {
+ CU.addDIETypeSignature(RefDie, Ins.first->second);
return;
}
bool TopLevelType = TypeUnitsUnderConstruction.empty();
AddrPool.resetUsedFlag();
- auto OwnedUnit = make_unique<DwarfTypeUnit>(
- InfoHolder.getUnits().size() + TypeUnitsUnderConstruction.size(), CU, Asm,
- this, &InfoHolder, getDwoLineTable(CU));
+ auto OwnedUnit = make_unique<DwarfTypeUnit>(CU, Asm, this, &InfoHolder,
+ getDwoLineTable(CU));
DwarfTypeUnit &NewTU = *OwnedUnit;
DIE &UnitDie = NewTU.getUnitDie();
- TU = &NewTU;
TypeUnitsUnderConstruction.push_back(
std::make_pair(std::move(OwnedUnit), CTy));
uint64_t Signature = makeTypeSignature(Identifier);
NewTU.setTypeSignature(Signature);
+ Ins.first->second = Signature;
if (useSplitDwarf())
NewTU.initSection(Asm->getObjFileLowering().getDwarfTypesDWOSection());
// This is pessimistic as some of these types might not be dependent on
// the type that used an address.
for (const auto &TU : TypeUnitsToAdd)
- DwarfTypeUnits.erase(TU.second);
+ TypeSignatures.erase(TU.second);
// Construct this type in the CU directly.
// This is inefficient because all the dependent types will be rebuilt
// If the type wasn't dependent on fission addresses, finish adding the type
// and all its dependent types.
- for (auto &TU : TypeUnitsToAdd)
- InfoHolder.addUnit(std::move(TU.first));
+ for (auto &TU : TypeUnitsToAdd) {
+ InfoHolder.computeSizeAndOffsetsForUnit(TU.first.get());
+ InfoHolder.emitUnit(TU.first.get(), useSplitDwarf());
+ }
}
- CU.addDIETypeSignature(RefDie, NewTU);
+ CU.addDIETypeSignature(RefDie, Signature);
}
// Accelerator table mutators - add each name along with its companion
/// Holders for the various debug information flags that we might need to
/// have exposed. See accessor functions below for description.
- /// Map from MDNodes for user-defined types to the type units that
- /// describe them.
- DenseMap<const MDNode *, const DwarfTypeUnit *> DwarfTypeUnits;
+ /// Map from MDNodes for user-defined types to their type signatures. Also
+ /// used to keep track of which types we have emitted type units for.
+ DenseMap<const MDNode *, uint64_t> TypeSignatures;
SmallVector<
std::pair<std::unique_ptr<DwarfTypeUnit>, const DICompositeType *>, 1>
MCDwarfDwoLineTable *getDwoLineTable(const DwarfCompileUnit &);
- const SmallVectorImpl<std::unique_ptr<DwarfUnit>> &getUnits() {
+ const SmallVectorImpl<std::unique_ptr<DwarfCompileUnit>> &getUnits() {
return InfoHolder.getUnits();
}
/// Initialize common features of skeleton units.
void initSkeletonUnit(const DwarfUnit &U, DIE &Die,
- std::unique_ptr<DwarfUnit> NewU);
+ std::unique_ptr<DwarfCompileUnit> NewU);
/// Construct the split debug info compile unit for the debug info
/// section.
//===----------------------------------------------------------------------===//
#include "DwarfFile.h"
+#include "DwarfCompileUnit.h"
#include "DwarfDebug.h"
#include "DwarfUnit.h"
#include "llvm/ADT/STLExtras.h"
return *New;
}
-void DwarfFile::addUnit(std::unique_ptr<DwarfUnit> U) {
+void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) {
CUs.push_back(std::move(U));
}
// Emit the various dwarf units to the unit section USection with
// the abbreviations going into ASection.
void DwarfFile::emitUnits(bool UseOffsets) {
- for (const auto &TheU : CUs) {
- DIE &Die = TheU->getUnitDie();
- MCSection *USection = TheU->getSection();
- Asm->OutStreamer->SwitchSection(USection);
+ for (const auto &TheU : CUs)
+ emitUnit(TheU.get(), UseOffsets);
+}
- TheU->emitHeader(UseOffsets);
+void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) {
+ DIE &Die = TheU->getUnitDie();
+ MCSection *USection = TheU->getSection();
+ Asm->OutStreamer->SwitchSection(USection);
- Asm->emitDwarfDIE(Die);
- }
+ TheU->emitHeader(UseOffsets);
+
+ Asm->emitDwarfDIE(Die);
}
// Compute the size and offset for each DIE.
// DIE within each compile unit. All offsets are CU relative.
for (const auto &TheU : CUs) {
TheU->setDebugInfoOffset(SecOffset);
+ SecOffset += computeSizeAndOffsetsForUnit(TheU.get());
+ }
+}
- // CU-relative offset is reset to 0 here.
- unsigned Offset = sizeof(int32_t) + // Length of Unit Info
- TheU->getHeaderSize(); // Unit-specific headers
+unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit *TheU) {
+ // CU-relative offset is reset to 0 here.
+ unsigned Offset = sizeof(int32_t) + // Length of Unit Info
+ TheU->getHeaderSize(); // Unit-specific headers
- // EndOffset here is CU-relative, after laying out
- // all of the CU DIE.
- unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset);
- SecOffset += EndOffset;
- }
+ // The return value here is CU-relative, after laying out
+ // all of the CU DIE.
+ return computeSizeAndOffset(TheU->getUnitDie(), Offset);
}
+
// Compute the size and offset of a DIE. The offset is relative to start of the
// CU. It returns the offset after laying out the DIE.
unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
namespace llvm {
class AsmPrinter;
class DbgVariable;
+class DwarfCompileUnit;
class DwarfUnit;
class DIEAbbrev;
class MCSymbol;
std::vector<DIEAbbrev *> Abbreviations;
// A pointer to all units in the section.
- SmallVector<std::unique_ptr<DwarfUnit>, 1> CUs;
+ SmallVector<std::unique_ptr<DwarfCompileUnit>, 1> CUs;
DwarfStringPool StrPool;
~DwarfFile();
- const SmallVectorImpl<std::unique_ptr<DwarfUnit>> &getUnits() { return CUs; }
+ const SmallVectorImpl<std::unique_ptr<DwarfCompileUnit>> &getUnits() {
+ return CUs;
+ }
/// \brief Compute the size and offset of a DIE given an incoming Offset.
unsigned computeSizeAndOffset(DIE &Die, unsigned Offset);
/// \brief Compute the size and offset of all the DIEs.
void computeSizeAndOffsets();
+ /// \brief Compute the size and offset of all the DIEs in the given unit.
+ /// \returns The size of the root DIE.
+ unsigned computeSizeAndOffsetsForUnit(DwarfUnit *TheU);
+
/// Define a unique number for the abbreviation.
///
/// Compute the abbreviation for \c Die, look up its unique number, and
DIEAbbrev &assignAbbrevNumber(DIE &Die);
/// \brief Add a unit to the list of CUs.
- void addUnit(std::unique_ptr<DwarfUnit> U);
+ void addUnit(std::unique_ptr<DwarfCompileUnit> U);
/// \brief Emit all of the units to the section listed with the given
/// abbreviation section.
void emitUnits(bool UseOffsets);
+ /// \brief Emit the given unit to its section.
+ void emitUnit(DwarfUnit *U, bool UseOffsets);
+
/// \brief Emit a set of abbreviations to the specific section.
void emitAbbrevs(MCSection *);
return MachineReg == TRI.getFrameRegister(*AP.MF);
}
-DwarfUnit::DwarfUnit(unsigned UID, dwarf::Tag UnitTag,
- const DICompileUnit *Node, AsmPrinter *A, DwarfDebug *DW,
- DwarfFile *DWU)
- : UniqueID(UID), CUNode(Node),
- UnitDie(*DIE::get(DIEValueAllocator, UnitTag)), DebugInfoOffset(0),
- Asm(A), DD(DW), DU(DWU), IndexTyDie(nullptr), Section(nullptr) {
+DwarfUnit::DwarfUnit(dwarf::Tag UnitTag, const DICompileUnit *Node,
+ AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU)
+ : CUNode(Node), UnitDie(*DIE::get(DIEValueAllocator, UnitTag)), Asm(A),
+ DD(DW), DU(DWU), IndexTyDie(nullptr), Section(nullptr) {
assert(UnitTag == dwarf::DW_TAG_compile_unit ||
UnitTag == dwarf::DW_TAG_type_unit);
}
-DwarfTypeUnit::DwarfTypeUnit(unsigned UID, DwarfCompileUnit &CU, AsmPrinter *A,
+DwarfTypeUnit::DwarfTypeUnit(DwarfCompileUnit &CU, AsmPrinter *A,
DwarfDebug *DW, DwarfFile *DWU,
MCDwarfDwoLineTable *SplitLineTable)
- : DwarfUnit(UID, dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU),
- CU(CU), SplitLineTable(SplitLineTable) {
+ : DwarfUnit(dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU), CU(CU),
+ SplitLineTable(SplitLineTable) {
if (SplitLineTable)
addSectionOffset(UnitDie, dwarf::DW_AT_stmt_list, 0);
}
addDIEEntry(Die, Attribute, DIEEntry(Entry));
}
-void DwarfUnit::addDIETypeSignature(DIE &Die, const DwarfTypeUnit &Type) {
+void DwarfUnit::addDIETypeSignature(DIE &Die, uint64_t Signature) {
// Flag the type unit reference as a declaration so that if it contains
// members (implicit special members, static data member definitions, member
// declarations for definitions in this CU, etc) consumers don't get confused
addFlag(Die, dwarf::DW_AT_declaration);
Die.addValue(DIEValueAllocator, dwarf::DW_AT_signature,
- dwarf::DW_FORM_ref_sig8, DIETypeSignature(Type));
+ dwarf::DW_FORM_ref_sig8, DIEInteger(Signature));
}
void DwarfUnit::addDIETypeSignature(DIE &Die, dwarf::Attribute Attribute,
// start of the section. Use a relocatable offset where needed to ensure
// linking doesn't invalidate that offset.
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
- Asm->emitDwarfSymbolReference(TLOF.getDwarfAbbrevSection()->getBeginSymbol(),
- UseOffsets);
+ if (UseOffsets)
+ Asm->EmitInt32(0);
+ else
+ Asm->emitDwarfSymbolReference(
+ TLOF.getDwarfAbbrevSection()->getBeginSymbol(), false);
Asm->OutStreamer->AddComment("Address Size (in bytes)");
Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
/// source file.
class DwarfUnit {
protected:
- /// A numeric ID unique among all CUs in the module
- unsigned UniqueID;
-
/// MDNode for the compile unit.
const DICompileUnit *CUNode;
/// Unit debug information entry.
DIE &UnitDie;
- /// Offset of the UnitDie from beginning of debug info section.
- unsigned DebugInfoOffset;
-
/// Target of Dwarf emission.
AsmPrinter *Asm;
/// The section this unit will be emitted in.
MCSection *Section;
- DwarfUnit(unsigned UID, dwarf::Tag, const DICompileUnit *CU, AsmPrinter *A,
- DwarfDebug *DW, DwarfFile *DWU);
+ DwarfUnit(dwarf::Tag, const DICompileUnit *CU, AsmPrinter *A, DwarfDebug *DW,
+ DwarfFile *DWU);
bool applySubprogramDefinitionAttributes(const DISubprogram *SP, DIE &SPDie);
// Accessors.
AsmPrinter* getAsmPrinter() const { return Asm; }
- unsigned getUniqueID() const { return UniqueID; }
uint16_t getLanguage() const { return CUNode->getSourceLanguage(); }
const DICompileUnit *getCUNode() const { return CUNode; }
DIE &getUnitDie() { return UnitDie; }
- unsigned getDebugInfoOffset() const { return DebugInfoOffset; }
- void setDebugInfoOffset(unsigned DbgInfoOff) { DebugInfoOffset = DbgInfoOff; }
-
/// Return true if this compile unit has something to write out.
bool hasContent() const { return UnitDie.hasChildren(); }
void addDIEEntry(DIE &Die, dwarf::Attribute Attribute, DIEEntry Entry);
/// Add a type's DW_AT_signature and set the declaration flag.
- void addDIETypeSignature(DIE &Die, const DwarfTypeUnit &Type);
+ void addDIETypeSignature(DIE &Die, uint64_t Signature);
/// Add an attribute containing the type signature for a unique identifier.
void addDIETypeSignature(DIE &Die, dwarf::Attribute Attribute,
StringRef Identifier);
bool isDwoUnit() const override;
public:
- DwarfTypeUnit(unsigned UID, DwarfCompileUnit &CU, AsmPrinter *A,
- DwarfDebug *DW, DwarfFile *DWU,
- MCDwarfDwoLineTable *SplitLineTable = nullptr);
+ DwarfTypeUnit(DwarfCompileUnit &CU, AsmPrinter *A, DwarfDebug *DW,
+ DwarfFile *DWU, MCDwarfDwoLineTable *SplitLineTable = nullptr);
void setTypeSignature(uint64_t Signature) { TypeSignature = Signature; }
- uint64_t getTypeSignature() const { return TypeSignature; }
void setType(const DIE *Ty) { this->Ty = Ty; }
/// Emit the header for this unit, not including the initial length field.