[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