[llvm] Allow DWARF expressions to refer to variable values (PR #181028)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 11 13:47:13 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-ir
Author: Tom Tromey (tromey)
<details>
<summary>Changes</summary>
In Ada, it is possible for a type to refer to the value of local variables. In many cases this can be described in the DWARF using existing LLVM constructs. However, in some cases, a DWARF expression that uses multiple variables can be required.
This patch adds a mechanism to allow this. It adds a new DIVariableExpression class. This class holds a DIExpression and a list of variables. When DWARF is emitted, each DW_OP_LLVM_arg in the expression is changed to a DW_OP_GNU_variable_value referencing the variable's DIE.
DW_OP_GNU_variable_value has been in use in GCC for years. This has also been proposed for DWARF 6, though unfortunately it seems to have stalled:
http://dwarfstd.org/ShowIssue.php?issue=161109.2
At present this feature is only supported for member offsets and sizes, and the size of a DICompositeType. These are just the spots that I know are needed by gnat-llvm.
---
Patch is 27.29 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/181028.diff
22 Files Affected:
- (modified) llvm/docs/LangRef.rst (+14)
- (modified) llvm/include/llvm-c/DebugInfo.h (+1)
- (modified) llvm/include/llvm/BinaryFormat/Dwarf.def (+4)
- (modified) llvm/include/llvm/Bitcode/LLVMBitCodes.h (+1)
- (modified) llvm/include/llvm/IR/DIBuilder.h (+9)
- (modified) llvm/include/llvm/IR/DebugInfoMetadata.h (+48)
- (modified) llvm/include/llvm/IR/Metadata.def (+1)
- (modified) llvm/lib/AsmParser/LLParser.cpp (+14)
- (modified) llvm/lib/Bitcode/Reader/MetadataLoader.cpp (+13)
- (modified) llvm/lib/Bitcode/Writer/BitcodeWriter.cpp (+14)
- (modified) llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (+4)
- (modified) llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp (+5)
- (modified) llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h (+9)
- (modified) llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (+41)
- (modified) llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h (+4)
- (modified) llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp (+1)
- (modified) llvm/lib/IR/AsmWriter.cpp (+10)
- (modified) llvm/lib/IR/DIBuilder.cpp (+8)
- (modified) llvm/lib/IR/DebugInfoMetadata.cpp (+10)
- (modified) llvm/lib/IR/LLVMContextImpl.h (+16)
- (modified) llvm/lib/IR/Verifier.cpp (+18-4)
- (added) llvm/test/DebugInfo/variable-expression.ll (+46)
``````````diff
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 28edd439b6900..f032b048b58af 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -6980,6 +6980,20 @@ Some examples of expressions:
!DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)
!DIExpression(DW_OP_constu, 42, DW_OP_stack_value)
+DIVariableExpression
+""""""""""""""""""""
+
+``DIVariableExpression`` holds a ``DIExpression`` and a list of
+references to other variables. When DWARF is emitted for this sort of
+object, each instance of ``DW_OP_LLVM_arg`` in the expression is
+replaced with the DWARF extension operator
+``DW_OP_GNU_variable_value``.
+
+A ``DIVariableExpression`` is useful when a type depends on a
+variable's value. Currently it can be used as the bit size or bit
+offset of a member of a type, or the bit size of a
+``DICompositeType``.
+
DIAssignID
""""""""""
diff --git a/llvm/include/llvm-c/DebugInfo.h b/llvm/include/llvm-c/DebugInfo.h
index 70da3a61a46d8..6fbc6d9e73d79 100644
--- a/llvm/include/llvm-c/DebugInfo.h
+++ b/llvm/include/llvm-c/DebugInfo.h
@@ -200,6 +200,7 @@ enum {
LLVMDIAssignIDMetadataKind,
LLVMDISubrangeTypeMetadataKind,
LLVMDIFixedPointTypeMetadataKind,
+ LLVMDIVariableExpressionMetadataKind,
};
typedef unsigned LLVMMetadataKind;
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index fbf22cc6f760b..529d35a2c5d91 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -926,6 +926,10 @@ HANDLE_DW_OP(0xf8, PGI_omp_thread_num, -1, -1, 0, PGI)
HANDLE_DW_OP(0xfb, GNU_addr_index, 1, 0, 0, GNU)
HANDLE_DW_OP(0xfc, GNU_const_index, 1, 0, 0, GNU)
+// Allow an expression to use the value of a variable.
+// http://dwarfstd.org/ShowIssue.php?issue=161109.2
+HANDLE_DW_OP (0xfd, GNU_variable_value, 1, 0, 0, GNU)
+
// DW_OP_LLVM_user has two operands:
// (1) An unsigned LEB128 "LLVM Vendor Extension Opcode".
// (2) Zero or more literal operands, the number and type of which are
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 811116a3e1756..aa8cfa81a0e2f 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -393,6 +393,7 @@ enum MetadataCodes {
METADATA_ASSIGN_ID = 47, // [distinct, ...]
METADATA_SUBRANGE_TYPE = 48, // [distinct, ...]
METADATA_FIXED_POINT_TYPE = 49, // [distinct, ...]
+ METADATA_VARIABLE_EXPR = 50, // [distinct, ...]
};
// The constants block (CONSTANTS_BLOCK_ID) describes emission for each
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 9753c363166d9..1c027c9b9ad85 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -942,6 +942,15 @@ namespace llvm {
VMContext, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_stack_value});
}
+ /// Create an expression that involves the value of one or more
+ /// variables. Each instance of DW_OP_LLVM_arg in \c Expr is
+ /// replaced with the appropriate variable from \c Vars.
+ /// \param Expr The expression.
+ /// \param Vars The variables to substitute.
+ DIVariableExpression *
+ createExpressionWithVariables(ArrayRef<uint64_t> Expr,
+ ArrayRef<Metadata *> Vars);
+
/// Create a new descriptor for the specified subprogram.
/// See comments in DISubprogram* for descriptions of these fields.
/// \param Scope Function scope.
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 3ce899db66217..bd772c377ee09 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -4681,6 +4681,54 @@ class DIArgList : public Metadata, ReplaceableMetadataImpl {
LLVM_ABI void handleChangedOperand(void *Ref, Metadata *New);
};
+/// This holds a DIExpression and a list of variables that are
+/// referenced by that expression.
+class DIVariableExpression : public MDNode {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ DIVariableExpression(LLVMContext &C, StorageType Storage,
+ ArrayRef<Metadata *> Ops)
+ : MDNode(C, DIVariableExpressionKind, Storage, Ops) {}
+
+ static DIVariableExpression *getImpl(LLVMContext &Context, DIExpression *Expr,
+ DINodeArray VarArray,
+ StorageType Storage,
+ bool ShouldCreate = true) {
+ return getImpl(Context, static_cast<Metadata *>(Expr), VarArray.get(), Storage, ShouldCreate);
+ }
+ static DIVariableExpression *getImpl(LLVMContext &Context, Metadata *Expr,
+ Metadata *VarArray, StorageType Storage,
+ bool ShouldCreate = true);
+
+ TempDIVariableExpression cloneImpl() const {
+ return getTemporary(getContext(), getExpression(), getVariableArray());
+ }
+
+public:
+ DEFINE_MDNODE_GET(DIVariableExpression,
+ (DIExpression * Expr, DINodeArray Vars),
+ (Expr, Vars))
+ DEFINE_MDNODE_GET(DIVariableExpression, (Metadata * Expr, Metadata *Vars),
+ (Expr, Vars))
+
+ DIExpression *getExpression() const {
+ return cast<DIExpression>(getRawExpression());
+ }
+
+ Metadata *getRawExpression() const { return getOperand(0); }
+
+ DINodeArray getVariableArray() const {
+ return cast_or_null<MDTuple>(getRawVariableArray());
+ }
+
+ Metadata *getRawVariableArray() const { return getOperand(1); }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == DIVariableExpressionKind;
+ }
+};
+
/// Identifies a unique instance of a variable.
///
/// Storage for identifying a potentially inlined instance of a variable,
diff --git a/llvm/include/llvm/IR/Metadata.def b/llvm/include/llvm/IR/Metadata.def
index 511bf48707f00..7417514c34134 100644
--- a/llvm/include/llvm/IR/Metadata.def
+++ b/llvm/include/llvm/IR/Metadata.def
@@ -120,6 +120,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIStringType)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGenericSubrange)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubrangeType)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIFixedPointType)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIVariableExpression)
#undef HANDLE_METADATA
#undef HANDLE_METADATA_LEAF
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 5b916711690ec..3f61f264fa602 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -6477,6 +6477,20 @@ bool LLParser::parseDIArgList(Metadata *&MD, PerFunctionState *PFS) {
return false;
}
+/// parseDIVariableExpression:
+/// ::= !DIVariableExpression(expr: !0, vars: !1)
+bool LLParser::parseDIVariableExpression(MDNode *&Result, bool IsDistinct) {
+#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
+ REQUIRED(expr, MDField, ); \
+ REQUIRED(vars, MDField, );
+ PARSE_MD_FIELDS();
+#undef VISIT_MD_FIELDS
+
+ Result = GET_OR_DISTINCT(DIVariableExpression,
+ (Context, expr.Val, vars.Val));
+ return false;
+}
+
/// parseDIGlobalVariableExpression:
/// ::= !DIGlobalVariableExpression(var: !0, expr: !1)
bool LLParser::parseDIGlobalVariableExpression(MDNode *&Result,
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 4bc55232a6df6..3174b4a043abf 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -2367,6 +2367,19 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
NextMetadataNo++;
break;
}
+ case bitc::METADATA_VARIABLE_EXPR: {
+ if (Record.size() != 3)
+ return error("Invalid record");
+
+ IsDistinct = Record[0];
+ Metadata *Expr = getMDOrNull(Record[1]);
+ Metadata *Vars = getMDOrNull(Record[2]);
+ MetadataList.assignValue(
+ GET_OR_DISTINCT(DIVariableExpression, (Context, Expr, Vars)),
+ NextMetadataNo);
+ NextMetadataNo++;
+ break;
+ }
case bitc::METADATA_GLOBAL_VAR_EXPR: {
if (Record.size() != 3)
return error("Invalid record");
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 2566b2a292300..11564c9d18c49 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -401,6 +401,9 @@ class ModuleBitcodeWriter : public ModuleBitcodeWriterBase {
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
void writeDIExpression(const DIExpression *N,
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
+ void writeDIVariableExpression(const DIVariableExpression *N,
+ SmallVectorImpl<uint64_t> &Record,
+ unsigned Abbrev);
void writeDIGlobalVariableExpression(const DIGlobalVariableExpression *N,
SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev);
@@ -2389,6 +2392,17 @@ void ModuleBitcodeWriter::writeDIExpression(const DIExpression *N,
Record.clear();
}
+void ModuleBitcodeWriter::writeDIVariableExpression(
+ const DIVariableExpression *N, SmallVectorImpl<uint64_t> &Record,
+ unsigned Abbrev) {
+ Record.push_back(N->isDistinct());
+ Record.push_back(VE.getMetadataOrNullID(N->getExpression()));
+ Record.push_back(VE.getMetadataOrNullID(N->getVariableArray().get()));
+
+ Stream.EmitRecord(bitc::METADATA_VARIABLE_EXPR, Record, Abbrev);
+ Record.clear();
+}
+
void ModuleBitcodeWriter::writeDIGlobalVariableExpression(
const DIGlobalVariableExpression *N, SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev) {
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index f8c2c753b91ce..2ab2cbb535f34 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -199,6 +199,10 @@ void DebugLocDwarfExpression::emitBaseTypeRef(uint64_t Idx) {
getActiveStreamer().emitULEB128(Idx, Twine(Idx), ULEB128PadSize);
}
+void DebugLocDwarfExpression::emitDIERef(DIE &Ref) {
+ getActiveStreamer().emitDIERef(Ref);
+}
+
bool DebugLocDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI,
llvm::Register MachineReg) {
// This information is not available while emitting .debug_loc entries.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index d6b06b83207c7..cfc3c1eb46ad4 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -40,6 +40,11 @@ void DwarfExpression::emitConstu(uint64_t Value) {
}
}
+void DwarfExpression::addVariableReference(DIE &Ref) {
+ emitOp(llvm::dwarf::DW_OP_GNU_variable_value);
+ emitDIERef(Ref);
+}
+
void DwarfExpression::addReg(int64_t DwarfReg, const char *Comment) {
assert(DwarfReg >= 0 && "invalid negative dwarf register number");
assert((isUnknownLocation() || isRegisterLocation()) &&
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
index c4929aed1c197..4de24343358fe 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -134,6 +134,9 @@ class DwarfExpression {
virtual void emitBaseTypeRef(uint64_t Idx) = 0;
+ /// Emit a reference to the given DIE.
+ virtual void emitDIERef(DIE &Ref) = 0;
+
/// Start emitting data to the temporary buffer. The data stored in the
/// temporary buffer can be committed to the main output using
/// commitTemporaryBuffer().
@@ -270,6 +273,10 @@ class DwarfExpression {
llvm::Register MachineReg,
unsigned FragmentOffsetInBits = 0);
+ /// Add a reference to the variable indicated by the given DIE. A
+ /// DW_OP_GNU_variable_value operation is emitted first.
+ void addVariableReference(DIE &);
+
/// Begin emission of an entry value dwarf operation. The entry value's
/// first operand is the size of the DWARF block (its second operand),
/// which needs to be calculated at time of emission, so we don't emit
@@ -327,6 +334,7 @@ class DebugLocDwarfExpression final : public DwarfExpression {
void emitUnsigned(uint64_t Value) override;
void emitData1(uint8_t Value) override;
void emitBaseTypeRef(uint64_t Idx) override;
+ void emitDIERef(DIE &Ref) override;
void enableTemporaryBuffer() override;
void disableTemporaryBuffer() override;
@@ -357,6 +365,7 @@ class DIEDwarfExpression final : public DwarfExpression {
void emitUnsigned(uint64_t Value) override;
void emitData1(uint8_t Value) override;
void emitBaseTypeRef(uint64_t Idx) override;
+ void emitDIERef(DIE &Ref) override;
void enableTemporaryBuffer() override;
void disableTemporaryBuffer() override;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index baffd81b4f336..198c02afd61e6 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -61,6 +61,10 @@ void DIEDwarfExpression::emitBaseTypeRef(uint64_t Idx) {
CU.addBaseTypeRef(getActiveDIE(), Idx);
}
+void DIEDwarfExpression::emitDIERef(DIE &Ref) {
+ CU.addDIEEntry(getActiveDIE(), dwarf::DW_FORM_ref_addr, Ref);
+}
+
void DIEDwarfExpression::enableTemporaryBuffer() {
assert(!IsBuffering && "Already buffering?");
IsBuffering = true;
@@ -389,6 +393,10 @@ void DwarfUnit::addDIEEntry(DIE &Die, dwarf::Attribute Attribute, DIE &Entry) {
addDIEEntry(Die, Attribute, DIEEntry(Entry));
}
+void DwarfUnit::addDIEEntry(DIEValueList &Die, dwarf::Form Form, DIE &Entry) {
+ addAttribute(Die, (dwarf::Attribute)0, Form, DIEEntry(Entry));
+}
+
void DwarfUnit::addDIETypeSignature(DIE &Die, uint64_t Signature) {
// Flag the type unit reference as a declaration so that if it contains
// members (implicit special members, static data member definitions, member
@@ -450,6 +458,30 @@ void DwarfUnit::addBlock(DIE &Die, dwarf::Attribute Attribute,
addBlock(Die, Attribute, DwarfExpr.finalize());
}
+void DwarfUnit::addBlock(DIE &Die, dwarf::Attribute Attribute,
+ const DIVariableExpression *Expr) {
+ // Emitting a DIVariableExpression normally involves an extension
+ // operator, so just drop this in strict mode.
+ // See http://dwarfstd.org/ShowIssue.php?issue=161109.2.
+ if (Asm->TM.Options.DebugStrictDwarf)
+ return;
+
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ DIEDwarfExpression DwarfExpr(*Asm, getCU(), *Loc);
+ DwarfExpr.setMemoryLocationKind();
+ DINodeArray Vars = Expr->getVariableArray();
+ DwarfExpr.addExpression(
+ Expr->getExpression(),
+ [&](unsigned Idx, DIExpressionCursor &Cursor) -> bool {
+ if (auto *VarDie = getDIE(Vars[Idx])) {
+ DwarfExpr.addVariableReference(*VarDie);
+ return true;
+ }
+ return false;
+ });
+ addBlock(Die, Attribute, DwarfExpr.finalize());
+}
+
void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, unsigned Column,
const DIFile *File) {
if (Line == 0)
@@ -1208,6 +1240,9 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
} else if (auto *Exp =
dyn_cast_or_null<DIExpression>(CTy->getRawSizeInBits())) {
addBlock(Buffer, dwarf::DW_AT_bit_size, Exp);
+ } else if (auto *VarExp = dyn_cast_or_null<DIVariableExpression>(
+ CTy->getRawSizeInBits())) {
+ addBlock(Buffer, dwarf::DW_AT_bit_size, VarExp);
} else {
uint64_t Size = CTy->getSizeInBits() >> 3;
// Add size if non-zero (derived types might be zero-sized.)
@@ -1890,6 +1925,9 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
addDIEEntry(MemberDie, dwarf::DW_AT_bit_size, *VarDIE);
} else if (auto *Exp = dyn_cast<DIExpression>(DT->getRawSizeInBits())) {
addBlock(MemberDie, dwarf::DW_AT_bit_size, Exp);
+ } else if (auto *VarExp = dyn_cast_or_null<DIVariableExpression>(
+ DT->getRawSizeInBits())) {
+ addBlock(MemberDie, dwarf::DW_AT_bit_size, VarExp);
} else {
Size = DT->getSizeInBits();
FieldSize = DD->getBaseTypeSize(DT);
@@ -1915,6 +1953,9 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
if (!Asm->TM.Options.DebugStrictDwarf || DD->getDwarfVersion() >= 6) {
addBlock(MemberDie, dwarf::DW_AT_data_bit_offset, Expr);
}
+ } else if (auto *VarExp = dyn_cast_or_null<DIVariableExpression>(
+ DT->getRawOffsetInBits())) {
+ addBlock(MemberDie, dwarf::DW_AT_data_bit_offset, VarExp);
} else {
uint32_t AlignInBytes = DT->getAlignInBytes();
uint64_t OffsetInBytes;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
index 22eef85a1dffa..2053b4241048d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -205,6 +205,9 @@ class DwarfUnit : public DIEUnit {
/// Add a DIE attribute data and value.
void addDIEEntry(DIE &Die, dwarf::Attribute Attribute, DIEEntry Entry);
+ /// Add a reference to Entry using the indicated form.
+ void addDIEEntry(DIEValueList &Die, dwarf::Form Form, DIE &Entry);
+
/// Add a type's DW_AT_signature and set the declaration flag.
void addDIETypeSignature(DIE &Die, uint64_t Signature);
@@ -218,6 +221,7 @@ class DwarfUnit : public DIEUnit {
/// Add an expression as block data.
void addBlock(DIE &Die, dwarf::Attribute Attribute, const DIExpression *Expr);
+ void addBlock(DIE &Die, dwarf::Attribute Attribute, const DIVariableExpression *Expr);
/// Add location information to specified debug information entry.
void addSourceLine(DIE &Die, unsigned Line, unsigned Column,
diff --git a/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp b/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp
index 61bd6fcb65bfa..f154d0126b3c8 100644
--- a/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp
+++ b/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp
@@ -101,6 +101,7 @@ static std::vector<Desc> getOpDescriptions() {
Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB);
Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB);
Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB);
+ Descriptions[DW_OP_GNU_variable_value] = Desc(Op::Dwarf4, Op::SizeRefAddr);
Descriptions[DW_OP_GNU_implicit_pointer] =
Desc(Op::Dwarf4, Op::SizeRefAddr, Op::SignedSizeLEB);
// This Description acts as a marker that getSubOpDesc must be called
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index b3e0323fd8633..565979cfc2f3d 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2645,6 +2645,16 @@ static void writeDIExpression(raw_ostream &Out, const DIExpression *N,
Out << ")";
}
+static void writeDIVariableExpression(raw_ostream &Out,
+ const DIVariableExpression *N,
+ AsmWriterContext &WriterCtx) {
+ Out << "!DIVariableExpression(";
+ MDFieldPrinter Printer(Out, WriterCtx);
+ Printer.printMetadata("expr", N->getRawExpression());
+ Printer.printMetadata("vars", N->getRawVariableArray());
+ Out << ")";
+}
+
static void writeDIArgList(raw_ostream &Out, const DIArgList *N,
AsmWriterContext &WriterCtx,
bool FromValue = false) {
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 38cf3f552b83d..327f794964618 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -918,6 +918,14 @@ static void checkGlobalVariableScope(DIScope *Context) {
#endif
}
+DIVariableExpression *
+DIBuilder::createExpressionWithVariables(ArrayRef<uint64_t> Expr,
+ ArrayRef<Metadata *> Vars) {
+ DIExpression *EX = DIExpress...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/181028
More information about the llvm-commits
mailing list