attachLowHighPC(SPCU, *SPDie, FunctionBeginSym, FunctionEndSym);
- const TargetRegisterInfo *RI = Asm->TM.getSubtargetImpl()->getRegisterInfo();
- MachineLocation Location(RI->getFrameRegister(*Asm->MF));
- SPCU.addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
+ // Only include DW_AT_frame_base in full debug info
+ if (SPCU.getCUNode().getEmissionKind() != DIBuilder::LineTablesOnly) {
+ const TargetRegisterInfo *RI =
+ Asm->TM.getSubtargetImpl()->getRegisterInfo();
+ MachineLocation Location(RI->getFrameRegister(*Asm->MF));
+ SPCU.addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
+ }
// Add name to the name table, we do this here because we're guaranteed
// to have concrete versions of our DW_TAG_subprogram nodes.
// We don't create a DIE if we have a single Range and the end label
// is null.
- SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin();
- MCSymbol *End = getLabelAfterInsn(RI->second);
- return !End;
+ return !getLabelAfterInsn(Ranges.front().second);
}
static void addSectionLabel(AsmPrinter &Asm, DwarfUnit &U, DIE &D,
DIE *DwarfDebug::createScopeChildrenDIE(
DwarfCompileUnit &TheCU, LexicalScope *Scope,
- SmallVectorImpl<std::unique_ptr<DIE>> &Children) {
+ SmallVectorImpl<std::unique_ptr<DIE>> &Children,
+ unsigned *ChildScopeCount) {
DIE *ObjectPointer = nullptr;
- // Collect arguments for current function.
- if (LScopes.isCurrentFunctionScope(Scope)) {
- for (DbgVariable *ArgDV : CurrentFnArguments)
- if (ArgDV)
- Children.push_back(
- constructVariableDIE(TheCU, *ArgDV, *Scope, ObjectPointer));
-
- // If this is a variadic function, add an unspecified parameter.
- DISubprogram SP(Scope->getScopeNode());
- DITypeArray FnArgs = SP.getType().getTypeArray();
- // If we have a single element of null, it is a function that returns void.
- // If we have more than one elements and the last one is null, it is a
- // variadic function.
- if (FnArgs.getNumElements() > 1 &&
- !FnArgs.getElement(FnArgs.getNumElements() - 1))
- Children.push_back(
- make_unique<DIE>(dwarf::DW_TAG_unspecified_parameters));
- }
-
- // Collect lexical scope children first.
for (DbgVariable *DV : ScopeVariables.lookup(Scope))
Children.push_back(constructVariableDIE(TheCU, *DV, *Scope, ObjectPointer));
+ unsigned ChildCountWithoutScopes = Children.size();
+
for (LexicalScope *LS : Scope->getChildren())
- if (std::unique_ptr<DIE> Nested = constructScopeDIE(TheCU, LS))
- Children.push_back(std::move(Nested));
+ constructScopeDIE(TheCU, LS, Children);
+
+ if (ChildScopeCount)
+ *ChildScopeCount = Children.size() - ChildCountWithoutScopes;
+
return ObjectPointer;
}
-void DwarfDebug::createAndAddScopeChildren(DwarfCompileUnit &TheCU,
+DIE *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);
+ DIE *ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children);
// Add children
for (auto &I : Children)
ScopeDIE.addChild(std::move(I));
+
+ return ObjectPointer;
}
void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU,
SPCU.applySubprogramAttributesToDefinition(SP, *AbsDef);
SPCU.addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
- createAndAddScopeChildren(SPCU, Scope, *AbsDef);
+ if (DIE *ObjectPointer = createAndAddScopeChildren(SPCU, Scope, *AbsDef))
+ SPCU.addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
}
DIE &DwarfDebug::constructSubprogramScopeDIE(DwarfCompileUnit &TheCU,
DIE &ScopeDIE = updateSubprogramScopeDIE(TheCU, Sub);
- createAndAddScopeChildren(TheCU, Scope, ScopeDIE);
+ // Collect arguments for current function.
+ assert(LScopes.isCurrentFunctionScope(Scope));
+ DIE *ObjectPointer = nullptr;
+ for (DbgVariable *ArgDV : CurrentFnArguments)
+ if (ArgDV)
+ ScopeDIE.addChild(
+ constructVariableDIE(TheCU, *ArgDV, *Scope, ObjectPointer));
+
+ // If this is a variadic function, add an unspecified parameter.
+ DITypeArray FnArgs = Sub.getType().getTypeArray();
+ // If we have a single element of null, it is a function that returns void.
+ // If we have more than one elements and the last one is null, it is a
+ // variadic function.
+ if (FnArgs.getNumElements() > 1 &&
+ !FnArgs.getElement(FnArgs.getNumElements() - 1))
+ ScopeDIE.addChild(make_unique<DIE>(dwarf::DW_TAG_unspecified_parameters));
+
+ // Collect lexical scope children first.
+ // ObjectPointer might be a local (non-argument) local variable if it's a
+ // block's synthetic this pointer.
+ if (DIE *BlockObjPtr = createAndAddScopeChildren(TheCU, Scope, ScopeDIE)) {
+ assert(!ObjectPointer && "multiple object pointers can't be described");
+ ObjectPointer = BlockObjPtr;
+ }
+
+ if (ObjectPointer)
+ TheCU.addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer);
return ScopeDIE;
}
// Construct a DIE for this scope.
-std::unique_ptr<DIE> DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU,
- LexicalScope *Scope) {
+void DwarfDebug::constructScopeDIE(
+ DwarfCompileUnit &TheCU, LexicalScope *Scope,
+ SmallVectorImpl<std::unique_ptr<DIE>> &FinalChildren) {
if (!Scope || !Scope->getScopeNode())
- return nullptr;
+ return;
DIScope DS(Scope->getScopeNode());
if (Scope->getParent() && DS.isSubprogram()) {
ScopeDIE = constructInlinedScopeDIE(TheCU, Scope);
if (!ScopeDIE)
- return nullptr;
+ return;
// 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))
- return nullptr;
+ return;
+
+ unsigned ChildScopeCount;
// 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.
- createScopeChildrenDIE(TheCU, Scope, Children);
+ createScopeChildrenDIE(TheCU, Scope, Children, &ChildScopeCount);
// There is no need to emit empty lexical block DIE.
std::pair<ImportedEntityMap::const_iterator,
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);
+ Children.push_back(
+ constructImportedEntityDIE(TheCU, DIImportedEntity(i->second)));
+ // If there are only other scopes as children, put them directly in the
+ // parent instead, as this scope would serve no purpose.
+ if (Children.size() == ChildScopeCount) {
+ FinalChildren.insert(FinalChildren.end(),
+ std::make_move_iterator(Children.begin()),
+ std::make_move_iterator(Children.end()));
+ return;
+ }
+ ScopeDIE = constructLexicalScopeDIE(TheCU, Scope);
+ assert(ScopeDIE && "Scope DIE should not be null.");
}
// Add children
for (auto &I : Children)
ScopeDIE->addChild(std::move(I));
- return ScopeDIE;
+ FinalChildren.push_back(std::move(ScopeDIE));
}
void DwarfDebug::addGnuPubAttributes(DwarfUnit &U, DIE &D) const {
return NewCU;
}
-void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU,
- const MDNode *N) {
+void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,
+ const MDNode *N) {
DIImportedEntity Module(N);
assert(Module.Verify());
if (DIE *D = TheCU.getOrCreateContextDIE(Module.getContext()))
- constructImportedEntityDIE(TheCU, Module, *D);
-}
-
-void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU,
- const MDNode *N, DIE &Context) {
- DIImportedEntity Module(N);
- assert(Module.Verify());
- return constructImportedEntityDIE(TheCU, Module, Context);
+ D->addChild(constructImportedEntityDIE(TheCU, Module));
}
-void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU,
- const DIImportedEntity &Module,
- DIE &Context) {
+std::unique_ptr<DIE>
+DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU,
+ const DIImportedEntity &Module) {
assert(Module.Verify() &&
"Use one of the MDNode * overloads to handle invalid metadata");
- DIE &IMDie = TheCU.createAndAddDIE(Module.getTag(), Context, Module);
+ std::unique_ptr<DIE> IMDie = make_unique<DIE>((dwarf::Tag)Module.getTag());
+ TheCU.insertDIE(Module, IMDie.get());
DIE *EntityDie;
DIDescriptor Entity = resolve(Module.getEntity());
if (Entity.isNameSpace())
EntityDie = TheCU.getOrCreateTypeDIE(DIType(Entity));
else
EntityDie = TheCU.getDIE(Entity);
- TheCU.addSourceLine(IMDie, Module.getLineNumber(),
+ assert(EntityDie);
+ TheCU.addSourceLine(*IMDie, Module.getLineNumber(),
Module.getContext().getFilename(),
Module.getContext().getDirectory());
- TheCU.addDIEEntry(IMDie, dwarf::DW_AT_import, *EntityDie);
+ TheCU.addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie);
StringRef Name = Module.getName();
if (!Name.empty())
- TheCU.addString(IMDie, dwarf::DW_AT_name, Name);
+ TheCU.addString(*IMDie, dwarf::DW_AT_name, Name);
+
+ return IMDie;
}
// Emit all Dwarf sections that should come prior to the content. Create
ScopesWithImportedEntities.end(), less_first());
DIArray GVs = CUNode.getGlobalVariables();
for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i)
- CU.createGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i)));
+ CU.getOrCreateGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i)));
DIArray SPs = CUNode.getSubprograms();
for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i)
SPMap.insert(std::make_pair(SPs.getElement(i), &CU));
// Emit imported_modules last so that the relevant context is already
// available.
for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i)
- constructImportedEntityDIE(CU, ImportedEntities.getElement(i));
+ constructAndAddImportedEntityDIE(CU, ImportedEntities.getElement(i));
}
// Tell MMI that we have debug info.
void DwarfDebug::finishVariableDefinitions() {
for (const auto &Var : ConcreteVariables) {
DIE *VariableDie = Var->getDIE();
- // FIXME: There shouldn't be any variables without DIEs.
assert(VariableDie);
// FIXME: Consider the time-space tradeoff of just storing the unit pointer
// in the ConcreteVariables list, rather than looking it up again here.
0);
} else {
RangeSpan &Range = TheU->getRanges().back();
- U.addLocalLabelAddress(U.getUnitDie(), dwarf::DW_AT_low_pc,
- Range.getStart());
- U.addLabelDelta(U.getUnitDie(), dwarf::DW_AT_high_pc, Range.getEnd(),
- Range.getStart());
+ attachLowHighPC(U, U.getUnitDie(), Range.getStart(), Range.getEnd());
}
}
}
// arguments does the function have at source level.
if (ArgNo > Size)
CurrentFnArguments.resize(ArgNo * 2);
+ assert(!CurrentFnArguments[ArgNo - 1]);
CurrentFnArguments[ArgNo - 1] = Var;
return true;
}
// Collect variable information from side table maintained by MMI.
void DwarfDebug::collectVariableInfoFromMMITable(
- SmallPtrSet<const MDNode *, 16> &Processed) {
+ SmallPtrSetImpl<const MDNode *> &Processed) {
for (const auto &VI : MMI->getVariableDbgInfo()) {
if (!VI.Var)
continue;
// [1-3] [x, (reg0, piece 0, 32), (reg1, piece 32, 32)]
// [3-4] [x, (reg1, piece 32, 32)]
// [4- ] [x, (mem, piece 0, 64)]
-void DwarfDebug::
-buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
- const DbgValueHistoryMap::InstrRanges &Ranges,
- DwarfCompileUnit *TheCU) {
- typedef std::pair<DIVariable, DebugLocEntry::Value> Range;
- SmallVector<Range, 4> OpenRanges;
+void
+DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
+ const DbgValueHistoryMap::InstrRanges &Ranges) {
+ SmallVector<DebugLocEntry::Value, 4> OpenRanges;
for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
const MachineInstr *Begin = I->first;
assert(Begin->isDebugValue() && "Invalid History entry");
// Check if a variable is inaccessible in this range.
- if (!Begin->isDebugValue() ||
- (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg() &&
- !Begin->getOperand(0).getReg())) {
+ if (Begin->getNumOperands() > 1 &&
+ Begin->getOperand(0).isReg() && !Begin->getOperand(0).getReg()) {
OpenRanges.clear();
continue;
}
// If this piece overlaps with any open ranges, truncate them.
DIVariable DIVar = Begin->getDebugVariable();
- auto Last = std::remove_if(OpenRanges.begin(), OpenRanges.end(), [&](Range R){
- return piecesOverlap(DIVar, R.first);
- });
+ auto Last = std::remove_if(OpenRanges.begin(), OpenRanges.end(),
+ [&](DebugLocEntry::Value R) {
+ return piecesOverlap(DIVar, R.getVariable());
+ });
OpenRanges.erase(Last, OpenRanges.end());
const MCSymbol *StartLabel = getLabelBeforeInsn(Begin);
DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n");
auto Value = getDebugLocValue(Begin);
- DebugLocEntry Loc(StartLabel, EndLabel, Value, TheCU);
- if (DebugLoc.empty() || !DebugLoc.back().Merge(Loc)) {
- // Add all values from still valid non-overlapping pieces.
- for (auto Range : OpenRanges)
- Loc.addValue(Range.second);
+ DebugLocEntry Loc(StartLabel, EndLabel, Value);
+ bool couldMerge = false;
+
+ // If this is a piece, it may belong to the current DebugLocEntry.
+ if (DIVar.isVariablePiece()) {
+ // Add this value to the list of open ranges.
+ OpenRanges.push_back(Value);
+
+ // Attempt to add the piece to the last entry.
+ if (!DebugLoc.empty())
+ if (DebugLoc.back().MergeValues(Loc))
+ couldMerge = true;
+ }
+
+ if (!couldMerge) {
+ // Need to add a new DebugLocEntry. Add all values from still
+ // valid non-overlapping pieces.
+ if (OpenRanges.size())
+ Loc.addValues(OpenRanges);
+
DebugLoc.push_back(std::move(Loc));
}
- // Add this value to the list of open ranges.
- if (DIVar.isVariablePiece())
- OpenRanges.push_back(std::make_pair(DIVar, Value));
+
+ // Attempt to coalesce the ranges of two otherwise identical
+ // DebugLocEntries.
+ auto CurEntry = DebugLoc.rbegin();
+ auto PrevEntry = std::next(CurEntry);
+ if (PrevEntry != DebugLoc.rend() && PrevEntry->MergeRanges(*CurEntry))
+ DebugLoc.pop_back();
DEBUG(dbgs() << "Values:\n";
- for (auto Value : DebugLoc.back().getValues())
+ for (auto Value : CurEntry->getValues())
Value.getVariable()->dump();
dbgs() << "-----\n");
}
// Find variables for each lexical scope.
void
-DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) {
+DwarfDebug::collectVariableInfo(SmallPtrSetImpl<const MDNode *> &Processed) {
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
continue;
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()) {
+ if (MDNode *IA = DV.getInlinedAt()) {
DebugLoc DL = DebugLoc::getFromDILocation(IA);
Scope = LScopes.findInlinedScope(DebugLoc::get(
DL.getLine(), DL.getCol(), DV.getContext(), IA));
DotDebugLocEntries.resize(DotDebugLocEntries.size() + 1);
DebugLocList &LocList = DotDebugLocEntries.back();
+ LocList.CU = TheCU;
LocList.Label =
Asm->GetTempSymbol("debug_loc", DotDebugLocEntries.size() - 1);
// Build the location list for this variable.
- buildLocationList(LocList.List, Ranges, TheCU);
+ buildLocationList(LocList.List, Ranges);
}
// Collect info for variables that were optimized out.
// If we don't have a lexical scope for this function then there will
// be a hole in the range information. Keep note of this by setting the
// previously used section to nullptr.
- PrevSection = nullptr;
PrevCU = nullptr;
CurFn = nullptr;
return;
// Add the range of this function to the list of ranges for the CU.
RangeSpan Span(FunctionBeginSym, FunctionEndSym);
TheCU.addRange(std::move(Span));
- PrevSection = Asm->getCurrentSection();
- PrevCU = &TheCU;
// Clear debug info
// Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the
assert(Scope.isScope());
Fn = Scope.getFilename();
Dir = Scope.getDirectory();
- if (Scope.isLexicalBlock())
- Discriminator = DILexicalBlock(S).getDiscriminator();
+ if (Scope.isLexicalBlockFile())
+ Discriminator = DILexicalBlockFile(S).getDiscriminator();
unsigned CUID = Asm->OutStreamer.getContext().getDwarfCompileUnitID();
Src = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID])
Asm->EmitInt8(1);
}
-// Emit visible names into a hashed accelerator table section.
-void DwarfDebug::emitAccelNames() {
- AccelNames.FinalizeTable(Asm, "Names");
- Asm->OutStreamer.SwitchSection(
- Asm->getObjFileLowering().getDwarfAccelNamesSection());
- MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin");
+void DwarfDebug::emitAccel(DwarfAccelTable &Accel, const MCSection *Section,
+ StringRef TableName, StringRef SymName) {
+ Accel.FinalizeTable(Asm, TableName);
+ Asm->OutStreamer.SwitchSection(Section);
+ auto *SectionBegin = Asm->GetTempSymbol(SymName);
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
- AccelNames.Emit(Asm, SectionBegin, &InfoHolder);
+ Accel.Emit(Asm, SectionBegin, &InfoHolder, DwarfStrSectionSym);
+}
+
+// Emit visible names into a hashed accelerator table section.
+void DwarfDebug::emitAccelNames() {
+ emitAccel(AccelNames, Asm->getObjFileLowering().getDwarfAccelNamesSection(),
+ "Names", "names_begin");
}
// Emit objective C classes and categories into a hashed accelerator table
// section.
void DwarfDebug::emitAccelObjC() {
- AccelObjC.FinalizeTable(Asm, "ObjC");
- Asm->OutStreamer.SwitchSection(
- Asm->getObjFileLowering().getDwarfAccelObjCSection());
- MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin");
- Asm->OutStreamer.EmitLabel(SectionBegin);
-
- // Emit the full data.
- AccelObjC.Emit(Asm, SectionBegin, &InfoHolder);
+ emitAccel(AccelObjC, Asm->getObjFileLowering().getDwarfAccelObjCSection(),
+ "ObjC", "objc_begin");
}
// Emit namespace dies into a hashed accelerator table.
void DwarfDebug::emitAccelNamespaces() {
- AccelNamespace.FinalizeTable(Asm, "namespac");
- Asm->OutStreamer.SwitchSection(
- Asm->getObjFileLowering().getDwarfAccelNamespaceSection());
- MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin");
- Asm->OutStreamer.EmitLabel(SectionBegin);
-
- // Emit the full data.
- AccelNamespace.Emit(Asm, SectionBegin, &InfoHolder);
+ emitAccel(AccelNamespace,
+ Asm->getObjFileLowering().getDwarfAccelNamespaceSection(),
+ "namespac", "namespac_begin");
}
// Emit type dies into a hashed accelerator table.
void DwarfDebug::emitAccelTypes() {
-
- AccelTypes.FinalizeTable(Asm, "types");
- Asm->OutStreamer.SwitchSection(
- Asm->getObjFileLowering().getDwarfAccelTypesSection());
- MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin");
- Asm->OutStreamer.EmitLabel(SectionBegin);
-
- // Emit the full data.
- AccelTypes.Emit(Asm, SectionBegin, &InfoHolder);
+ emitAccel(AccelTypes, Asm->getObjFileLowering().getDwarfAccelTypesSection(),
+ "types", "types_begin");
}
// Public name handling.
void DwarfDebug::emitLocPieces(ByteStreamer &Streamer,
const DITypeIdentifierMap &Map,
ArrayRef<DebugLocEntry::Value> Values) {
- typedef DebugLocEntry::Value Piece;
- SmallVector<Piece, 4> Pieces(Values.begin(), Values.end());
- assert(std::all_of(Pieces.begin(), Pieces.end(), [](Piece &P) {
- return DIVariable(P.getVariable()).isVariablePiece();
+ assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value P) {
+ return P.isVariablePiece();
}) && "all values are expected to be pieces");
-
- // Sort the pieces so they can be emitted using DW_OP_piece.
- std::sort(Pieces.begin(), Pieces.end(), [](const Piece &A, const Piece &B) {
- DIVariable VarA(A.getVariable());
- DIVariable VarB(B.getVariable());
- return VarA.getPieceOffset() < VarB.getPieceOffset();
- });
- // Remove any duplicate entries by dropping all but the first.
- Pieces.erase(std::unique(Pieces.begin(), Pieces.end(),
- [] (const Piece &A,const Piece &B){
- return A.getVariable() == B.getVariable();
- }), Pieces.end());
+ assert(std::is_sorted(Values.begin(), Values.end()) &&
+ "pieces are expected to be sorted");
unsigned Offset = 0;
- for (auto Piece : Pieces) {
- DIVariable Var(Piece.getVariable());
+ for (auto Piece : Values) {
+ DIVariable Var = Piece.getVariable();
unsigned PieceOffset = Var.getPieceOffset();
unsigned PieceSize = Var.getPieceSize();
- assert(Offset <= PieceOffset && "overlapping pieces in DebugLocEntry");
+ assert(Offset <= PieceOffset && "overlapping or duplicate pieces");
if (Offset < PieceOffset) {
// The DWARF spec seriously mandates pieces with no locations for gaps.
Asm->EmitDwarfOpPiece(Streamer, (PieceOffset-Offset)*8);
void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
const DebugLocEntry &Entry) {
const DebugLocEntry::Value Value = Entry.getValues()[0];
- DIVariable DV(Value.getVariable());
- if (DV.isVariablePiece())
+ if (Value.isVariablePiece())
// Emit all pieces that belong to the same variable and range.
return emitLocPieces(Streamer, TypeIdentifierMap, Entry.getValues());
void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer,
const DebugLocEntry::Value &Value) {
- DIVariable DV(Value.getVariable());
+ DIVariable DV = Value.getVariable();
// Regular entry.
if (Value.isInt()) {
DIBasicType BTy(resolve(DV.getType()));
unsigned char Size = Asm->getDataLayout().getPointerSize();
for (const auto &DebugLoc : DotDebugLocEntries) {
Asm->OutStreamer.EmitLabel(DebugLoc.Label);
+ const DwarfCompileUnit *CU = DebugLoc.CU;
+ assert(!CU->getRanges().empty());
for (const auto &Entry : DebugLoc.List) {
// Set up the range. This range is relative to the entry point of the
// compile unit. This is a hard coded 0 for low_pc when we're emitting
// ranges, or the DW_AT_low_pc on the compile unit otherwise.
- const DwarfCompileUnit *CU = Entry.getCU();
if (CU->getRanges().size() == 1) {
// Grab the begin symbol from the first range as our base.
const MCSymbol *Base = CU->getRanges()[0].getStart();
return NewCU;
}
-// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_dwo_name,
-// DW_AT_addr_base.
-DwarfTypeUnit &DwarfDebug::constructSkeletonTU(DwarfTypeUnit &TU) {
- DwarfCompileUnit &CU = static_cast<DwarfCompileUnit &>(
- *SkeletonHolder.getUnits()[TU.getCU().getUniqueID()]);
-
- 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, NewTU.getUnitDie(), std::move(OwnedUnit));
- return NewTU;
-}
-
// Emit the .debug_info.dwo section for separated dwarf. This contains the
// compile units that would normally be in debug_info.
void DwarfDebug::emitDebugInfoDWO() {
assert(useSplitDwarf() && "No split dwarf?");
const MCSection *OffSec =
Asm->getObjFileLowering().getDwarfStrOffDWOSection();
- const MCSymbol *StrSym = DwarfStrSectionSym;
InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
- OffSec, StrSym);
+ OffSec);
}
MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) {
// 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));
+ for (auto &TU : TypeUnitsToAdd)
InfoHolder.addUnit(std::move(TU.first));
- }
}
CU.addDIETypeSignature(RefDie, NewTU);
}
void DwarfDebug::attachLowHighPC(DwarfCompileUnit &Unit, DIE &D,
- MCSymbol *Begin, MCSymbol *End) {
+ const MCSymbol *Begin, const MCSymbol *End) {
assert(Begin && "Begin label should not be null!");
assert(End && "End label should not be null!");
assert(Begin->isDefined() && "Invalid starting label");