/// CompileUnit - Compile unit constructor.
CompileUnit::CompileUnit(unsigned UID, DIE *D, DICompileUnit Node,
AsmPrinter *A, DwarfDebug *DW, DwarfUnits *DWU)
- : UniqueID(UID), Node(Node), CUDie(D), Asm(A), DD(DW), DU(DWU),
- IndexTyDie(0), Language(Node.getLanguage()) {
+ : UniqueID(UID), Node(Node), Language(Node.getLanguage()), CUDie(D),
+ DebugInfoOffset(0), Asm(A), DD(DW), DU(DWU), IndexTyDie(0) {
DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1);
insertDIE(Node, D);
}
CompileUnit::CompileUnit(unsigned UID, DIE *D, uint16_t Language, AsmPrinter *A,
DwarfDebug *DD, DwarfUnits *DU)
- : UniqueID(UID), Node(NULL), CUDie(D), Asm(A), DD(DD), DU(DU),
- IndexTyDie(0), Language(Language) {
+ : UniqueID(UID), Node(NULL), Language(Language), CUDie(D),
+ DebugInfoOffset(0), Asm(A), DD(DD), DU(DU), IndexTyDie(0) {
DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1);
}
/// Check whether the DIE for this MDNode can be shared across CUs.
static bool isShareableAcrossCUs(DIDescriptor D) {
- // When the MDNode can be part of the type system, the DIE can be
- // shared across CUs.
+ // When the MDNode can be part of the type system, the DIE can be shared
+ // across CUs.
+ // Combining type units and cross-CU DIE sharing is lower value (since
+ // cross-CU DIE sharing is used in LTO and removes type redundancy at that
+ // level already) but may be implementable for some value in projects
+ // building multiple independent libraries with LTO and then linking those
+ // together.
return (D.isType() ||
(D.isSubprogram() && !DISubprogram(D).isDefinition())) &&
!GenerateTypeUnits;
addLabel(Die, (dwarf::Attribute)0, Form, Label);
}
+/// addSectionLabel - Add a Dwarf section label attribute data and value.
+///
+void CompileUnit::addSectionLabel(DIE *Die, dwarf::Attribute Attribute,
+ const MCSymbol *Label) {
+ if (DD->getDwarfVersion() >= 4)
+ addLabel(Die, Attribute, dwarf::DW_FORM_sec_offset, Label);
+ else
+ addLabel(Die, Attribute, dwarf::DW_FORM_data4, Label);
+}
+
+/// addSectionOffset - Add an offset into a section attribute data and value.
+///
+void CompileUnit::addSectionOffset(DIE *Die, dwarf::Attribute Attribute,
+ uint64_t Integer) {
+ if (DD->getDwarfVersion() >= 4)
+ addUInt(Die, Attribute, dwarf::DW_FORM_sec_offset, Integer);
+ else
+ addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer);
+}
+
/// addLabelAddress - Add a dwarf label attribute data and value using
/// DW_FORM_addr or DW_FORM_GNU_addr_index.
///
/// form given and an op of either DW_FORM_addr or DW_FORM_GNU_addr_index.
///
void CompileUnit::addOpAddress(DIEBlock *Die, const MCSymbol *Sym) {
- DD->addArangeLabel(SymbolCU(this, Sym));
if (!DD->useSplitDwarf()) {
addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
addLabel(Die, dwarf::DW_FORM_udata, Sym);
}
}
-/// addDelta - Add a label delta attribute data and value.
+/// addSectionDelta - Add a section label delta attribute data and value.
///
-void CompileUnit::addDelta(DIE *Die, dwarf::Attribute Attribute,
- dwarf::Form Form, const MCSymbol *Hi,
- const MCSymbol *Lo) {
+void CompileUnit::addSectionDelta(DIE *Die, dwarf::Attribute Attribute,
+ const MCSymbol *Hi, const MCSymbol *Lo) {
DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo);
- Die->addValue(Attribute, Form, Value);
+ if (DD->getDwarfVersion() >= 4)
+ Die->addValue(Attribute, dwarf::DW_FORM_sec_offset, Value);
+ else
+ Die->addValue(Attribute, dwarf::DW_FORM_data4, Value);
}
/// addDIEEntry - Add a DIE attribute data and value.
}
DIE *CompileUnit::createTypeDIE(DICompositeType Ty) {
- DIE *ContextDIE = getOrCreateContextDIE(resolve(Ty.getContext()));
+ DIScope Context = resolve(Ty.getContext());
+ DIE *ContextDIE = getOrCreateContextDIE(Context);
DIE *TyDIE = getDIE(Ty);
if (TyDIE)
// Create new type.
TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty);
- constructTypeDIEImpl(*TyDIE, Ty);
+ constructTypeDIE(*TyDIE, Ty);
- updateAcceleratorTables(Ty, TyDIE);
+ updateAcceleratorTables(Context, Ty, TyDIE);
return TyDIE;
}
+/// Return true if the type is appropriately scoped to be contained inside
+/// its own type unit.
+static bool isTypeUnitScoped(DIType Ty, const DwarfDebug *DD) {
+ DIScope Parent = DD->resolve(Ty.getContext());
+ while (Parent) {
+ // Don't generate a hash for anything scoped inside a function.
+ if (Parent.isSubprogram())
+ return false;
+ Parent = DD->resolve(Parent.getContext());
+ }
+ return true;
+}
+
+/// Return true if the type should be split out into a type unit.
+static bool shouldCreateTypeUnit(DICompositeType CTy, const DwarfDebug *DD) {
+ if (!GenerateTypeUnits)
+ return false;
+
+ uint16_t Tag = CTy.getTag();
+
+ switch (Tag) {
+ case dwarf::DW_TAG_structure_type:
+ case dwarf::DW_TAG_union_type:
+ case dwarf::DW_TAG_enumeration_type:
+ case dwarf::DW_TAG_class_type:
+ // If this is a class, structure, union, or enumeration type
+ // that is a definition (not a declaration), and not scoped
+ // inside a function then separate this out as a type unit.
+ return !CTy.isForwardDecl() && isTypeUnitScoped(CTy, DD);
+ default:
+ return false;
+ }
+}
+
/// getOrCreateTypeDIE - Find existing DIE or create new DIE for the
/// given DIType.
DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) {
// Construct the context before querying for the existence of the DIE in case
// such construction creates the DIE.
- DIE *ContextDIE = getOrCreateContextDIE(resolve(Ty.getContext()));
+ DIScope Context = resolve(Ty.getContext());
+ DIE *ContextDIE = getOrCreateContextDIE(Context);
assert(ContextDIE);
DIE *TyDIE = getDIE(Ty);
if (Ty.isBasicType())
constructTypeDIE(*TyDIE, DIBasicType(Ty));
- else if (Ty.isCompositeType())
- constructTypeDIE(*TyDIE, DICompositeType(Ty));
- else {
+ else if (Ty.isCompositeType()) {
+ DICompositeType CTy(Ty);
+ if (shouldCreateTypeUnit(CTy, DD)) {
+ DD->addTypeUnitType(TyDIE, CTy);
+ // Skip updating the accellerator tables since this is not the full type
+ return TyDIE;
+ }
+ constructTypeDIE(*TyDIE, CTy);
+ } else {
assert(Ty.isDerivedType() && "Unknown kind of DIType");
constructTypeDIE(*TyDIE, DIDerivedType(Ty));
}
- updateAcceleratorTables(Ty, TyDIE);
+ updateAcceleratorTables(Context, Ty, TyDIE);
return TyDIE;
}
-void CompileUnit::updateAcceleratorTables(DIType Ty, const DIE *TyDIE) {
+void CompileUnit::updateAcceleratorTables(DIScope Context, DIType Ty,
+ const DIE *TyDIE) {
if (!Ty.getName().empty() && !Ty.isForwardDecl()) {
bool IsImplementation = 0;
if (Ty.isCompositeType()) {
}
unsigned Flags = IsImplementation ? dwarf::DW_FLAG_type_implementation : 0;
addAccelType(Ty.getName(), std::make_pair(TyDIE, Flags));
+
+ if (!Context || Context.isCompileUnit() || Context.isFile() ||
+ Context.isNameSpace())
+ GlobalTypes[getParentContextString(Context) + Ty.getName().str()] = TyDIE;
}
}
Entry = createDIEEntry(Buffer);
insertDIEEntry(Ty, Entry);
addDIEEntry(Entity, Attribute, Entry);
-
- // If this is a complete composite type then include it in the
- // list of global types.
- addGlobalType(Ty);
}
// Accelerator table mutators - add each name along with its companion
GlobalNames[FullName] = Die;
}
-/// addGlobalType - Add a new global type to the compile unit.
-///
-void CompileUnit::addGlobalType(DIType Ty) {
- DIScope Context = resolve(Ty.getContext());
- if (!Ty.getName().empty() && !Ty.isForwardDecl() &&
- (!Context || Context.isCompileUnit() || Context.isFile() ||
- Context.isNameSpace()))
- if (DIEEntry *Entry = getDIEEntry(Ty)) {
- std::string FullName =
- getParentContextString(Context) + Ty.getName().str();
- GlobalTypes[FullName] = Entry->getEntry();
- }
-}
-
/// getParentContextString - Walks the metadata parent chain in a language
/// specific manner (using the compile unit language) and returns
/// it as a string. This is done at the metadata level because DIEs may
return CS;
}
-/// addPubTypes - Add subprogram argument types for pubtypes section.
-void CompileUnit::addPubTypes(DISubprogram SP) {
- DICompositeType SPTy = SP.getType();
- uint16_t SPTag = SPTy.getTag();
- if (SPTag != dwarf::DW_TAG_subroutine_type)
- return;
-
- DIArray Args = SPTy.getTypeArray();
- for (unsigned i = 0, e = Args.getNumElements(); i != e; ++i) {
- DIType ATy(Args.getElement(i));
- if (!ATy.isType())
- continue;
- addGlobalType(ATy);
- }
-}
-
/// constructTypeDIE - Construct basic type die from DIBasicType.
void CompileUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) {
// Get core information.
addSourceLine(&Buffer, DTy);
}
-/// Return true if the type is appropriately scoped to be contained inside
-/// its own type unit.
-static bool isTypeUnitScoped(DIType Ty, const DwarfDebug *DD) {
- DIScope Parent = DD->resolve(Ty.getContext());
- while (Parent) {
- // Don't generate a hash for anything scoped inside a function.
- if (Parent.isSubprogram())
- return false;
- Parent = DD->resolve(Parent.getContext());
- }
- return true;
-}
-
-/// Return true if the type should be split out into a type unit.
-static bool shouldCreateTypeUnit(DICompositeType CTy, const DwarfDebug *DD) {
- if (!GenerateTypeUnits)
- return false;
-
- uint16_t Tag = CTy.getTag();
-
- switch (Tag) {
- case dwarf::DW_TAG_structure_type:
- case dwarf::DW_TAG_union_type:
- case dwarf::DW_TAG_enumeration_type:
- case dwarf::DW_TAG_class_type:
- // If this is a class, structure, union, or enumeration type
- // that is a definition (not a declaration), and not scoped
- // inside a function then separate this out as a type unit.
- return !CTy.isForwardDecl() && isTypeUnitScoped(CTy, DD);
- default:
- return false;
- }
-}
-
/// constructTypeDIE - Construct type DIE from DICompositeType.
void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
- // If this is a type applicable to a type unit it then add it to the
- // list of types we'll compute a hash for later.
- if (shouldCreateTypeUnit(CTy, DD))
- DD->addTypeUnitType(&Buffer, CTy);
- else
- constructTypeDIEImpl(Buffer, CTy);
-}
-
-void CompileUnit::constructTypeDIEImpl(DIE &Buffer, DICompositeType CTy) {
// Add name if not anonymous or intermediate type.
StringRef Name = CTy.getName();
}
// 3) followed by a custom OP to make the debugger do a TLS lookup.
addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_push_tls_address);
- } else
+ } else {
+ DD->addArangeLabel(SymbolCU(this, Sym));
addOpAddress(Block, Sym);
+ }
// Do not create specification DIE if context is either compile unit
// or a subprogram.
if (GVContext && GV.isDefinition() && !GVContext.isCompileUnit() &&
// GV is a merged global.
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
Value *Ptr = CE->getOperand(0);
- addOpAddress(Block, Asm->getSymbol(cast<GlobalValue>(Ptr)));
+ MCSymbol *Sym = Asm->getSymbol(cast<GlobalValue>(Ptr));
+ DD->addArangeLabel(SymbolCU(this, Sym));
+ addOpAddress(Block, Sym);
addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
SmallVector<Value *, 3> Idx(CE->op_begin() + 1, CE->op_end());
addUInt(Block, dwarf::DW_FORM_udata,
unsigned Offset = DV.getDotDebugLocOffset();
if (Offset != ~0U) {
- addLabel(VariableDie, dwarf::DW_AT_location,
- DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset
- : dwarf::DW_FORM_data4,
- Asm->GetTempSymbol("debug_loc", Offset));
+ addSectionLabel(VariableDie, dwarf::DW_AT_location,
+ Asm->GetTempSymbol("debug_loc", Offset));
DV.setDIE(VariableDie);
return VariableDie;
}