summaryrefslogtreecommitdiff
path: root/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp')
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp189
1 files changed, 152 insertions, 37 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index c8cd8eb8ffd3..32271a0ef24a 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -28,7 +28,6 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
@@ -40,6 +39,7 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <algorithm>
@@ -94,16 +94,18 @@ void DwarfCompileUnit::addLocalLabelAddress(DIE &Die,
DIEInteger(0));
}
-unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName,
- StringRef DirName) {
+unsigned DwarfCompileUnit::getOrCreateSourceID(const DIFile *File) {
// If we print assembly, we can't separate .file entries according to
// compile units. Thus all files will belong to the default compile unit.
// FIXME: add a better feature test than hasRawTextSupport. Even better,
// extend .file to support this.
+ unsigned CUID = Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID();
+ if (!File)
+ return Asm->OutStreamer->EmitDwarfFileDirective(0, "", "", nullptr, None, CUID);
return Asm->OutStreamer->EmitDwarfFileDirective(
- 0, DirName, FileName,
- Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID());
+ 0, File->getDirectory(), File->getFilename(), getMD5AsBytes(File),
+ File->getSource(), CUID);
}
DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
@@ -190,10 +192,13 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
DwarfExpr = llvm::make_unique<DIEDwarfExpression>(*Asm, *this, *Loc);
}
+ if (Expr)
+ DwarfExpr->addFragmentOffset(Expr);
+
if (Global) {
const MCSymbol *Sym = Asm->getSymbol(Global);
if (Global->isThreadLocal()) {
- if (Asm->TM.Options.EmulatedTLS) {
+ if (Asm->TM.useEmulatedTLS()) {
// TODO: add debug info for emulated thread local mode.
} else {
// FIXME: Make this work with -gsplit-dwarf.
@@ -225,10 +230,13 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
addOpAddress(*Loc, Sym);
}
}
- if (Expr) {
- DwarfExpr->addFragmentOffset(Expr);
- DwarfExpr->addExpression(Expr);
- }
+ // Global variables attached to symbols are memory locations.
+ // It would be better if this were unconditional, but malformed input that
+ // mixes non-fragments and fragments for the same variable is too expensive
+ // to detect in the verifier.
+ if (DwarfExpr->isUnknownLocation())
+ DwarfExpr->setMemoryLocationKind();
+ DwarfExpr->addExpression(Expr);
}
if (Loc)
addBlock(*VariableDIE, dwarf::DW_AT_location, DwarfExpr->finalize());
@@ -241,7 +249,8 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
// If the linkage name is different than the name, go ahead and output
// that as well into the name table.
- if (GV->getLinkageName() != "" && GV->getName() != GV->getLinkageName())
+ if (GV->getLinkageName() != "" && GV->getName() != GV->getLinkageName() &&
+ DD->useAllLinkageNames())
DD->addAccelName(GV->getLinkageName(), *VariableDIE);
}
@@ -267,15 +276,20 @@ void DwarfCompileUnit::addRange(RangeSpan Range) {
void DwarfCompileUnit::initStmtList() {
// Define start line table label for each Compile Unit.
- MCSymbol *LineTableStartSym =
- Asm->OutStreamer->getDwarfLineTableSymbol(getUniqueID());
+ MCSymbol *LineTableStartSym;
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+ if (DD->useSectionsAsReferences()) {
+ LineTableStartSym = TLOF.getDwarfLineSection()->getBeginSymbol();
+ } else {
+ LineTableStartSym =
+ Asm->OutStreamer->getDwarfLineTableSymbol(getUniqueID());
+ }
// DW_AT_stmt_list is a offset of line number information for this
// compile unit in debug_line section. For split dwarf this is
// left in the skeleton CU and so not included.
// The line table entries are not always emitted in assembly, so it
// is not okay to use line_table_start here.
- const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
StmtListValue =
addSectionLabel(getUnitDie(), dwarf::DW_AT_stmt_list, LineTableStartSym,
TLOF.getDwarfLineSection()->getBeginSymbol());
@@ -313,10 +327,16 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {
// Only include DW_AT_frame_base in full debug info
if (!includeMinimalInlineScopes()) {
- const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo();
- MachineLocation Location(RI->getFrameRegister(*Asm->MF));
- if (RI->isPhysicalRegister(Location.getReg()))
- addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
+ if (Asm->MF->getTarget().getTargetTriple().isNVPTX()) {
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_call_frame_cfa);
+ addBlock(*SPDie, dwarf::DW_AT_frame_base, Loc);
+ } else {
+ const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo();
+ MachineLocation Location(RI->getFrameRegister(*Asm->MF));
+ if (RI->isPhysicalRegister(Location.getReg()))
+ addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
+ }
}
// Add name to the name table, we do this here because we're guaranteed
@@ -385,21 +405,28 @@ void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE,
SmallVector<RangeSpan, 2> Range) {
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
- // Emit offset in .debug_range as a relocatable label. emitDIE will handle
- // emitting it appropriately.
+ // Emit the offset into .debug_ranges or .debug_rnglists as a relocatable
+ // label. emitDIE() will handle emitting it appropriately.
const MCSymbol *RangeSectionSym =
- TLOF.getDwarfRangesSection()->getBeginSymbol();
+ DD->getDwarfVersion() >= 5
+ ? TLOF.getDwarfRnglistsSection()->getBeginSymbol()
+ : TLOF.getDwarfRangesSection()->getBeginSymbol();
RangeSpanList List(Asm->createTempSymbol("debug_ranges"), std::move(Range));
// Under fission, ranges are specified by constant offsets relative to the
// CU's DW_AT_GNU_ranges_base.
- if (isDwoUnit())
- addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
- RangeSectionSym);
- else
+ // FIXME: For DWARF v5, do not generate the DW_AT_ranges attribute under
+ // fission until we support the forms using the .debug_addr section
+ // (DW_RLE_startx_endx etc.).
+ if (isDwoUnit()) {
+ if (DD->getDwarfVersion() < 5)
+ addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
+ RangeSectionSym);
+ } else {
addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
RangeSectionSym);
+ }
// Add the range list to the set of ranges to be emitted.
(Skeleton ? Skeleton : this)->CURangeLists.push_back(std::move(List));
@@ -407,9 +434,10 @@ void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE,
void DwarfCompileUnit::attachRangesOrLowHighPC(
DIE &Die, SmallVector<RangeSpan, 2> Ranges) {
- if (Ranges.size() == 1) {
- const auto &single = Ranges.front();
- attachLowHighPC(Die, single.getStart(), single.getEnd());
+ if (Ranges.size() == 1 || !DD->useRangesSection()) {
+ const RangeSpan &Front = Ranges.front();
+ const RangeSpan &Back = Ranges.back();
+ attachLowHighPC(Die, Front.getStart(), Back.getEnd());
} else
addScopeRangeList(Die, std::move(Ranges));
}
@@ -443,7 +471,7 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope) {
// Add the call site information to the DIE.
const DILocation *IA = Scope->getInlinedAt();
addUInt(*ScopeDIE, dwarf::DW_AT_call_file, None,
- getOrCreateSourceID(IA->getFilename(), IA->getDirectory()));
+ getOrCreateSourceID(IA->getFile()));
addUInt(*ScopeDIE, dwarf::DW_AT_call_line, None, IA->getLine());
if (IA->getDiscriminator() && DD->getDwarfVersion() >= 4)
addUInt(*ScopeDIE, dwarf::DW_AT_GNU_discriminator, None,
@@ -482,6 +510,7 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
bool Abstract) {
// Define variable debug information entry.
auto VariableDie = DIE::get(DIEValueAllocator, DV.getTag());
+ insertDIE(DV.getVariable(), VariableDie);
if (Abstract) {
applyVariableAttributes(DV, *VariableDie);
@@ -547,8 +576,11 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
Ops.append(Expr->elements_begin(), Expr->elements_end());
DIExpressionCursor Cursor(Ops);
DwarfExpr.setMemoryLocationKind();
- DwarfExpr.addMachineRegExpression(
- *Asm->MF->getSubtarget().getRegisterInfo(), Cursor, FrameReg);
+ if (const MCSymbol *FrameSymbol = Asm->getFunctionFrameSymbol())
+ addOpAddress(*Loc, FrameSymbol);
+ else
+ DwarfExpr.addMachineRegExpression(
+ *Asm->MF->getSubtarget().getRegisterInfo(), Cursor, FrameReg);
DwarfExpr.addExpression(std::move(Cursor));
}
addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
@@ -565,13 +597,95 @@ DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV,
return Var;
}
+/// Return all DIVariables that appear in count: expressions.
+static SmallVector<const DIVariable *, 2> dependencies(DbgVariable *Var) {
+ SmallVector<const DIVariable *, 2> Result;
+ auto *Array = dyn_cast<DICompositeType>(Var->getType());
+ if (!Array || Array->getTag() != dwarf::DW_TAG_array_type)
+ return Result;
+ for (auto *El : Array->getElements()) {
+ if (auto *Subrange = dyn_cast<DISubrange>(El)) {
+ auto Count = Subrange->getCount();
+ if (auto *Dependency = Count.dyn_cast<DIVariable *>())
+ Result.push_back(Dependency);
+ }
+ }
+ return Result;
+}
+
+/// Sort local variables so that variables appearing inside of helper
+/// expressions come first.
+static SmallVector<DbgVariable *, 8>
+sortLocalVars(SmallVectorImpl<DbgVariable *> &Input) {
+ SmallVector<DbgVariable *, 8> Result;
+ SmallVector<PointerIntPair<DbgVariable *, 1>, 8> WorkList;
+ // Map back from a DIVariable to its containing DbgVariable.
+ SmallDenseMap<const DILocalVariable *, DbgVariable *> DbgVar;
+ // Set of DbgVariables in Result.
+ SmallDenseSet<DbgVariable *, 8> Visited;
+ // For cycle detection.
+ SmallDenseSet<DbgVariable *, 8> Visiting;
+
+ // Initialize the worklist and the DIVariable lookup table.
+ for (auto Var : reverse(Input)) {
+ DbgVar.insert({Var->getVariable(), Var});
+ WorkList.push_back({Var, 0});
+ }
+
+ // Perform a stable topological sort by doing a DFS.
+ while (!WorkList.empty()) {
+ auto Item = WorkList.back();
+ DbgVariable *Var = Item.getPointer();
+ bool visitedAllDependencies = Item.getInt();
+ WorkList.pop_back();
+
+ // Dependency is in a different lexical scope or a global.
+ if (!Var)
+ continue;
+
+ // Already handled.
+ if (Visited.count(Var))
+ continue;
+
+ // Add to Result if all dependencies are visited.
+ if (visitedAllDependencies) {
+ Visited.insert(Var);
+ Result.push_back(Var);
+ continue;
+ }
+
+ // Detect cycles.
+ auto Res = Visiting.insert(Var);
+ if (!Res.second) {
+ assert(false && "dependency cycle in local variables");
+ return Result;
+ }
+
+ // Push dependencies and this node onto the worklist, so that this node is
+ // visited again after all of its dependencies are handled.
+ WorkList.push_back({Var, 1});
+ for (auto *Dependency : dependencies(Var)) {
+ auto Dep = dyn_cast_or_null<const DILocalVariable>(Dependency);
+ WorkList.push_back({DbgVar[Dep], 0});
+ }
+ }
+ return Result;
+}
+
DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope,
SmallVectorImpl<DIE *> &Children,
bool *HasNonScopeChildren) {
assert(Children.empty());
DIE *ObjectPointer = nullptr;
- for (DbgVariable *DV : DU->getScopeVariables().lookup(Scope))
+ // Emit function arguments (order is significant).
+ auto Vars = DU->getScopeVariables().lookup(Scope);
+ for (auto &DV : Vars.Args)
+ Children.push_back(constructVariableDIE(*DV.second, *Scope, ObjectPointer));
+
+ // Emit local variables.
+ auto Locals = sortLocalVars(Vars.Locals);
+ for (DbgVariable *DV : Locals)
Children.push_back(constructVariableDIE(*DV, *Scope, ObjectPointer));
// Skip imported directives in gmlt-like data.
@@ -687,9 +801,7 @@ DIE *DwarfCompileUnit::constructImportedEntityDIE(
else
EntityDie = getDIE(Entity);
assert(EntityDie);
- auto *File = Module->getFile();
- addSourceLine(*IMDie, Module->getLine(), File ? File->getFilename() : "",
- File ? File->getDirectory() : "");
+ addSourceLine(*IMDie, Module->getLine(), Module->getFile());
addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie);
StringRef Name = Module->getName();
if (!Name.empty())
@@ -750,7 +862,7 @@ void DwarfCompileUnit::createAbstractVariable(const DILocalVariable *Var,
void DwarfCompileUnit::emitHeader(bool UseOffsets) {
// Don't bother labeling the .dwo unit, as its offset isn't used.
- if (!Skeleton) {
+ if (!Skeleton && !DD->useSectionsAsReferences()) {
LabelBegin = Asm->createTempSymbol("cu_begin");
Asm->OutStreamer->EmitLabel(LabelBegin);
}
@@ -759,6 +871,8 @@ void DwarfCompileUnit::emitHeader(bool UseOffsets) {
: DD->useSplitDwarf() ? dwarf::DW_UT_skeleton
: dwarf::DW_UT_compile;
DwarfUnit::emitCommonHeader(UseOffsets, UT);
+ if (DD->getDwarfVersion() >= 5 && UT != dwarf::DW_UT_compile)
+ Asm->emitInt64(getDWOId());
}
bool DwarfCompileUnit::hasDwarfPubSections() const {
@@ -767,7 +881,8 @@ bool DwarfCompileUnit::hasDwarfPubSections() const {
if (CUNode->getGnuPubnames())
return true;
- return DD->tuneForGDB() && !includeMinimalInlineScopes();
+ return DD->tuneForGDB() && DD->usePubSections() &&
+ !includeMinimalInlineScopes();
}
/// addGlobalName - Add a new global name to the compile unit.