Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions llvm/docs/SourceLevelDebugging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,28 @@ directly, not its address. Note that the value operand of this intrinsic may
be indirect (i.e, a pointer to the source variable), provided that interpreting
the complex expression derives the direct value.


``#dbg_declare_value``
^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: llvm

#dbg_declare_value([Value|MDNode], DILocalVariable, DIExpression, DILocation)

This record provides information about a local element (e.g., variable). The
first argument is used to compute the value of the variable throughout the
entire function. The second argument is a
:ref:`local variable <dilocalvariable>` containing a description of the
variable. The third argument is a :ref:`complex expression <diexpression>`. The
foruth argument is a :ref:`source location <dilocation>`. A
``#dbg_declare_value`` record describes describes the *value* of a source
variable directly, not its address. The difference between a ``#dbg_value`` and
a ``#dbg_declare_value`` is that, just like a ``#dbg_declare``, a frontend
should generate exactly one ``#dbg_declare_value`` record. The idea is to have
``#dbg_declare`` guarantees but be able to describe a value rather than the
address of a value.


``#dbg_assign``
^^^^^^^^^^^^^^^
.. toctree::
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/Bitcode/LLVMBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,8 @@ enum FunctionCodes {
FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE =
64, // [DILocation, DILocalVariable, DIExpression, Value]
FUNC_CODE_DEBUG_RECORD_LABEL = 65, // [DILocation, DILabel]
FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE =
66, // [DILocation, DILocalVariable, DIExpression, ValueAsMetadata]
};

