[llvm] 4333146 - [NFC][AsmPrinter] Use std::visit in constructVariableDIEImpl
Scott Linder via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 11 10:33:07 PDT 2023
Author: Scott Linder
Date: 2023-09-11T17:32:00Z
New Revision: 43331461954939032a03621998c30ac90299ad40
URL: https://github.com/llvm/llvm-project/commit/43331461954939032a03621998c30ac90299ad40
DIFF: https://github.com/llvm/llvm-project/commit/43331461954939032a03621998c30ac90299ad40.diff
LOG: [NFC][AsmPrinter] Use std::visit in constructVariableDIEImpl
This potentially has a slightly positive performance impact, as
std::visit can be implemented as a `switch`-like jump rather than
a series of `if`s.
More importantly, the reader can be confident is no overlap between the
cases.
Differential Revision: https://reviews.llvm.org/D158678
Added:
Modified:
llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 25cad6743196a1e..e37dd14c96f76b3 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -771,192 +771,197 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
}
// Add variable address.
-
- if (auto *Multi = std::get_if<Loc::Multi>(&DV)) {
- addLocationList(*VariableDie, dwarf::DW_AT_location,
- Multi->getDebugLocListIndex());
- auto TagOffset = Multi->getDebugLocListTagOffset();
- if (TagOffset)
- addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1,
- *TagOffset);
- return VariableDie;
- }
-
- // Check if variable has a single location description.
- if (const auto *Single = std::get_if<Loc::Single>(&DV)) {
- const DbgValueLoc *DVal = &Single->getValueLoc();
- if (!DVal->isVariadic()) {
- const DbgValueLocEntry *Entry = DVal->getLocEntries().begin();
- if (Entry->isLocation()) {
- addVariableAddress(DV, *VariableDie, Entry->getLoc());
- } else if (Entry->isInt()) {
- auto *Expr = Single->getExpr();
- 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);
- 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 = Single->getExpr();
- 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()) {
- // DwarfExpression does not support arguments wider than 64 bits
- // (see PR52584).
- // TODO: Consider chunking expressions containing overly wide
- // arguments into separate pointer-sized fragment expressions.
- APInt RawBytes = Entry.getConstantFP()->getValueAPF().bitcastToAPInt();
- if (RawBytes.getBitWidth() > 64)
- return false;
- DwarfExpr.addUnsignedConstant(RawBytes.getZExtValue());
- } else if (Entry.isConstantInt()) {
- APInt RawBytes = Entry.getConstantInt()->getValue();
- if (RawBytes.getBitWidth() > 64)
- return false;
- DwarfExpr.addUnsignedConstant(RawBytes.getZExtValue());
- } 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;
- };
-
- if (!DwarfExpr.addExpression(
- std::move(Cursor),
- [&](unsigned Idx, DIExpressionCursor &Cursor) -> bool {
- return AddEntry(DVal->getLocEntries()[Idx], Cursor);
- }))
- return VariableDie;
-
- // 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;
- }
-
- if (auto *EntryValue = std::get_if<Loc::EntryValue>(&DV)) {
- DIELoc *Loc = new (DIEValueAllocator) DIELoc;
- DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
- // Emit each expression as: EntryValue(Register) <other ops> <Fragment>.
- for (auto [Register, Expr] : EntryValue->EntryValues) {
- DwarfExpr.addFragmentOffset(&Expr);
- DIExpressionCursor Cursor(Expr.getElements());
- DwarfExpr.beginEntryValueExpression(Cursor);
- DwarfExpr.addMachineRegExpression(
- *Asm->MF->getSubtarget().getRegisterInfo(), Cursor, Register);
- DwarfExpr.addExpression(std::move(Cursor));
- }
- addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
- return VariableDie;
- }
-
- // .. else use frame index.
- if (!DV.holds<Loc::MMI>())
- return VariableDie;
-
- std::optional<unsigned> NVPTXAddressSpace;
- DIELoc *Loc = new (DIEValueAllocator) DIELoc;
- DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
- for (const auto &Fragment : DV.get<Loc::MMI>().getFrameIndexExprs()) {
- Register FrameReg;
- const DIExpression *Expr = Fragment.Expr;
- const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
- StackOffset Offset =
- TFI->getFrameIndexReference(*Asm->MF, Fragment.FI, FrameReg);
- DwarfExpr.addFragmentOffset(Expr);
-
- auto *TRI = Asm->MF->getSubtarget().getRegisterInfo();
- SmallVector<uint64_t, 8> Ops;
- TRI->getOffsetOpcodes(Offset, Ops);
-
- // According to
- // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf
- // cuda-gdb requires DW_AT_address_class for all variables to be able to
- // correctly interpret address space of the variable address.
- // Decode DW_OP_constu <DWARF Address Space> DW_OP_swap DW_OP_xderef
- // sequence for the NVPTX + gdb target.
- unsigned LocalNVPTXAddressSpace;
- if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
- const DIExpression *NewExpr =
- DIExpression::extractAddressClass(Expr, LocalNVPTXAddressSpace);
- if (NewExpr != Expr) {
- Expr = NewExpr;
- NVPTXAddressSpace = LocalNVPTXAddressSpace;
- }
- }
- if (Expr)
- Ops.append(Expr->elements_begin(), Expr->elements_end());
- DIExpressionCursor Cursor(Ops);
- DwarfExpr.setMemoryLocationKind();
- if (const MCSymbol *FrameSymbol = Asm->getFunctionFrameSymbol())
- addOpAddress(*Loc, FrameSymbol);
- else
- DwarfExpr.addMachineRegExpression(
- *Asm->MF->getSubtarget().getRegisterInfo(), Cursor, FrameReg);
- DwarfExpr.addExpression(std::move(Cursor));
- }
- if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
- // According to
- // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf
- // cuda-gdb requires DW_AT_address_class for all variables to be able to
- // correctly interpret address space of the variable address.
- const unsigned NVPTX_ADDR_local_space = 6;
- addUInt(*VariableDie, dwarf::DW_AT_address_class, dwarf::DW_FORM_data1,
- NVPTXAddressSpace.value_or(NVPTX_ADDR_local_space));
- }
- 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);
+ std::visit(
+ makeVisitor(
+ [=, &DV](const Loc::Single &Single) {
+ const DbgValueLoc *DVal = &Single.getValueLoc();
+ if (!DVal->isVariadic()) {
+ const DbgValueLocEntry *Entry = DVal->getLocEntries().begin();
+ if (Entry->isLocation()) {
+ addVariableAddress(DV, *VariableDie, Entry->getLoc());
+ } else if (Entry->isInt()) {
+ auto *Expr = Single.getExpr();
+ 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);
+ 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;
+ }
+ // 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;
+ const DIExpression *Expr = Single.getExpr();
+ 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()) {
+ // DwarfExpression does not support arguments wider than 64 bits
+ // (see PR52584).
+ // TODO: Consider chunking expressions containing overly wide
+ // arguments into separate pointer-sized fragment expressions.
+ APInt RawBytes =
+ Entry.getConstantFP()->getValueAPF().bitcastToAPInt();
+ if (RawBytes.getBitWidth() > 64)
+ return false;
+ DwarfExpr.addUnsignedConstant(RawBytes.getZExtValue());
+ } else if (Entry.isConstantInt()) {
+ APInt RawBytes = Entry.getConstantInt()->getValue();
+ if (RawBytes.getBitWidth() > 64)
+ return false;
+ DwarfExpr.addUnsignedConstant(RawBytes.getZExtValue());
+ } 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;
+ };
+
+ if (!DwarfExpr.addExpression(
+ std::move(Cursor),
+ [&](unsigned Idx, DIExpressionCursor &Cursor) -> bool {
+ return AddEntry(DVal->getLocEntries()[Idx], Cursor);
+ }))
+ return;
+
+ // 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);
+ },
+ [=](const Loc::Multi &Multi) {
+ addLocationList(*VariableDie, dwarf::DW_AT_location,
+ Multi.getDebugLocListIndex());
+ auto TagOffset = Multi.getDebugLocListTagOffset();
+ if (TagOffset)
+ addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset,
+ dwarf::DW_FORM_data1, *TagOffset);
+ },
+ [=](const Loc::MMI &MMI) {
+ std::optional<unsigned> NVPTXAddressSpace;
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
+ for (const auto &Fragment : MMI.getFrameIndexExprs()) {
+ Register FrameReg;
+ const DIExpression *Expr = Fragment.Expr;
+ const TargetFrameLowering *TFI =
+ Asm->MF->getSubtarget().getFrameLowering();
+ StackOffset Offset =
+ TFI->getFrameIndexReference(*Asm->MF, Fragment.FI, FrameReg);
+ DwarfExpr.addFragmentOffset(Expr);
+
+ auto *TRI = Asm->MF->getSubtarget().getRegisterInfo();
+ SmallVector<uint64_t, 8> Ops;
+ TRI->getOffsetOpcodes(Offset, Ops);
+
+ // According to
+ // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf
+ // cuda-gdb requires DW_AT_address_class for all variables to be
+ // able to correctly interpret address space of the variable
+ // address. Decode DW_OP_constu <DWARF Address Space> DW_OP_swap
+ // DW_OP_xderef sequence for the NVPTX + gdb target.
+ unsigned LocalNVPTXAddressSpace;
+ if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
+ const DIExpression *NewExpr = DIExpression::extractAddressClass(
+ Expr, LocalNVPTXAddressSpace);
+ if (NewExpr != Expr) {
+ Expr = NewExpr;
+ NVPTXAddressSpace = LocalNVPTXAddressSpace;
+ }
+ }
+ if (Expr)
+ Ops.append(Expr->elements_begin(), Expr->elements_end());
+ DIExpressionCursor Cursor(Ops);
+ DwarfExpr.setMemoryLocationKind();
+ if (const MCSymbol *FrameSymbol = Asm->getFunctionFrameSymbol())
+ addOpAddress(*Loc, FrameSymbol);
+ else
+ DwarfExpr.addMachineRegExpression(
+ *Asm->MF->getSubtarget().getRegisterInfo(), Cursor,
+ FrameReg);
+ DwarfExpr.addExpression(std::move(Cursor));
+ }
+ if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
+ // According to
+ // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf
+ // cuda-gdb requires DW_AT_address_class for all variables to be
+ // able to correctly interpret address space of the variable
+ // address.
+ const unsigned NVPTX_ADDR_local_space = 6;
+ addUInt(*VariableDie, dwarf::DW_AT_address_class,
+ dwarf::DW_FORM_data1,
+ NVPTXAddressSpace.value_or(NVPTX_ADDR_local_space));
+ }
+ 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);
+ },
+ [=](const Loc::EntryValue &EntryValue) {
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
+ // Emit each expression as: EntryValue(Register) <other ops>
+ // <Fragment>.
+ for (auto [Register, Expr] : EntryValue.EntryValues) {
+ DwarfExpr.addFragmentOffset(&Expr);
+ DIExpressionCursor Cursor(Expr.getElements());
+ DwarfExpr.beginEntryValueExpression(Cursor);
+ DwarfExpr.addMachineRegExpression(
+ *Asm->MF->getSubtarget().getRegisterInfo(), Cursor, Register);
+ DwarfExpr.addExpression(std::move(Cursor));
+ }
+ addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
+ },
+ [](const std::monostate &) {}),
+ DV.asVariant());
return VariableDie;
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index d675bae190d5d38..e8b0f3178939dc8 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -186,6 +186,9 @@ struct EntryValue {
EntryValues.insert({Reg, **NonVariadicExpr});
}
};
+/// Alias for the std::variant specialization base class of DbgVariable.
+using Variant = std::variant<std::monostate, Loc::Single, Loc::Multi, Loc::MMI,
+ Loc::EntryValue>;
} // namespace Loc
//===----------------------------------------------------------------------===//
@@ -209,11 +212,16 @@ struct EntryValue {
/// DebugLocListIndex and (optionally) \c DebugLocListTagOffset, while those
/// with a single location hold a \c Loc::Single alternative which use \c
/// ValueLoc and (optionally) a single \c Expr.
-class DbgVariable : public DbgEntity,
- public std::variant<std::monostate, Loc::Single, Loc::Multi,
- Loc::MMI, Loc::EntryValue> {
+class DbgVariable : public DbgEntity, public Loc::Variant {
public:
+ /// To workaround P2162R0 https://github.com/cplusplus/papers/issues/873 the
+ /// base class subobject needs to be passed directly to std::visit, so expose
+ /// it directly here.
+ Loc::Variant &asVariant() { return *static_cast<Loc::Variant *>(this); }
+ const Loc::Variant &asVariant() const {
+ return *static_cast<const Loc::Variant *>(this);
+ }
/// Member shorthand for std::holds_alternative
template <typename T> bool holds() const {
return std::holds_alternative<T>(*this);
More information about the llvm-commits
mailing list