return Var.isBlockByrefVariable(DD->getTypeIdentifierMap());
}
-
DIType DbgVariable::getType() const {
DIType Ty = Var.getType().resolve(DD->getTypeIdentifierMap());
// FIXME: isBlockByrefVariable should be reformulated in terms of complex
else
HasDwarfPubSections = DwarfPubSections == Enable;
- DwarfVersion = DwarfVersionNumber
- ? DwarfVersionNumber
- : MMI->getModule()->getDwarfVersion();
+ DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber
+ : MMI->getModule()->getDwarfVersion();
{
NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
}
}
+// Define out of line so we don't have to include DwarfUnit.h in DwarfDebug.h.
+DwarfDebug::~DwarfDebug() { }
+
// Switch to the specified MCSection and emit an assembler
// temporary label to it if SymbolStem is specified.
static MCSymbol *emitSectionSym(AsmPrinter *Asm, const MCSection *Section,
// Find DIE for the given subprogram and attach appropriate DW_AT_low_pc
// and DW_AT_high_pc attributes. If there are global variables in this
// scope then create and insert DIEs for these variables.
-DIE *DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit &SPCU,
+DIE &DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit &SPCU,
DISubprogram SP) {
DIE *SPDie = SPCU.getDIE(SP);
// object pointer later on. But what we don't want to do is process the
// concrete DIE twice.
if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) {
+ assert(SPDie == AbsSPDIE);
// Pick up abstract subprogram DIE.
SPDie = &SPCU.createAndAddDIE(dwarf::DW_TAG_subprogram, SPCU.getUnitDie());
SPCU.addDIEEntry(*SPDie, dwarf::DW_AT_abstract_origin, *AbsSPDIE);
- } else {
- DISubprogram SPDecl = SP.getFunctionDeclaration();
- if (!SPDecl.isSubprogram()) {
- // There is not any need to generate specification DIE for a function
- // defined at compile unit level. If a function is defined inside another
- // function then gdb prefers the definition at top level and but does not
- // expect specification DIE in parent function. So avoid creating
- // specification DIE for a function defined inside a function.
- DIScope SPContext = resolve(SP.getContext());
- if (SP.isDefinition() && !SPContext.isCompileUnit() &&
- !SPContext.isFile() && !isSubprogramContext(SPContext)) {
- SPCU.addFlag(*SPDie, dwarf::DW_AT_declaration);
-
- // Add arguments.
- DICompositeType SPTy = SP.getType();
- DIArray Args = SPTy.getTypeArray();
- uint16_t SPTag = SPTy.getTag();
- if (SPTag == dwarf::DW_TAG_subroutine_type)
- SPCU.constructSubprogramArguments(*SPDie, Args);
- DIE *SPDeclDie = SPDie;
- SPDie =
- &SPCU.createAndAddDIE(dwarf::DW_TAG_subprogram, SPCU.getUnitDie());
- SPCU.addDIEEntry(*SPDie, dwarf::DW_AT_specification, *SPDeclDie);
- }
- }
}
attachLowHighPC(SPCU, *SPDie, FunctionBeginSym, FunctionEndSym);
// to have concrete versions of our DW_TAG_subprogram nodes.
addSubprogramNames(SP, *SPDie);
- return SPDie;
+ return *SPDie;
}
/// Check whether we should create a DIE for the given Scope, return true
TheCU.addRangeList(std::move(List));
}
+void DwarfDebug::attachRangesOrLowHighPC(DwarfCompileUnit &TheCU, DIE &Die,
+ const SmallVectorImpl<InsnRange> &Ranges) {
+ assert(!Ranges.empty());
+ if (Ranges.size() == 1)
+ attachLowHighPC(TheCU, Die, getLabelBeforeInsn(Ranges.front().first),
+ getLabelAfterInsn(Ranges.front().second));
+ else
+ addScopeRangeList(TheCU, Die, Ranges);
+}
+
// Construct new DW_TAG_lexical_block for this scope and attach
// DW_AT_low_pc/DW_AT_high_pc labels.
-DIE *DwarfDebug::constructLexicalScopeDIE(DwarfCompileUnit &TheCU,
- LexicalScope *Scope) {
+std::unique_ptr<DIE>
+DwarfDebug::constructLexicalScopeDIE(DwarfCompileUnit &TheCU,
+ LexicalScope *Scope) {
if (isLexicalScopeDIENull(Scope))
return nullptr;
- DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block);
+ auto ScopeDIE = make_unique<DIE>(dwarf::DW_TAG_lexical_block);
if (Scope->isAbstractScope())
return ScopeDIE;
- const SmallVectorImpl<InsnRange> &ScopeRanges = Scope->getRanges();
-
- // If we have multiple ranges, emit them into the range section.
- if (ScopeRanges.size() > 1) {
- addScopeRangeList(TheCU, *ScopeDIE, ScopeRanges);
- return ScopeDIE;
- }
-
- // Construct the address range for this DIE.
- SmallVectorImpl<InsnRange>::const_iterator RI = ScopeRanges.begin();
- MCSymbol *Start = getLabelBeforeInsn(RI->first);
- MCSymbol *End = getLabelAfterInsn(RI->second);
- assert(End && "End label should not be null!");
-
- assert(Start->isDefined() && "Invalid starting label for an inlined scope!");
- assert(End->isDefined() && "Invalid end label for an inlined scope!");
-
- attachLowHighPC(TheCU, *ScopeDIE, Start, End);
+ attachRangesOrLowHighPC(TheCU, *ScopeDIE, Scope->getRanges());
return ScopeDIE;
}
// This scope represents inlined body of a function. Construct DIE to
// represent this concrete inlined copy of the function.
-DIE *DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit &TheCU,
- LexicalScope *Scope) {
- const SmallVectorImpl<InsnRange> &ScopeRanges = Scope->getRanges();
- assert(!ScopeRanges.empty() &&
- "LexicalScope does not have instruction markers!");
-
- if (!Scope->getScopeNode())
- return nullptr;
+std::unique_ptr<DIE>
+DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit &TheCU,
+ LexicalScope *Scope) {
+ assert(Scope->getScopeNode());
DIScope DS(Scope->getScopeNode());
DISubprogram InlinedSP = getDISubprogram(DS);
DIE *OriginDIE = TheCU.getDIE(InlinedSP);
+ // FIXME: This should be an assert (or possibly a
+ // getOrCreateSubprogram(InlinedSP)) otherwise we're just failing to emit
+ // inlining information.
if (!OriginDIE) {
DEBUG(dbgs() << "Unable to find original DIE for an inlined subprogram.");
return nullptr;
}
- DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
+ auto ScopeDIE = make_unique<DIE>(dwarf::DW_TAG_inlined_subroutine);
TheCU.addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *OriginDIE);
- // If we have multiple ranges, emit them into the range section.
- if (ScopeRanges.size() > 1)
- addScopeRangeList(TheCU, *ScopeDIE, ScopeRanges);
- else {
- SmallVectorImpl<InsnRange>::const_iterator RI = ScopeRanges.begin();
- MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
- MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
-
- if (!StartLabel || !EndLabel)
- llvm_unreachable("Unexpected Start and End labels for an inlined scope!");
-
- assert(StartLabel->isDefined() &&
- "Invalid starting label for an inlined scope!");
- assert(EndLabel->isDefined() && "Invalid end label for an inlined scope!");
-
- attachLowHighPC(TheCU, *ScopeDIE, StartLabel, EndLabel);
- }
+ attachRangesOrLowHighPC(TheCU, *ScopeDIE, Scope->getRanges());
InlinedSubprogramDIEs.insert(OriginDIE);
return ScopeDIE;
}
+static std::unique_ptr<DIE> constructVariableDIE(DwarfCompileUnit &TheCU,
+ DbgVariable &DV,
+ const LexicalScope &Scope,
+ DIE *&ObjectPointer) {
+ AbstractOrInlined AOI = AOI_None;
+ if (Scope.isAbstractScope())
+ AOI = AOI_Abstract;
+ else if (Scope.getInlinedAt())
+ AOI = AOI_Inlined;
+ auto Var = TheCU.constructVariableDIE(DV, AOI);
+ if (DV.isObjectPointer())
+ ObjectPointer = Var.get();
+ return Var;
+}
+
DIE *DwarfDebug::createScopeChildrenDIE(
DwarfCompileUnit &TheCU, LexicalScope *Scope,
SmallVectorImpl<std::unique_ptr<DIE>> &Children) {
// Collect arguments for current function.
if (LScopes.isCurrentFunctionScope(Scope)) {
for (DbgVariable *ArgDV : CurrentFnArguments)
- if (ArgDV) {
- std::unique_ptr<DIE> Arg =
- TheCU.constructVariableDIE(*ArgDV, Scope->isAbstractScope());
- assert(Arg);
- if (ArgDV->isObjectPointer())
- ObjectPointer = Arg.get();
- Children.push_back(std::move(Arg));
- }
+ if (ArgDV)
+ Children.push_back(
+ constructVariableDIE(TheCU, *ArgDV, *Scope, ObjectPointer));
// If this is a variadic function, add an unspecified parameter.
DISubprogram SP(Scope->getScopeNode());
}
// Collect lexical scope children first.
- for (DbgVariable *DV : ScopeVariables.lookup(Scope)) {
- std::unique_ptr<DIE> Variable =
- TheCU.constructVariableDIE(*DV, Scope->isAbstractScope());
- assert(Variable);
- Children.push_back(std::move(Variable));
- if (DV->isObjectPointer())
- ObjectPointer = Variable.get();
- }
+ for (DbgVariable *DV : ScopeVariables.lookup(Scope))
+ Children.push_back(constructVariableDIE(TheCU, *DV, *Scope, ObjectPointer));
+
for (LexicalScope *LS : Scope->getChildren())
- if (DIE *Nested = constructScopeDIE(TheCU, LS))
- Children.push_back(std::unique_ptr<DIE>(Nested));
+ if (std::unique_ptr<DIE> Nested = constructScopeDIE(TheCU, LS))
+ Children.push_back(std::move(Nested));
return ObjectPointer;
}
+void DwarfDebug::createAndAddScopeChildren(DwarfCompileUnit &TheCU,
+ LexicalScope *Scope, DIE &ScopeDIE) {
+ // We create children when the scope DIE is not null.
+ SmallVector<std::unique_ptr<DIE>, 8> Children;
+ if (DIE *ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children))
+ TheCU.addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer);
+
+ // Add children
+ for (auto &I : Children)
+ ScopeDIE.addChild(std::move(I));
+}
+
+void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU,
+ LexicalScope *Scope) {
+ assert(Scope && Scope->getScopeNode());
+ assert(Scope->isAbstractScope());
+ assert(!Scope->getInlinedAt());
+
+ DISubprogram Sub(Scope->getScopeNode());
+
+ if (!ProcessedSPNodes.insert(Sub))
+ return;
+
+ DIE *ScopeDIE = TheCU.getDIE(Sub);
+ assert(ScopeDIE);
+ AbstractSPDies.insert(std::make_pair(Sub, ScopeDIE));
+ TheCU.addUInt(*ScopeDIE, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
+ createAndAddScopeChildren(TheCU, Scope, *ScopeDIE);
+}
+
+DIE &DwarfDebug::constructSubprogramScopeDIE(DwarfCompileUnit &TheCU,
+ LexicalScope *Scope) {
+ assert(Scope && Scope->getScopeNode());
+ assert(!Scope->getInlinedAt());
+ assert(!Scope->isAbstractScope());
+ DISubprogram Sub(Scope->getScopeNode());
+
+ assert(Sub.isSubprogram());
+
+ ProcessedSPNodes.insert(Sub);
+
+ DIE &ScopeDIE = updateSubprogramScopeDIE(TheCU, Sub);
+
+ createAndAddScopeChildren(TheCU, Scope, ScopeDIE);
+
+ return ScopeDIE;
+}
+
// Construct a DIE for this scope.
-DIE *DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU,
- LexicalScope *Scope) {
+std::unique_ptr<DIE> DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU,
+ LexicalScope *Scope) {
if (!Scope || !Scope->getScopeNode())
return nullptr;
DIScope DS(Scope->getScopeNode());
+ assert((Scope->getInlinedAt() || !DS.isSubprogram()) &&
+ "Only handle inlined subprograms here, use "
+ "constructSubprogramScopeDIE for non-inlined "
+ "subprograms");
+
SmallVector<std::unique_ptr<DIE>, 8> Children;
- DIE *ObjectPointer = nullptr;
- bool ChildrenCreated = false;
// We try to create the scope DIE first, then the children DIEs. This will
// avoid creating un-used children then removing them later when we find out
// the scope DIE is null.
- DIE *ScopeDIE = nullptr;
- if (Scope->getInlinedAt())
+ std::unique_ptr<DIE> ScopeDIE;
+ if (Scope->getParent() && DS.isSubprogram()) {
ScopeDIE = constructInlinedScopeDIE(TheCU, Scope);
- else if (DS.isSubprogram()) {
- ProcessedSPNodes.insert(DS);
- if (Scope->isAbstractScope()) {
- ScopeDIE = TheCU.getDIE(DS);
- // Note down abstract DIE.
- if (ScopeDIE)
- AbstractSPDies.insert(std::make_pair(DS, ScopeDIE));
- } else
- ScopeDIE = updateSubprogramScopeDIE(TheCU, DISubprogram(DS));
+ if (!ScopeDIE)
+ return nullptr;
+ // We create children when the scope DIE is not null.
+ createScopeChildrenDIE(TheCU, Scope, Children);
} else {
// Early exit when we know the scope DIE is going to be null.
if (isLexicalScopeDIENull(Scope))
// We create children here when we know the scope DIE is not going to be
// null and the children will be added to the scope DIE.
- ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children);
- ChildrenCreated = true;
+ createScopeChildrenDIE(TheCU, Scope, Children);
// There is no need to emit empty lexical block DIE.
std::pair<ImportedEntityMap::const_iterator,
ImportedEntityMap::const_iterator> Range =
- std::equal_range(
- ScopesWithImportedEntities.begin(),
- ScopesWithImportedEntities.end(),
- std::pair<const MDNode *, const MDNode *>(DS, nullptr),
- less_first());
+ std::equal_range(ScopesWithImportedEntities.begin(),
+ ScopesWithImportedEntities.end(),
+ std::pair<const MDNode *, const MDNode *>(DS, nullptr),
+ less_first());
if (Children.empty() && Range.first == Range.second)
return nullptr;
ScopeDIE = constructLexicalScopeDIE(TheCU, Scope);
assert(ScopeDIE && "Scope DIE should not be null.");
for (ImportedEntityMap::const_iterator i = Range.first; i != Range.second;
++i)
- constructImportedEntityDIE(TheCU, i->second, ScopeDIE);
- }
-
- if (!ScopeDIE) {
- assert(Children.empty() &&
- "We create children only when the scope DIE is not null.");
- return nullptr;
+ constructImportedEntityDIE(TheCU, i->second, *ScopeDIE);
}
- if (!ChildrenCreated)
- // We create children when the scope DIE is not null.
- ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children);
// Add children
for (auto &I : Children)
ScopeDIE->addChild(std::move(I));
- if (DS.isSubprogram() && ObjectPointer != nullptr)
- TheCU.addDIEEntry(*ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer);
-
return ScopeDIE;
}
StringRef FN = DIUnit.getFilename();
CompilationDir = DIUnit.getDirectory();
- DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
auto OwnedUnit = make_unique<DwarfCompileUnit>(
- InfoHolder.getUnits().size(), Die, DIUnit, Asm, this, &InfoHolder);
+ InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder);
DwarfCompileUnit &NewCU = *OwnedUnit;
+ DIE &Die = NewCU.getUnitDie();
InfoHolder.addUnit(std::move(OwnedUnit));
// LTO with assembly output shares a single line table amongst multiple CUs.
Asm->OutStreamer.getContext().setMCLineTableCompilationDir(
NewCU.getUniqueID(), CompilationDir);
- NewCU.addString(*Die, dwarf::DW_AT_producer, DIUnit.getProducer());
- NewCU.addUInt(*Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
+ NewCU.addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer());
+ NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
DIUnit.getLanguage());
- NewCU.addString(*Die, dwarf::DW_AT_name, FN);
+ NewCU.addString(Die, dwarf::DW_AT_name, FN);
if (!useSplitDwarf()) {
NewCU.initStmtList(DwarfLineSectionSym);
// If we're using split dwarf the compilation dir is going to be in the
// skeleton CU and so we don't need to duplicate it here.
if (!CompilationDir.empty())
- NewCU.addString(*Die, dwarf::DW_AT_comp_dir, CompilationDir);
+ NewCU.addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
- addGnuPubAttributes(NewCU, *Die);
+ addGnuPubAttributes(NewCU, Die);
}
if (DIUnit.isOptimized())
- NewCU.addFlag(*Die, dwarf::DW_AT_APPLE_optimized);
+ NewCU.addFlag(Die, dwarf::DW_AT_APPLE_optimized);
StringRef Flags = DIUnit.getFlags();
if (!Flags.empty())
- NewCU.addString(*Die, dwarf::DW_AT_APPLE_flags, Flags);
+ NewCU.addString(Die, dwarf::DW_AT_APPLE_flags, Flags);
if (unsigned RVer = DIUnit.getRunTimeVersion())
- NewCU.addUInt(*Die, dwarf::DW_AT_APPLE_major_runtime_vers,
+ NewCU.addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
dwarf::DW_FORM_data1, RVer);
if (!FirstCU)
DwarfInfoSectionSym);
CUMap.insert(std::make_pair(DIUnit, &NewCU));
- CUDieMap.insert(std::make_pair(Die, &NewCU));
+ CUDieMap.insert(std::make_pair(&Die, &NewCU));
return NewCU;
}
CURef = &TheCU;
DISubprogram SP(N);
- if (!SP.isDefinition())
- // This is a method declaration which will be handled while constructing
- // class type.
- return;
+ assert(SP.isSubprogram());
+ assert(SP.isDefinition());
DIE &SubprogramDie = *TheCU.getOrCreateSubprogramDIE(SP);
DIImportedEntity Module(N);
assert(Module.Verify());
if (DIE *D = TheCU.getOrCreateContextDIE(Module.getContext()))
- constructImportedEntityDIE(TheCU, Module, D);
+ constructImportedEntityDIE(TheCU, Module, *D);
}
void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU,
- const MDNode *N, DIE *Context) {
+ const MDNode *N, DIE &Context) {
DIImportedEntity Module(N);
assert(Module.Verify());
return constructImportedEntityDIE(TheCU, Module, Context);
void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU,
const DIImportedEntity &Module,
- DIE *Context) {
+ DIE &Context) {
assert(Module.Verify() &&
"Use one of the MDNode * overloads to handle invalid metadata");
- assert(Context && "Should always have a context for an imported_module");
- DIE &IMDie = TheCU.createAndAddDIE(Module.getTag(), *Context, Module);
+ DIE &IMDie = TheCU.createAndAddDIE(Module.getTag(), Context, Module);
DIE *EntityDie;
DIDescriptor Entity = resolve(Module.getEntity());
if (Entity.isNameSpace())
SectionMap[Asm->getObjFileLowering().getTextSection()];
}
-// Attach DW_AT_inline attribute with inlined subprogram DIEs.
-void DwarfDebug::computeInlinedDIEs() {
- // Attach DW_AT_inline attribute with inlined subprogram DIEs.
- for (DIE *ISP : InlinedSubprogramDIEs)
- FirstCU->addUInt(*ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
-
- for (const auto &AI : AbstractSPDies) {
- DIE &ISP = *AI.second;
- if (InlinedSubprogramDIEs.count(&ISP))
- continue;
- FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
- }
-}
-
// Collect info for variables that were optimized out.
void DwarfDebug::collectDeadVariables() {
const Module *M = MMI->getModule();
if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) {
for (MDNode *N : CU_Nodes->operands()) {
DICompileUnit TheCU(N);
+ // Construct subprogram DIE and add variables DIEs.
+ DwarfCompileUnit *SPCU =
+ static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU));
+ assert(SPCU && "Unable to find Compile Unit!");
DIArray Subprograms = TheCU.getSubprograms();
for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) {
DISubprogram SP(Subprograms.getElement(i));
if (ProcessedSPNodes.count(SP) != 0)
continue;
- if (!SP.isSubprogram())
- continue;
- if (!SP.isDefinition())
- continue;
+ assert(SP.isSubprogram() &&
+ "CU's subprogram list contains a non-subprogram");
+ assert(SP.isDefinition() &&
+ "CU's subprogram list contains a subprogram declaration");
DIArray Variables = SP.getVariables();
if (Variables.getNumElements() == 0)
continue;
- // Construct subprogram DIE and add variables DIEs.
- DwarfCompileUnit *SPCU =
- static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU));
- assert(SPCU && "Unable to find Compile Unit!");
// FIXME: See the comment in constructSubprogramDIE about duplicate
// subprogram DIEs.
constructSubprogramDIE(*SPCU, SP);
DIE *SPDIE = SPCU->getDIE(SP);
for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) {
DIVariable DV(Variables.getElement(vi));
- if (!DV.isVariable())
- continue;
+ assert(DV.isVariable());
DbgVariable NewVar(DV, nullptr, this);
- SPDIE->addChild(SPCU->constructVariableDIE(NewVar, false));
+ SPDIE->addChild(SPCU->constructVariableDIE(NewVar));
}
}
}
// Collect info for variables that were optimized out.
collectDeadVariables();
- // Attach DW_AT_inline attribute with inlined subprogram DIEs.
- computeInlinedDIEs();
-
// Handle anything that needs to be done on a per-unit basis after
// all other generation.
for (const auto &TheU : getUnits()) {
// Emit all Dwarf sections that should come after the content.
void DwarfDebug::endModule() {
- assert(CurFn == 0);
- assert(CurMI == 0);
+ assert(CurFn == nullptr);
+ assert(CurMI == nullptr);
if (!FirstCU)
return;
RegVar->setFrameIndex(VI.Slot);
if (!addCurrentFnArgument(RegVar, Scope))
addScopeVariable(Scope, RegVar);
- if (AbsDbgVariable)
- AbsDbgVariable->setFrameIndex(VI.Slot);
}
}
-// Return true if debug value, encoded by DBG_VALUE instruction, is in a
-// defined reg.
-static bool isDbgValueInDefinedReg(const MachineInstr *MI) {
- assert(MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
- return MI->getNumOperands() == 3 && MI->getOperand(0).isReg() &&
- MI->getOperand(0).getReg() &&
- (MI->getOperand(1).isImm() ||
- (MI->getOperand(1).isReg() && MI->getOperand(1).getReg() == 0U));
-}
-
// Get .debug_loc entry for the instruction range starting at MI.
-static DebugLocEntry getDebugLocEntry(AsmPrinter *Asm,
- const MCSymbol *FLabel,
- const MCSymbol *SLabel,
- const MachineInstr *MI,
- DwarfCompileUnit *Unit) {
+static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) {
const MDNode *Var = MI->getDebugVariable();
assert(MI->getNumOperands() == 3);
MLoc.set(MI->getOperand(0).getReg());
else
MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
- return DebugLocEntry(FLabel, SLabel, MLoc, Var, Unit);
+ return DebugLocEntry::Value(Var, MLoc);
}
if (MI->getOperand(0).isImm())
- return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm(), Var, Unit);
+ return DebugLocEntry::Value(Var, MI->getOperand(0).getImm());
if (MI->getOperand(0).isFPImm())
- return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm(),
- Var, Unit);
+ return DebugLocEntry::Value(Var, MI->getOperand(0).getFPImm());
if (MI->getOperand(0).isCImm())
- return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm(),
- Var, Unit);
+ return DebugLocEntry::Value(Var, MI->getOperand(0).getCImm());
llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!");
}
// Find variables for each lexical scope.
void
DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) {
+ LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
+ DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
// Grab the variable info that was squirreled away in the MMI side-table.
collectVariableInfoFromMMITable(Processed);
- for (const MDNode *Var : UserVariables) {
- if (Processed.count(Var))
+ for (const auto &I : DbgValues) {
+ DIVariable DV(I.first);
+ if (Processed.count(DV))
continue;
- // History contains relevant DBG_VALUE instructions for Var and instructions
+ // History contains relevant DBG_VALUE instructions for DV and instructions
// clobbering it.
- SmallVectorImpl<const MachineInstr *> &History = DbgValues[Var];
+ const SmallVectorImpl<const MachineInstr *> &History = I.second;
if (History.empty())
continue;
const MachineInstr *MInsn = History.front();
- DIVariable DV(Var);
LexicalScope *Scope = nullptr;
if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
DISubprogram(DV.getContext()).describes(CurFn->getFunction()))
Scope = LScopes.getCurrentFunctionScope();
- else if (MDNode *IA = DV.getInlinedAt())
- Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA));
- else
- Scope = LScopes.findLexicalScope(cast<MDNode>(DV->getOperand(1)));
+ else if (MDNode *IA = DV.getInlinedAt()) {
+ DebugLoc DL = DebugLoc::getFromDILocation(IA);
+ Scope = LScopes.findInlinedScope(DebugLoc::get(
+ DL.getLine(), DL.getCol(), DV.getContext(), IA));
+ } else
+ Scope = LScopes.findLexicalScope(DV.getContext());
// If variable scope is not found then skip this variable.
if (!Scope)
continue;
const MachineInstr *End = HI[1];
DEBUG(dbgs() << "DotDebugLoc Pair:\n"
<< "\t" << *Begin << "\t" << *End << "\n");
- if (End->isDebugValue())
+ if (End->isDebugValue() && End->getDebugVariable() == DV)
SLabel = getLabelBeforeInsn(End);
else {
- // End is a normal instruction clobbering the range.
+ // End is clobbering the range.
SLabel = getLabelAfterInsn(End);
assert(SLabel && "Forgot label after clobber instruction");
++HI;
}
// The value is valid until the next DBG_VALUE or clobber.
- LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
- DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
- DebugLocEntry Loc = getDebugLocEntry(Asm, FLabel, SLabel, Begin, TheCU);
+ DebugLocEntry Loc(FLabel, SLabel, getDebugLocValue(Begin), TheCU);
if (DebugLoc.empty() || !DebugLoc.back().Merge(Loc))
DebugLoc.push_back(std::move(Loc));
}
}
// Collect info for variables that were optimized out.
- LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
DIArray Variables = DISubprogram(FnScope->getScopeNode()).getVariables();
for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) {
DIVariable DV(Variables.getElement(i));
- if (!DV || !DV.isVariable() || !Processed.insert(DV))
+ assert(DV.isVariable());
+ if (!Processed.insert(DV))
continue;
if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext()))
addScopeVariable(Scope, new DbgVariable(DV, nullptr, this));
// Process beginning of an instruction.
void DwarfDebug::beginInstruction(const MachineInstr *MI) {
- assert(CurMI == 0);
+ assert(CurMI == nullptr);
CurMI = MI;
// Check if source location changes, but ignore DBG_VALUE locations.
if (!MI->isDebugValue()) {
// Process end of an instruction.
void DwarfDebug::endInstruction() {
- assert(CurMI != 0);
+ assert(CurMI != nullptr);
// Don't create a new label after DBG_VALUE instructions.
// They don't generate code.
if (!CurMI->isDebugValue())
if (LScopes.empty())
return;
- assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned");
+ assert(DbgValues.empty() && "DbgValues map wasn't cleaned!");
// Make sure that each lexical scope will have a begin/end label.
identifyScopeMarkers();
// Assumes in correct section after the entry point.
Asm->OutStreamer.EmitLabel(FunctionBeginSym);
- const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
- // LiveUserVar - Map physreg numbers to the MDNode they contain.
- std::vector<const MDNode *> LiveUserVar(TRI->getNumRegs());
-
- for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E;
- ++I) {
- bool AtBlockEntry = true;
- for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
- II != IE; ++II) {
- const MachineInstr *MI = II;
-
- if (MI->isDebugValue()) {
- assert(MI->getNumOperands() > 1 && "Invalid machine instruction!");
-
- // Keep track of user variables.
- const MDNode *Var = MI->getDebugVariable();
-
- // Variable is in a register, we need to check for clobbers.
- if (isDbgValueInDefinedReg(MI))
- LiveUserVar[MI->getOperand(0).getReg()] = Var;
-
- // Check the history of this variable.
- SmallVectorImpl<const MachineInstr *> &History = DbgValues[Var];
- if (History.empty()) {
- UserVariables.push_back(Var);
- // The first mention of a function argument gets the FunctionBeginSym
- // label, so arguments are visible when breaking at function entry.
- DIVariable DV(Var);
- if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable &&
- getDISubprogram(DV.getContext()).describes(MF->getFunction()))
- LabelsBeforeInsn[MI] = FunctionBeginSym;
- } else {
- // We have seen this variable before. Try to coalesce DBG_VALUEs.
- const MachineInstr *Prev = History.back();
- if (Prev->isDebugValue()) {
- // Coalesce identical entries at the end of History.
- if (History.size() >= 2 &&
- Prev->isIdenticalTo(History[History.size() - 2])) {
- DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"
- << "\t" << *Prev << "\t"
- << *History[History.size() - 2] << "\n");
- History.pop_back();
- }
-
- // Terminate old register assignments that don't reach MI;
- MachineFunction::const_iterator PrevMBB = Prev->getParent();
- if (PrevMBB != I && (!AtBlockEntry || std::next(PrevMBB) != I) &&
- isDbgValueInDefinedReg(Prev)) {
- // Previous register assignment needs to terminate at the end of
- // its basic block.
- MachineBasicBlock::const_iterator LastMI =
- PrevMBB->getLastNonDebugInstr();
- if (LastMI == PrevMBB->end()) {
- // Drop DBG_VALUE for empty range.
- DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n"
- << "\t" << *Prev << "\n");
- History.pop_back();
- } else if (std::next(PrevMBB) != PrevMBB->getParent()->end())
- // Terminate after LastMI.
- History.push_back(LastMI);
- }
- }
- }
- History.push_back(MI);
- } else {
- // Not a DBG_VALUE instruction.
- if (!MI->isPosition())
- AtBlockEntry = false;
-
+ // Collect user variables, find the end of the prologue.
+ for (const auto &MBB : *MF) {
+ for (const auto &MI : MBB) {
+ if (MI.isDebugValue()) {
+ assert(MI.getNumOperands() > 1 && "Invalid machine instruction!");
+ // Keep track of user variables in order of appearance. Create the
+ // empty history for each variable so that the order of keys in
+ // DbgValues is correct. Actual history will be populated in
+ // calculateDbgValueHistory() function.
+ const MDNode *Var = MI.getDebugVariable();
+ DbgValues.insert(
+ std::make_pair(Var, SmallVector<const MachineInstr *, 4>()));
+ } else if (!MI.getFlag(MachineInstr::FrameSetup) &&
+ PrologEndLoc.isUnknown() && !MI.getDebugLoc().isUnknown()) {
// First known non-DBG_VALUE and non-frame setup location marks
// the beginning of the function body.
- if (!MI->getFlag(MachineInstr::FrameSetup) &&
- (PrologEndLoc.isUnknown() && !MI->getDebugLoc().isUnknown()))
- PrologEndLoc = MI->getDebugLoc();
-
- // Check if the instruction clobbers any registers with debug vars.
- for (const MachineOperand &MO : MI->operands()) {
- if (!MO.isReg() || !MO.isDef() || !MO.getReg())
- continue;
- for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
- ++AI) {
- unsigned Reg = *AI;
- const MDNode *Var = LiveUserVar[Reg];
- if (!Var)
- continue;
- // Reg is now clobbered.
- LiveUserVar[Reg] = nullptr;
-
- // Was MD last defined by a DBG_VALUE referring to Reg?
- DbgValueHistoryMap::iterator HistI = DbgValues.find(Var);
- if (HistI == DbgValues.end())
- continue;
- SmallVectorImpl<const MachineInstr *> &History = HistI->second;
- if (History.empty())
- continue;
- const MachineInstr *Prev = History.back();
- // Sanity-check: Register assignments are terminated at the end of
- // their block.
- if (!Prev->isDebugValue() || Prev->getParent() != MI->getParent())
- continue;
- // Is the variable still in Reg?
- if (!isDbgValueInDefinedReg(Prev) ||
- Prev->getOperand(0).getReg() != Reg)
- continue;
- // Var is clobbered. Make sure the next instruction gets a label.
- History.push_back(MI);
- }
- }
+ PrologEndLoc = MI.getDebugLoc();
}
}
}
+ // Calculate history for local variables.
+ calculateDbgValueHistory(MF, Asm->TM.getRegisterInfo(), DbgValues);
+
+ // Request labels for the full history.
for (auto &I : DbgValues) {
- SmallVectorImpl<const MachineInstr *> &History = I.second;
+ const SmallVectorImpl<const MachineInstr *> &History = I.second;
if (History.empty())
continue;
- // Make sure the final register assignments are terminated.
- const MachineInstr *Prev = History.back();
- if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) {
- const MachineBasicBlock *PrevMBB = Prev->getParent();
- MachineBasicBlock::const_iterator LastMI =
- PrevMBB->getLastNonDebugInstr();
- if (LastMI == PrevMBB->end())
- // Drop DBG_VALUE for empty range.
- History.pop_back();
- else if (PrevMBB != &PrevMBB->getParent()->back()) {
- // Terminate after LastMI.
- History.push_back(LastMI);
- }
- }
- // Request labels for the full history.
+ // The first mention of a function argument gets the FunctionBeginSym
+ // label, so arguments are visible when breaking at function entry.
+ DIVariable DV(I.first);
+ if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable &&
+ getDISubprogram(DV.getContext()).describes(MF->getFunction()))
+ LabelsBeforeInsn[History.front()] = FunctionBeginSym;
+
for (const MachineInstr *MI : History) {
- if (MI->isDebugValue())
+ if (MI->isDebugValue() && MI->getDebugVariable() == DV)
requestLabelBeforeInsn(MI);
else
requestLabelAfterInsn(MI);
CurFn = MF;
else
assert(CurFn == MF);
- assert(CurFn != 0);
+ assert(CurFn != nullptr);
if (!MMI->hasDebugInfo() || LScopes.empty()) {
// If we don't have a lexical scope for this function then there will
// Construct abstract scopes.
for (LexicalScope *AScope : LScopes.getAbstractScopesList()) {
DISubprogram SP(AScope->getScopeNode());
- if (SP.isSubprogram()) {
- // Collect info for variables that were optimized out.
- DIArray Variables = SP.getVariables();
- for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) {
- DIVariable DV(Variables.getElement(i));
- if (!DV || !DV.isVariable() || !ProcessedVars.insert(DV))
- continue;
- // Check that DbgVariable for DV wasn't created earlier, when
- // findAbstractVariable() was called for inlined instance of DV.
- LLVMContext &Ctx = DV->getContext();
- DIVariable CleanDV = cleanseInlinedVariable(DV, Ctx);
- if (AbstractVariables.lookup(CleanDV))
- continue;
- if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext()))
- addScopeVariable(Scope, new DbgVariable(DV, nullptr, this));
- }
+ if (!SP.isSubprogram())
+ continue;
+ // Collect info for variables that were optimized out.
+ DIArray Variables = SP.getVariables();
+ for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) {
+ DIVariable DV(Variables.getElement(i));
+ assert(DV && DV.isVariable());
+ if (!ProcessedVars.insert(DV))
+ continue;
+ // Check that DbgVariable for DV wasn't created earlier, when
+ // findAbstractVariable() was called for inlined instance of DV.
+ LLVMContext &Ctx = DV->getContext();
+ DIVariable CleanDV = cleanseInlinedVariable(DV, Ctx);
+ if (AbstractVariables.lookup(CleanDV))
+ continue;
+ if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext()))
+ addScopeVariable(Scope, new DbgVariable(DV, nullptr, this));
}
- if (ProcessedSPNodes.count(AScope->getScopeNode()) == 0)
- constructScopeDIE(TheCU, AScope);
+ constructAbstractSubprogramScopeDIE(TheCU, AScope);
}
- DIE &CurFnDIE = *constructScopeDIE(TheCU, FnScope);
+ DIE &CurFnDIE = constructSubprogramScopeDIE(TheCU, FnScope);
if (!CurFn->getTarget().Options.DisableFramePointerElim(*CurFn))
TheCU.addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr);
DeleteContainerPointers(I.second);
ScopeVariables.clear();
DeleteContainerPointers(CurrentFnArguments);
- UserVariables.clear();
DbgValues.clear();
AbstractVariables.clear();
LabelsBeforeInsn.clear();
StringRef Dir;
unsigned Src = 1;
unsigned Discriminator = 0;
- if (S) {
- DIDescriptor Scope(S);
-
- if (Scope.isCompileUnit()) {
- DICompileUnit CU(S);
- Fn = CU.getFilename();
- Dir = CU.getDirectory();
- } else if (Scope.isFile()) {
- DIFile F(S);
- Fn = F.getFilename();
- Dir = F.getDirectory();
- } else if (Scope.isSubprogram()) {
- DISubprogram SP(S);
- Fn = SP.getFilename();
- Dir = SP.getDirectory();
- } else if (Scope.isLexicalBlockFile()) {
- DILexicalBlockFile DBF(S);
- Fn = DBF.getFilename();
- Dir = DBF.getDirectory();
- } else if (Scope.isLexicalBlock()) {
- DILexicalBlock DB(S);
- Fn = DB.getFilename();
- Dir = DB.getDirectory();
- Discriminator = DB.getDiscriminator();
- } else
- llvm_unreachable("Unexpected scope info");
+ if (DIScope Scope = DIScope(S)) {
+ assert(Scope.isScope());
+ Fn = Scope.getFilename();
+ Dir = Scope.getDirectory();
+ if (Scope.isLexicalBlock())
+ Discriminator = DILexicalBlock(S).getDiscriminator();
unsigned CUID = Asm->OutStreamer.getContext().getDwarfCompileUnitID();
Src = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID])
// Dwarf sections base addresses.
DwarfInfoSectionSym =
emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info");
- if (useSplitDwarf())
+ if (useSplitDwarf()) {
DwarfInfoDWOSectionSym =
emitSectionSym(Asm, TLOF.getDwarfInfoDWOSection(), "section_info_dwo");
+ DwarfTypesDWOSectionSym =
+ emitSectionSym(Asm, TLOF.getDwarfTypesDWOSection(), "section_types_dwo");
+ }
DwarfAbbrevSectionSym =
emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev");
if (useSplitDwarf())
void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
const DebugLocEntry &Entry) {
- DIVariable DV(Entry.getVariable());
- if (Entry.isInt()) {
+ assert(Entry.getValues().size() == 1 &&
+ "multi-value entries are not supported yet.");
+ const DebugLocEntry::Value Value = Entry.getValues()[0];
+ DIVariable DV(Value.getVariable());
+ if (Value.isInt()) {
DIBasicType BTy(resolve(DV.getType()));
if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed ||
BTy.getEncoding() == dwarf::DW_ATE_signed_char)) {
Streamer.EmitInt8(dwarf::DW_OP_consts, "DW_OP_consts");
- Streamer.EmitSLEB128(Entry.getInt());
+ Streamer.EmitSLEB128(Value.getInt());
} else {
Streamer.EmitInt8(dwarf::DW_OP_constu, "DW_OP_constu");
- Streamer.EmitULEB128(Entry.getInt());
+ Streamer.EmitULEB128(Value.getInt());
}
- } else if (Entry.isLocation()) {
- MachineLocation Loc = Entry.getLoc();
+ } else if (Value.isLocation()) {
+ MachineLocation Loc = Value.getLoc();
if (!DV.hasComplexAddress())
// Regular entry.
Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect());
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfARangesSection());
- typedef DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan> > SpansType;
+ typedef DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan>> SpansType;
SpansType Spans;
for (const auto &I : CUMap) {
DwarfCompileUnit *TheCU = I.second;
- // Emit a symbol so we can find the beginning of our ranges.
- Asm->OutStreamer.EmitLabel(TheCU->getLabelRange());
-
// Iterate over the misc ranges for the compile units in the module.
for (const RangeSpanList &List : TheCU->getRangeLists()) {
// Emit our symbol so we can find the beginning of the range.
const MCSymbol *End = Range.getEnd();
assert(Begin && "Range without a begin symbol?");
assert(End && "Range without an end symbol?");
- Asm->OutStreamer.EmitSymbolValue(Begin, Size);
- Asm->OutStreamer.EmitSymbolValue(End, Size);
+ if (TheCU->getRanges().size() == 1) {
+ // Grab the begin symbol from the first range as our base.
+ const MCSymbol *Base = TheCU->getRanges()[0].getStart();
+ Asm->EmitLabelDifference(Begin, Base, Size);
+ Asm->EmitLabelDifference(End, Base, Size);
+ } else {
+ Asm->OutStreamer.EmitSymbolValue(Begin, Size);
+ Asm->OutStreamer.EmitSymbolValue(End, Size);
+ }
}
// And terminate the list with two 0 values.
// DW_AT_addr_base, DW_AT_ranges_base.
DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) {
- DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
auto OwnedUnit = make_unique<DwarfCompileUnit>(
- CU.getUniqueID(), Die, CU.getCUNode(), Asm, this, &SkeletonHolder);
+ CU.getUniqueID(), CU.getCUNode(), Asm, this, &SkeletonHolder);
DwarfCompileUnit &NewCU = *OwnedUnit;
NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection(),
DwarfInfoSectionSym);
NewCU.initStmtList(DwarfLineSectionSym);
- initSkeletonUnit(CU, *Die, std::move(OwnedUnit));
+ initSkeletonUnit(CU, NewCU.getUnitDie(), std::move(OwnedUnit));
return NewCU;
}
DwarfCompileUnit &CU = static_cast<DwarfCompileUnit &>(
*SkeletonHolder.getUnits()[TU.getCU().getUniqueID()]);
- DIE *Die = new DIE(dwarf::DW_TAG_type_unit);
- auto OwnedUnit = make_unique<DwarfTypeUnit>(TU.getUniqueID(), Die, CU, Asm,
- this, &SkeletonHolder);
+ auto OwnedUnit = make_unique<DwarfTypeUnit>(TU.getUniqueID(), CU, Asm, this,
+ &SkeletonHolder);
DwarfTypeUnit &NewTU = *OwnedUnit;
NewTU.setTypeSignature(TU.getTypeSignature());
NewTU.setType(nullptr);
NewTU.initSection(
Asm->getObjFileLowering().getDwarfTypesSection(TU.getTypeSignature()));
- initSkeletonUnit(TU, *Die, std::move(OwnedUnit));
+ initSkeletonUnit(TU, NewTU.getUnitDie(), std::move(OwnedUnit));
return NewTU;
}
assert(useSplitDwarf() && "No split dwarf debug info?");
// Don't pass an abbrev symbol, using a constant zero instead so as not to
// emit relocations into the dwo file.
- InfoHolder.emitUnits(this, /* AbbrevSymbol */nullptr);
+ InfoHolder.emitUnits(this, /* AbbrevSymbol */ nullptr);
}
// Emit the .debug_abbrev.dwo section for separated dwarf. This contains the
return &SplitTypeUnitFileTable;
}
+static uint64_t makeTypeSignature(StringRef Identifier) {
+ MD5 Hash;
+ Hash.update(Identifier);
+ // ... take the least significant 8 bytes and return those. Our MD5
+ // implementation always returns its results in little endian, swap bytes
+ // appropriately.
+ MD5::MD5Result Result;
+ Hash.final(Result);
+ return *reinterpret_cast<support::ulittle64_t *>(Result + 8);
+}
+
void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
StringRef Identifier, DIE &RefDie,
DICompositeType CTy) {
- // 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
- // and think this is a full definition.
- CU.addFlag(RefDie, dwarf::DW_AT_declaration);
+ // Fast path if we're building some type units and one has already used the
+ // address pool we know we're going to throw away all this work anyway, so
+ // don't bother building dependent types.
+ if (!TypeUnitsUnderConstruction.empty() && AddrPool.hasBeenUsed())
+ return;
const DwarfTypeUnit *&TU = DwarfTypeUnits[CTy];
if (TU) {
return;
}
- DIE *UnitDie = new DIE(dwarf::DW_TAG_type_unit);
- auto OwnedUnit =
- make_unique<DwarfTypeUnit>(InfoHolder.getUnits().size(), UnitDie, CU, Asm,
- this, &InfoHolder, getDwoLineTable(CU));
+ bool TopLevelType = TypeUnitsUnderConstruction.empty();
+ AddrPool.resetUsedFlag();
+
+ auto OwnedUnit = make_unique<DwarfTypeUnit>(
+ InfoHolder.getUnits().size() + TypeUnitsUnderConstruction.size(), CU, Asm,
+ this, &InfoHolder, getDwoLineTable(CU));
DwarfTypeUnit &NewTU = *OwnedUnit;
+ DIE &UnitDie = NewTU.getUnitDie();
TU = &NewTU;
- InfoHolder.addUnit(std::move(OwnedUnit));
+ TypeUnitsUnderConstruction.push_back(
+ std::make_pair(std::move(OwnedUnit), CTy));
- NewTU.addUInt(*UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
+ NewTU.addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
CU.getLanguage());
- MD5 Hash;
- Hash.update(Identifier);
- // ... take the least significant 8 bytes and return those. Our MD5
- // implementation always returns its results in little endian, swap bytes
- // appropriately.
- MD5::MD5Result Result;
- Hash.final(Result);
- uint64_t Signature = *reinterpret_cast<support::ulittle64_t *>(Result + 8);
+ uint64_t Signature = makeTypeSignature(Identifier);
NewTU.setTypeSignature(Signature);
+
if (useSplitDwarf())
- NewTU.setSkeleton(constructSkeletonTU(NewTU));
- else
- CU.applyStmtList(*UnitDie);
+ NewTU.initSection(Asm->getObjFileLowering().getDwarfTypesDWOSection(),
+ DwarfTypesDWOSectionSym);
+ else {
+ CU.applyStmtList(UnitDie);
+ NewTU.initSection(
+ Asm->getObjFileLowering().getDwarfTypesSection(Signature));
+ }
NewTU.setType(NewTU.createTypeDIE(CTy));
- NewTU.initSection(
- useSplitDwarf()
- ? Asm->getObjFileLowering().getDwarfTypesDWOSection(Signature)
- : Asm->getObjFileLowering().getDwarfTypesSection(Signature));
+ if (TopLevelType) {
+ auto TypeUnitsToAdd = std::move(TypeUnitsUnderConstruction);
+ TypeUnitsUnderConstruction.clear();
+
+ // Types referencing entries in the address table cannot be placed in type
+ // units.
+ if (AddrPool.hasBeenUsed()) {
+
+ // Remove all the types built while building this type.
+ // 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);
+
+ // Construct this type in the CU directly.
+ // This is inefficient because all the dependent types will be rebuilt
+ // from scratch, including building them in type units, discovering that
+ // they depend on addresses, throwing them out and rebuilding them.
+ CU.constructTypeDIE(RefDie, CTy);
+ return;
+ }
+ // If the type wasn't dependent on fission addresses, finish adding the type
+ // and all its dependent types.
+ for (auto &TU : TypeUnitsToAdd) {
+ if (useSplitDwarf())
+ TU.first->setSkeleton(constructSkeletonTU(*TU.first));
+ InfoHolder.addUnit(std::move(TU.first));
+ }
+ }
CU.addDIETypeSignature(RefDie, NewTU);
}
void DwarfDebug::attachLowHighPC(DwarfCompileUnit &Unit, DIE &D,
MCSymbol *Begin, MCSymbol *End) {
+ assert(Begin && "Begin label should not be null!");
+ assert(End && "End label should not be null!");
+ assert(Begin->isDefined() && "Invalid starting label");
+ assert(End->isDefined() && "Invalid end label");
+
Unit.addLabelAddress(D, dwarf::DW_AT_low_pc, Begin);
if (DwarfVersion < 4)
Unit.addLabelAddress(D, dwarf::DW_AT_high_pc, End);
void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) {
if (!useDwarfAccelTables())
return;
- InfoHolder.getStringPoolEntry(Name);
- AccelNames.AddName(Name, &Die);
+ AccelNames.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name),
+ &Die);
}
void DwarfDebug::addAccelObjC(StringRef Name, const DIE &Die) {
if (!useDwarfAccelTables())
return;
- InfoHolder.getStringPoolEntry(Name);
- AccelObjC.AddName(Name, &Die);
+ AccelObjC.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name),
+ &Die);
}
void DwarfDebug::addAccelNamespace(StringRef Name, const DIE &Die) {
if (!useDwarfAccelTables())
return;
- InfoHolder.getStringPoolEntry(Name);
- AccelNamespace.AddName(Name, &Die);
+ AccelNamespace.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name),
+ &Die);
}
void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) {
if (!useDwarfAccelTables())
return;
- InfoHolder.getStringPoolEntry(Name);
- AccelTypes.AddName(Name, &Die, Flags);
+ AccelTypes.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name),
+ &Die);
}