summaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp181
1 files changed, 135 insertions, 46 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index befc4bba19a2..faa14dca1c3f 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -16,6 +16,7 @@
#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/CodeGen/MachineFunction.h"
@@ -73,11 +74,35 @@ void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute,
if (Label)
DD->addArangeLabel(SymbolCU(this, Label));
- unsigned idx = DD->getAddressPool().getIndex(Label);
- Die.addValue(DIEValueAllocator, Attribute,
- DD->getDwarfVersion() >= 5 ? dwarf::DW_FORM_addrx
- : dwarf::DW_FORM_GNU_addr_index,
- DIEInteger(idx));
+ bool UseAddrOffsetFormOrExpressions =
+ DD->useAddrOffsetForm() || DD->useAddrOffsetExpressions();
+
+ const MCSymbol *Base = nullptr;
+ if (Label->isInSection() && UseAddrOffsetFormOrExpressions)
+ Base = DD->getSectionLabel(&Label->getSection());
+
+ if (!Base || Base == Label) {
+ unsigned idx = DD->getAddressPool().getIndex(Label);
+ addAttribute(Die, Attribute,
+ DD->getDwarfVersion() >= 5 ? dwarf::DW_FORM_addrx
+ : dwarf::DW_FORM_GNU_addr_index,
+ DIEInteger(idx));
+ return;
+ }
+
+ // Could be extended to work with DWARFv4 Split DWARF if that's important for
+ // someone. In that case DW_FORM_data would be used.
+ assert(DD->getDwarfVersion() >= 5 &&
+ "Addr+offset expressions are only valuable when using debug_addr (to "
+ "reduce relocations) available in DWARFv5 or higher");
+ if (DD->useAddrOffsetExpressions()) {
+ auto *Loc = new (DIEValueAllocator) DIEBlock();
+ addPoolOpAddress(*Loc, Label);
+ addBlock(Die, Attribute, dwarf::DW_FORM_exprloc, Loc);
+ } else
+ addAttribute(Die, Attribute, dwarf::DW_FORM_LLVM_addrx_offset,
+ new (DIEValueAllocator) DIEAddrOffset(
+ DD->getAddressPool().getIndex(Base), Label, Base));
}
void DwarfCompileUnit::addLocalLabelAddress(DIE &Die,
@@ -87,11 +112,9 @@ void DwarfCompileUnit::addLocalLabelAddress(DIE &Die,
DD->addArangeLabel(SymbolCU(this, Label));
if (Label)
- Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_addr,
- DIELabel(Label));
+ addAttribute(Die, Attribute, dwarf::DW_FORM_addr, DIELabel(Label));
else
- Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_addr,
- DIEInteger(0));
+ addAttribute(Die, Attribute, dwarf::DW_FORM_addr, DIEInteger(0));
}
unsigned DwarfCompileUnit::getOrCreateSourceID(const DIFile *File) {
@@ -184,11 +207,16 @@ void DwarfCompileUnit::addLocationAttribute(
const DIExpression *Expr = GE.Expr;
// For compatibility with DWARF 3 and earlier,
- // DW_AT_location(DW_OP_constu, X, DW_OP_stack_value) becomes
+ // DW_AT_location(DW_OP_constu, X, DW_OP_stack_value) or
+ // DW_AT_location(DW_OP_consts, X, DW_OP_stack_value) becomes
// DW_AT_const_value(X).
if (GlobalExprs.size() == 1 && Expr && Expr->isConstant()) {
addToAccelTable = true;
- addConstantValue(*VariableDIE, /*Unsigned=*/true, Expr->getElement(1));
+ addConstantValue(
+ *VariableDIE,
+ DIExpression::SignedOrUnsignedConstant::UnsignedConstant ==
+ *Expr->isConstant(),
+ Expr->getElement(1));
break;
}
@@ -422,10 +450,7 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {
// FIXME: duplicated from Target/WebAssembly/WebAssembly.h
// don't want to depend on target specific headers in this code?
const unsigned TI_GLOBAL_RELOC = 3;
- // FIXME: when writing dwo, we need to avoid relocations. Probably
- // the "right" solution is to treat globals the way func and data symbols
- // are (with entries in .debug_addr).
- if (FrameBase.Location.WasmLoc.Kind == TI_GLOBAL_RELOC && !isDwoUnit()) {
+ if (FrameBase.Location.WasmLoc.Kind == TI_GLOBAL_RELOC) {
// These need to be relocatable.
assert(FrameBase.Location.WasmLoc.Index == 0); // Only SP so far.
auto SPSym = cast<MCSymbolWasm>(
@@ -443,8 +468,16 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_WASM_location);
addSInt(*Loc, dwarf::DW_FORM_sdata, TI_GLOBAL_RELOC);
- addLabel(*Loc, dwarf::DW_FORM_data4, SPSym);
- DD->addArangeLabel(SymbolCU(this, SPSym));
+ if (!isDwoUnit()) {
+ addLabel(*Loc, dwarf::DW_FORM_data4, SPSym);
+ DD->addArangeLabel(SymbolCU(this, SPSym));
+ } else {
+ // FIXME: when writing dwo, we need to avoid relocations. Probably
+ // the "right" solution is to treat globals the way func and data
+ // symbols are (with entries in .debug_addr).
+ // For now, since we only ever use index 0, this should work as-is.
+ addUInt(*Loc, dwarf::DW_FORM_data4, FrameBase.Location.WasmLoc.Index);
+ }
addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value);
addBlock(*SPDie, dwarf::DW_AT_frame_base, Loc);
} else {
@@ -698,36 +731,92 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
// Check if variable has a single location description.
if (auto *DVal = DV.getValueLoc()) {
- if (DVal->isLocation())
- addVariableAddress(DV, *VariableDie, DVal->getLoc());
- else if (DVal->isInt()) {
- auto *Expr = DV.getSingleExpression();
- if (Expr && Expr->getNumElements()) {
+ if (!DVal->isVariadic()) {
+ const DbgValueLocEntry *Entry = DVal->getLocEntries().begin();
+ if (Entry->isLocation()) {
+ addVariableAddress(DV, *VariableDie, Entry->getLoc());
+ } else if (Entry->isInt()) {
+ auto *Expr = DV.getSingleExpression();
+ if (Expr && Expr->getNumElements()) {
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
+ // If there is an expression, emit raw unsigned bytes.
+ DwarfExpr.addFragmentOffset(Expr);
+ DwarfExpr.addUnsignedConstant(Entry->getInt());
+ DwarfExpr.addExpression(Expr);
+ addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
+ if (DwarfExpr.TagOffset)
+ addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset,
+ dwarf::DW_FORM_data1, *DwarfExpr.TagOffset);
+ } else
+ addConstantValue(*VariableDie, Entry->getInt(), DV.getType());
+ } else if (Entry->isConstantFP()) {
+ addConstantFPValue(*VariableDie, Entry->getConstantFP());
+ } else if (Entry->isConstantInt()) {
+ addConstantValue(*VariableDie, Entry->getConstantInt(), DV.getType());
+ } else if (Entry->isTargetIndexLocation()) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
- // If there is an expression, emit raw unsigned bytes.
- DwarfExpr.addFragmentOffset(Expr);
- DwarfExpr.addUnsignedConstant(DVal->getInt());
- DwarfExpr.addExpression(Expr);
+ const DIBasicType *BT = dyn_cast<DIBasicType>(
+ static_cast<const Metadata *>(DV.getVariable()->getType()));
+ DwarfDebug::emitDebugLocValue(*Asm, BT, *DVal, DwarfExpr);
addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
- if (DwarfExpr.TagOffset)
- addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset,
- dwarf::DW_FORM_data1, *DwarfExpr.TagOffset);
-
- } else
- addConstantValue(*VariableDie, DVal->getInt(), DV.getType());
- } else if (DVal->isConstantFP()) {
- addConstantFPValue(*VariableDie, DVal->getConstantFP());
- } else if (DVal->isConstantInt()) {
- addConstantValue(*VariableDie, DVal->getConstantInt(), DV.getType());
- } else if (DVal->isTargetIndexLocation()) {
- DIELoc *Loc = new (DIEValueAllocator) DIELoc;
- DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
- const DIBasicType *BT = dyn_cast<DIBasicType>(
- static_cast<const Metadata *>(DV.getVariable()->getType()));
- DwarfDebug::emitDebugLocValue(*Asm, BT, *DVal, DwarfExpr);
- addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
+ }
+ return VariableDie;
}
+ // If any of the location entries are registers with the value 0, then the
+ // location is undefined.
+ if (any_of(DVal->getLocEntries(), [](const DbgValueLocEntry &Entry) {
+ return Entry.isLocation() && !Entry.getLoc().getReg();
+ }))
+ return VariableDie;
+ const DIExpression *Expr = DV.getSingleExpression();
+ assert(Expr && "Variadic Debug Value must have an Expression.");
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
+ DwarfExpr.addFragmentOffset(Expr);
+ DIExpressionCursor Cursor(Expr);
+ const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
+
+ auto AddEntry = [&](const DbgValueLocEntry &Entry,
+ DIExpressionCursor &Cursor) {
+ if (Entry.isLocation()) {
+ if (!DwarfExpr.addMachineRegExpression(TRI, Cursor,
+ Entry.getLoc().getReg()))
+ return false;
+ } else if (Entry.isInt()) {
+ // If there is an expression, emit raw unsigned bytes.
+ DwarfExpr.addUnsignedConstant(Entry.getInt());
+ } else if (Entry.isConstantFP()) {
+ APInt RawBytes = Entry.getConstantFP()->getValueAPF().bitcastToAPInt();
+ DwarfExpr.addUnsignedConstant(RawBytes);
+ } else if (Entry.isConstantInt()) {
+ APInt RawBytes = Entry.getConstantInt()->getValue();
+ DwarfExpr.addUnsignedConstant(RawBytes);
+ } else if (Entry.isTargetIndexLocation()) {
+ TargetIndexLocation Loc = Entry.getTargetIndexLocation();
+ // TODO TargetIndexLocation is a target-independent. Currently only the
+ // WebAssembly-specific encoding is supported.
+ assert(Asm->TM.getTargetTriple().isWasm());
+ DwarfExpr.addWasmLocation(Loc.Index, static_cast<uint64_t>(Loc.Offset));
+ } else {
+ llvm_unreachable("Unsupported Entry type.");
+ }
+ return true;
+ };
+
+ DwarfExpr.addExpression(
+ std::move(Cursor),
+ [&](unsigned Idx, DIExpressionCursor &Cursor) -> bool {
+ return AddEntry(DVal->getLocEntries()[Idx], Cursor);
+ });
+
+ // Now attach the location information to the DIE.
+ addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
+ if (DwarfExpr.TagOffset)
+ addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1,
+ *DwarfExpr.TagOffset);
+
return VariableDie;
}
@@ -1381,7 +1470,7 @@ void DwarfCompileUnit::addLocationList(DIE &Die, dwarf::Attribute Attribute,
dwarf::Form Form = (DD->getDwarfVersion() >= 5)
? dwarf::DW_FORM_loclistx
: DD->getDwarfSectionOffsetForm();
- Die.addValue(DIEValueAllocator, Attribute, Form, DIELocList(Index));
+ addAttribute(Die, Attribute, Form, DIELocList(Index));
}
void DwarfCompileUnit::applyVariableAttributes(const DbgVariable &Var,
@@ -1413,7 +1502,7 @@ void DwarfCompileUnit::applyLabelAttributes(const DbgLabel &Label,
/// Add a Dwarf expression attribute data and value.
void DwarfCompileUnit::addExpr(DIELoc &Die, dwarf::Form Form,
const MCExpr *Expr) {
- Die.addValue(DIEValueAllocator, (dwarf::Attribute)0, Form, DIEExpr(Expr));
+ addAttribute(Die, (dwarf::Attribute)0, Form, DIEExpr(Expr));
}
void DwarfCompileUnit::applySubprogramAttributesToDefinition(
@@ -1447,7 +1536,7 @@ void DwarfCompileUnit::addAddrTableBase() {
}
void DwarfCompileUnit::addBaseTypeRef(DIEValueList &Die, int64_t Idx) {
- Die.addValue(DIEValueAllocator, (dwarf::Attribute)0, dwarf::DW_FORM_udata,
+ addAttribute(Die, (dwarf::Attribute)0, dwarf::DW_FORM_udata,
new (DIEValueAllocator) DIEBaseTypeRef(this, Idx));
}