enum UseListCodes {
Expand Down
12 changes: 12 additions & 0 deletions llvm/include/llvm/IR/DIBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,18 @@ namespace llvm {
DIExpression *Expr, const DILocation *DL,
InsertPosition InsertPt);

/// Insert a new llvm.dbg.declare_value intrinsic call.
/// \param Storage llvm::Value of the variable
/// \param VarInfo Variable's debug info descriptor.
/// \param Expr A complex location expression.
/// \param DL Debug info location.
/// \param InsertPt Location for the new intrinsic.
LLVM_ABI DbgInstPtr insertDeclareValue(llvm::Value *Storage,
DILocalVariable *VarInfo,
DIExpression *Expr,
const DILocation *DL,
InsertPosition InsertPt);

/// Insert a new llvm.dbg.label intrinsic call.
/// \param LabelInfo Label's debug info descriptor.
/// \param DL Debug info location.
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/IR/DebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class Module;
LLVM_ABI TinyPtrVector<DbgVariableRecord *> findDVRDeclares(Value *V);
/// As above, for DVRValues.
LLVM_ABI TinyPtrVector<DbgVariableRecord *> findDVRValues(Value *V);
/// As above, for DVRDeclareValues.
LLVM_ABI TinyPtrVector<DbgVariableRecord *> findDVRDeclareValues(Value *V);

/// Finds the debug info records describing a value.
LLVM_ABI void
Expand Down
19 changes: 16 additions & 3 deletions llvm/include/llvm/IR/DebugProgramInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser {
Declare,
Value,
Assign,
DeclareValue,

End, ///< Marks the end of the concrete types.
Any, ///< To indicate all LocationTypes in searches.
Expand Down Expand Up @@ -364,6 +365,13 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser {
createDVRDeclare(Value *Address, DILocalVariable *DV, DIExpression *Expr,
const DILocation *DI, DbgVariableRecord &InsertBefore);

LLVM_ABI static DbgVariableRecord *
createDVRDeclareValue(Value *Address, DILocalVariable *DV, DIExpression *Expr,
const DILocation *DI);
LLVM_ABI static DbgVariableRecord *
createDVRDeclareValue(Value *Address, DILocalVariable *DV, DIExpression *Expr,
const DILocation *DI, DbgVariableRecord &InsertBefore);

/// Iterator for ValueAsMetadata that internally uses direct pointer iteration
/// over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the
/// ValueAsMetadata .
Expand Down Expand Up @@ -414,6 +422,7 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser {

bool isDbgDeclare() const { return Type == LocationType::Declare; }
bool isDbgValue() const { return Type == LocationType::Value; }
bool isDbgDeclareValue() const { return Type == LocationType::DeclareValue; }

/// Get the locations corresponding to the variable referenced by the debug
/// info intrinsic. Depending on the intrinsic, this could be the
Expand All @@ -439,12 +448,16 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser {
bool hasValidLocation() const { return getVariableLocationOp(0) != nullptr; }

/// Does this describe the address of a local variable. True for dbg.addr
/// and dbg.declare, but not dbg.value, which describes its value.
/// and dbg.declare, but not dbg.value or dbg.declare_value, which describes
/// its value.
bool isAddressOfVariable() const { return Type == LocationType::Declare; }

/// Determine if this describes the value of a local variable. It is false for
/// dbg.declare, but true for dbg.value, which describes its value.
bool isValueOfVariable() const { return Type == LocationType::Value; }
/// dbg.declare, but true for dbg.value and dbg.declare_value, which describes
/// its value.
bool isValueOfVariable() const {
return Type == LocationType::Value || Type == LocationType::DeclareValue;
}

LocationType getType() const { return Type; }

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,7 @@ lltok::Kind LLLexer::LexIdentifier() {
DBGRECORDTYPEKEYWORD(declare);
DBGRECORDTYPEKEYWORD(assign);
DBGRECORDTYPEKEYWORD(label);
DBGRECORDTYPEKEYWORD(declare_value);
#undef DBGRECORDTYPEKEYWORD

if (Keyword.starts_with("DIFlag")) {
Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7155,7 +7155,8 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) {
.Case("declare", RecordKind::ValueKind)
.Case("value", RecordKind::ValueKind)
.Case("assign", RecordKind::ValueKind)
.Case("label", RecordKind::LabelKind);
.Case("label", RecordKind::LabelKind)
.Case("declare_value", RecordKind::ValueKind);

// Parsing labels is trivial; parse here and early exit, otherwise go into the
// full DbgVariableRecord processing stage.
Expand All @@ -7180,7 +7181,8 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) {
LocType ValueType = StringSwitch<LocType>(Lex.getStrVal())
.Case("declare", LocType::Declare)
.Case("value", LocType::Value)
.Case("assign", LocType::Assign);
.Case("assign", LocType::Assign)
.Case("declare_value", LocType::DeclareValue);

Lex.Lex();
if (parseToken(lltok::lparen, "Expected '(' here"))
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ GetCodeName(unsigned CodeID, unsigned BlockID,
STRINGIFY_CODE(FUNC_CODE, INST_CALLBR)
STRINGIFY_CODE(FUNC_CODE, BLOCKADDR_USERS)
STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_DECLARE)
STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_DECLARE_VALUE)
STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE)
STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_ASSIGN)
STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE_SIMPLE)
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Bitcode/Reader/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6655,6 +6655,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
case bitc::FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE:
case bitc::FUNC_CODE_DEBUG_RECORD_VALUE:
case bitc::FUNC_CODE_DEBUG_RECORD_DECLARE:
case bitc::FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE:
case bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN: {
// DbgVariableRecords are placed after the Instructions that they are
// attached to.
Expand All @@ -6671,6 +6672,8 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
// ..., Value
// dbg_declare (FUNC_CODE_DEBUG_RECORD_DECLARE)
// ..., LocationMetadata
// dbg_declare_value (FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE)
// ..., LocationMetadata
// dbg_assign (FUNC_CODE_DEBUG_RECORD_ASSIGN)
// ..., LocationMetadata, DIAssignID, DIExpression, LocationMetadata
unsigned Slot = 0;
Expand Down Expand Up @@ -6712,6 +6715,11 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
DVR = new DbgVariableRecord(RawLocation, Var, Expr, DIL,
DbgVariableRecord::LocationType::Declare);
break;
case bitc::FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE:
DVR = new DbgVariableRecord(
RawLocation, Var, Expr, DIL,
DbgVariableRecord::LocationType::DeclareValue);
break;
case bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN: {
DIAssignID *ID = cast<DIAssignID>(getFnMetadataByID(Record[Slot++]));
DIExpression *AddrExpr =
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3844,6 +3844,9 @@ void ModuleBitcodeWriter::writeFunction(
} else if (DVR.isDbgDeclare()) {
Vals.push_back(VE.getMetadataID(DVR.getRawLocation()));
Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_DECLARE, Vals);
} else if (DVR.isDbgDeclareValue()) {
Vals.push_back(VE.getMetadataID(DVR.getRawLocation()));
Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE, Vals);
} else {
assert(DVR.isDbgAssign() && "Unexpected DbgRecord kind");
Vals.push_back(VE.getMetadataID(DVR.getRawLocation()));
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/IR/AsmWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4864,6 +4864,9 @@ void AssemblyWriter::printDbgVariableRecord(const DbgVariableRecord &DVR) {
case DbgVariableRecord::LocationType::Declare:
Out << "declare";
break;
case DbgVariableRecord::LocationType::DeclareValue:
Out << "declare_value";
break;
case DbgVariableRecord::LocationType::Assign:
Out << "assign";
break;
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/IR/DIBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1147,6 +1147,24 @@ DbgInstPtr DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
return DVR;
}

DbgInstPtr DIBuilder::insertDeclareValue(Value *Storage,
DILocalVariable *VarInfo,
DIExpression *Expr,
const DILocation *DL,
InsertPosition InsertPt) {
assert(VarInfo &&
"empty or invalid DILocalVariable* passed to dbg.declare_value");
assert(DL && "Expected debug loc");
assert(DL->getScope()->getSubprogram() ==
VarInfo->getScope()->getSubprogram() &&
"Expected matching subprograms");

DbgVariableRecord *DVR =
DbgVariableRecord::createDVRDeclareValue(Storage, VarInfo, Expr, DL);
insertDbgVariableRecord(DVR, InsertPt);
return DVR;
}

void DIBuilder::insertDbgVariableRecord(DbgVariableRecord *DVR,
InsertPosition InsertPt) {
assert(InsertPt.isValid());
Expand Down
17 changes: 17 additions & 0 deletions llvm/lib/IR/DebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,23 @@ TinyPtrVector<DbgVariableRecord *> llvm::findDVRDeclares(Value *V) {
return Declares;
}

TinyPtrVector<DbgVariableRecord *> llvm::findDVRDeclareValues(Value *V) {
// This function is hot. Check whether the value has any metadata to avoid a
// DenseMap lookup. This check is a bitfield datamember lookup.
if (!V->isUsedByMetadata())
return {};
auto *L = ValueAsMetadata::getIfExists(V);
if (!L)
return {};

TinyPtrVector<DbgVariableRecord *> DEclareValues;
for (DbgVariableRecord *DVR : L->getAllDbgVariableRecordUsers())
if (DVR->getType() == DbgVariableRecord::LocationType::DeclareValue)
DEclareValues.push_back(DVR);

return DEclareValues;
}

TinyPtrVector<DbgVariableRecord *> llvm::findDVRValues(Value *V) {
// This function is hot. Check whether the value has any metadata to avoid a
// DenseMap lookup. This check is a bitfield datamember lookup.
Expand Down
20 changes: 20 additions & 0 deletions llvm/lib/IR/DebugProgramInstruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,22 @@ DbgVariableRecord::createDVRDeclare(Value *Address, DILocalVariable *DV,
return NewDVRDeclare;
}

DbgVariableRecord *
DbgVariableRecord::createDVRDeclareValue(Value *Address, DILocalVariable *DV,
DIExpression *Expr,
const DILocation *DI) {
return new DbgVariableRecord(ValueAsMetadata::get(Address), DV, Expr, DI,
LocationType::DeclareValue);
}

DbgVariableRecord *DbgVariableRecord::createDVRDeclareValue(
Value *Address, DILocalVariable *DV, DIExpression *Expr,
const DILocation *DI, DbgVariableRecord &InsertBefore) {
auto *NewDVRCoro = createDVRDeclareValue(Address, DV, Expr, DI);
NewDVRCoro->insertBefore(&InsertBefore);
return NewDVRCoro;
}

DbgVariableRecord *DbgVariableRecord::createDVRAssign(
Value *Val, DILocalVariable *Variable, DIExpression *Expression,
DIAssignID *AssignID, Value *Address, DIExpression *AddressExpression,
Expand Down Expand Up @@ -427,6 +443,10 @@ DbgVariableRecord::createDebugIntrinsic(Module *M,
case DbgVariableRecord::LocationType::End:
case DbgVariableRecord::LocationType::Any:
llvm_unreachable("Invalid LocationType");
break;
case DbgVariableRecord::LocationType::DeclareValue:
llvm_unreachable(
"#dbg_declare_value should never be converted to an intrinsic");
}

// Create the intrinsic from this DbgVariableRecord's information, optionally
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ struct llvm::VerifierSupport {
case DbgVariableRecord::LocationType::Declare:
*OS << "declare";
break;
case DbgVariableRecord::LocationType::DeclareValue:
*OS << "declare_value";
break;
case DbgVariableRecord::LocationType::Assign:
*OS << "assign";
break;
Expand Down Expand Up @@ -7083,6 +7086,7 @@ void Verifier::visit(DbgVariableRecord &DVR) {

CheckDI(DVR.getType() == DbgVariableRecord::LocationType::Value ||
DVR.getType() == DbgVariableRecord::LocationType::Declare ||
DVR.getType() == DbgVariableRecord::LocationType::DeclareValue ||
DVR.getType() == DbgVariableRecord::LocationType::Assign,
"invalid #dbg record type", &DVR, DVR.getType(), BB, F);

Expand Down
37 changes: 37 additions & 0 deletions llvm/test/Assembler/dbg_declare_value.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s

; CHECK: #dbg_declare_value(double %{{[0-9]+}}, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}})

; ModuleID = '/tmp/test.c'
source_filename = "/tmp/test.c"
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
target triple = "arm64-apple-macosx26.0.0"

; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
define void @foo(double noundef %0) #0 !dbg !9 {
#dbg_declare_value(double %0, !15, !DIExpression(), !16)
ret void, !dbg !21
}

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7}
!llvm.ident = !{!8}

!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 22.0.0git (git@github.com:rastogishubham/llvm-project.git bacf99969b2f3e6db4cfcf536cce8b01ffd20aa0)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")
!1 = !DIFile(filename: "/tmp/test.c", directory: "/Users/srastogi/Development/llvm-project-2/build_ninja", checksumkind: CSK_MD5, checksum: "fa15cf45ed4f9d805aab17eb7856a442")
!2 = !{i32 7, !"Dwarf Version", i32 5}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = !{i32 1, !"wchar_size", i32 4}
!5 = !{i32 8, !"PIC Level", i32 2}
!6 = !{i32 7, !"uwtable", i32 1}
!7 = !{i32 7, !"frame-pointer", i32 4}
!8 = !{!"clang version 22.0.0git (git@github.com:rastogishubham/llvm-project.git bacf99969b2f3e6db4cfcf536cce8b01ffd20aa0)"}
!9 = distinct !DISubprogram(name: "foo", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14)
!10 = !DIFile(filename: "/tmp/test.c", directory: "", checksumkind: CSK_MD5, checksum: "fa15cf45ed4f9d805aab17eb7856a442")
!11 = !DISubroutineType(types: !12)
!12 = !{null, !13}
!13 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float)
!14 = !{}
!15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
!16 = !DILocation(line: 1, column: 17, scope: !9)
!21 = !DILocation(line: 3, column: 1, scope: !9)