Skip to content

Commit c320df4

Browse files
authored
[LLVM-C] Add bindings to Instruction::getDbgRecordRange() (#107802)
Since the migration from `@llvm.dbg.value` intrinsic to `#dbg_value` records, there is no way to retrieve the debug records for an `Instruction` in LLVM-C API. Previously, with debug info intrinsics, retrieving debug info for an `Instruction` could be done with `LLVMGetNextInstructions`, because the intrinsic call was also an instruction. However, to be able to retrieve debug info with the current LLVM, where debug records are used, the `getDbgRecordRange()` iterator needs to be exposed. Add new functions for DbgRecord sequence traversal: LLVMGetFirstDbgRecord LLVMGetLastDbgRecord LLVMGetNextDbgRecord LLVMGetPreviousDbgRecord See llvm/docs/RemoveDIsDebugInfo.md and release notes.
1 parent 28646d0 commit c320df4

File tree

6 files changed

+147
-14
lines changed

6 files changed

+147
-14
lines changed

llvm/docs/ReleaseNotes.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,14 @@ Changes to the C API
196196
* The `LLVMSetPersonalityFn` and `LLVMSetInitializer` APIs now support clearing the
197197
personality function and initializer respectively by passing a null pointer.
198198

199+
* The following functions are added to allow iterating over debug records attached to
200+
instructions:
201+
202+
* ``LLVMGetFirstDbgRecord``
203+
* ``LLVMGetLastDbgRecord``
204+
* ``LLVMGetNextDbgRecord``
205+
* ``LLVMGetPreviousDbgRecord``
206+
199207

200208
Changes to the CodeGen infrastructure
201209
-------------------------------------

llvm/docs/RemoveDIsDebugInfo.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ LLVMSetIsNewDbgInfoFormat # Convert to the requested debug info format.
154154

155155
New functions (no plans to deprecate)
156156
-------------------------------------
157+
LLVMGetFirstDbgRecord # Obtain the first debug record attached to an instruction.
158+
LLVMGetLastDbgRecord # Obtain the last debug record attached to an instruction.
159+
LLVMGetNextDbgRecord # Get next debug record or NULL.
160+
LLVMGetPreviousDbgRecord # Get previous debug record or NULL.
157161
LLVMDIBuilderInsertDeclareRecordBefore # Insert a debug record (new debug info format).
158162
LLVMDIBuilderInsertDeclareRecordAtEnd # Same as above. See info below.
159163
LLVMDIBuilderInsertDbgValueRecordBefore # Same as above. See info below.
@@ -172,6 +176,24 @@ If you are trying to insert at the start of a block, or purposfully skip debug i
172176
173177
`LLVMPositionBuilder` and `LLVMPositionBuilderBefore` are unchanged. They insert before the indicated instruction but after any attached debug records.
174178
179+
`LLVMGetFirstDbgRecord`, `LLVMGetLastDbgRecord`, `LLVMGetNextDbgRecord` and `LLVMGetPreviousDbgRecord` can be used for iterating over debug records attached to instructions (provided as `LLVMValueRef`).
180+
181+
```c
182+
LLVMDbgRecordRef DbgRec;
183+
for (DbgRec = LLVMGetFirstDbgRecord(Inst); DbgRec;
184+
DbgRec = LLVMGetNextDbgRecord(DbgRec)) {
185+
// do something with DbgRec
186+
}
187+
```
188+
189+
```c
190+
LLVMDbgRecordRef DbgRec;
191+
for (DbgRec = LLVMGetLastDbgRecord(Inst); DbgRec;
192+
DbgRec = LLVMGetPreviousDbgRecord(DbgRec)) {
193+
// do something with DbgRec
194+
}
195+
````
196+
175197
# The new "Debug Record" model
176198

177199
Below is a brief overview of the new representation that replaces debug intrinsics; for an instructive guide on updating old code, see [here](#how-to-update-existing-code).
@@ -430,4 +452,4 @@ This can technically lead to trouble in the vanishingly rare scenario where an o
430452

431453
## Anything else?
432454

433-
The above guide does not comprehensively cover every pattern that could apply to debug intrinsics; as mentioned at the [start of the guide](#how-to-update-existing-code), you can temporarily convert the target module from debug records to intrinsics as a stopgap measure. Most operations that can be performed on debug intrinsics have exact equivalents for debug records, but if you encounter any exceptions, reading the class docs (linked [here](#what-exactly-have-you-replaced-debug-intrinsics-with)) may give some insight, there may be examples in the existing codebase, and you can always ask for help on the [forums](https://discourse.llvm.org/tag/debuginfo).
455+
The above guide does not comprehensively cover every pattern that could apply to debug intrinsics; as mentioned at the [start of the guide](#how-to-update-existing-code), you can temporarily convert the target module from debug records to intrinsics as a stopgap measure. Most operations that can be performed on debug intrinsics have exact equivalents for debug records, but if you encounter any exceptions, reading the class docs (linked [here](#what-exactly-have-you-replaced-debug-intrinsics-with)) may give some insight, there may be examples in the existing codebase, and you can always ask for help on the [forums](https://discourse.llvm.org/tag/debuginfo).

llvm/include/llvm-c/Core.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3682,6 +3682,41 @@ LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst);
36823682
*/
36833683
LLVMValueRef LLVMIsATerminatorInst(LLVMValueRef Inst);
36843684

3685+
/**
3686+
* Obtain the first debug record attached to an instruction.
3687+
*
3688+
* Use LLVMGetNextDbgRecord() and LLVMGetPreviousDbgRecord() to traverse the
3689+
* sequence of DbgRecords.
3690+
*
3691+
* Return the first DbgRecord attached to Inst or NULL if there are none.
3692+
*
3693+
* @see llvm::Instruction::getDbgRecordRange()
3694+
*/
3695+
LLVMDbgRecordRef LLVMGetFirstDbgRecord(LLVMValueRef Inst);
3696+
3697+
/**
3698+
* Obtain the last debug record attached to an instruction.
3699+
*
3700+
* Return the last DbgRecord attached to Inst or NULL if there are none.
3701+
*
3702+
* @see llvm::Instruction::getDbgRecordRange()
3703+
*/
3704+
LLVMDbgRecordRef LLVMGetLastDbgRecord(LLVMValueRef Inst);
3705+
3706+
/**
3707+
* Obtain the next DbgRecord in the sequence or NULL if there are no more.
3708+
*
3709+
* @see llvm::Instruction::getDbgRecordRange()
3710+
*/
3711+
LLVMDbgRecordRef LLVMGetNextDbgRecord(LLVMDbgRecordRef DbgRecord);
3712+
3713+
/**
3714+
* Obtain the previous DbgRecord in the sequence or NULL if there are no more.
3715+
*
3716+
* @see llvm::Instruction::getDbgRecordRange()
3717+
*/
3718+
LLVMDbgRecordRef LLVMGetPreviousDbgRecord(LLVMDbgRecordRef DbgRecord);
3719+
36853720
/**
36863721
* @defgroup LLVMCCoreValueInstructionCall Call Sites and Invocations
36873722
*

llvm/lib/IR/Core.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "llvm-c/Core.h"
15+
#include "llvm-c/Types.h"
1516
#include "llvm/IR/Attributes.h"
1617
#include "llvm/IR/BasicBlock.h"
1718
#include "llvm/IR/ConstantRange.h"
1819
#include "llvm/IR/Constants.h"
1920
#include "llvm/IR/DebugInfoMetadata.h"
21+
#include "llvm/IR/DebugProgramInstruction.h"
2022
#include "llvm/IR/DerivedTypes.h"
2123
#include "llvm/IR/DiagnosticInfo.h"
2224
#include "llvm/IR/DiagnosticPrinter.h"
@@ -2975,6 +2977,38 @@ LLVMValueRef LLVMIsATerminatorInst(LLVMValueRef Inst) {
29752977
return (I && I->isTerminator()) ? wrap(I) : nullptr;
29762978
}
29772979

2980+
LLVMDbgRecordRef LLVMGetFirstDbgRecord(LLVMValueRef Inst) {
2981+
Instruction *Instr = unwrap<Instruction>(Inst);
2982+
auto I = Instr->DebugMarker->StoredDbgRecords.begin();
2983+
if (I == Instr->DebugMarker->StoredDbgRecords.end())
2984+
return nullptr;
2985+
return wrap(&*I);
2986+
}
2987+
2988+
LLVMDbgRecordRef LLVMGetLastDbgRecord(LLVMValueRef Inst) {
2989+
Instruction *Instr = unwrap<Instruction>(Inst);
2990+
auto I = Instr->DebugMarker->StoredDbgRecords.rbegin();
2991+
if (I == Instr->DebugMarker->StoredDbgRecords.rend())
2992+
return nullptr;
2993+
return wrap(&*I);
2994+
}
2995+
2996+
LLVMDbgRecordRef LLVMGetNextDbgRecord(LLVMDbgRecordRef Rec) {
2997+
DbgRecord *Record = unwrap<DbgRecord>(Rec);
2998+
simple_ilist<DbgRecord>::iterator I(Record);
2999+
if (++I == Record->getInstruction()->DebugMarker->StoredDbgRecords.end())
3000+
return nullptr;
3001+
return wrap(&*I);
3002+
}
3003+
3004+
LLVMDbgRecordRef LLVMGetPreviousDbgRecord(LLVMDbgRecordRef Rec) {
3005+
DbgRecord *Record = unwrap<DbgRecord>(Rec);
3006+
simple_ilist<DbgRecord>::iterator I(Record);
3007+
if (I == Record->getInstruction()->DebugMarker->StoredDbgRecords.begin())
3008+
return nullptr;
3009+
return wrap(&*--I);
3010+
}
3011+
29783012
unsigned LLVMGetNumArgOperands(LLVMValueRef Instr) {
29793013
if (FuncletPadInst *FPI = dyn_cast<FuncletPadInst>(unwrap(Instr))) {
29803014
return FPI->arg_size();

llvm/test/Bindings/llvm-c/debug_info_new_format.ll

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66

77
; CHECK: define i64 @foo(i64 %0, i64 %1, <10 x i64> %2) !dbg !31 {
88
; CHECK-NEXT: entry:
9-
; CHECK-NEXT: #dbg_declare(i64 0, !38, !DIExpression(), !43)
10-
; CHECK-NEXT: #dbg_declare(i64 0, !39, !DIExpression(), !43)
11-
; CHECK-NEXT: #dbg_declare(i64 0, !40, !DIExpression(), !43)
9+
; CHECK-NEXT: #dbg_declare(i64 0, !38, !DIExpression(), !44)
10+
; CHECK-NEXT: #dbg_declare(i64 0, !39, !DIExpression(), !44)
11+
; CHECK-NEXT: #dbg_declare(i64 0, !40, !DIExpression(), !44)
1212
; CHECK-NEXT: br label %vars
1313
; CHECK: vars:
1414
; CHECK-NEXT: %p1 = phi i64 [ 0, %entry ]
1515
; CHECK-NEXT: %p2 = phi i64 [ 0, %entry ]
16-
; CHECK-NEXT: #dbg_value(i64 0, !41, !DIExpression(DW_OP_constu, 0, DW_OP_stack_value), !44)
16+
; CHECK-NEXT: #dbg_value(i64 0, !41, !DIExpression(DW_OP_constu, 0, DW_OP_stack_value), !45)
17+
; CHECK-NEXT: #dbg_value(i64 1, !43, !DIExpression(DW_OP_constu, 1, DW_OP_stack_value), !45)
1718
; CHECK-NEXT: %a = add i64 %p1, %p2
1819
; CHECK-NEXT: ret i64 0
1920
; CHECK-NEXT: }
@@ -59,11 +60,12 @@
5960
; CHECK-NEXT: !34 = !DICompositeType(tag: DW_TAG_array_type, baseType: !6, size: 640, flags: DIFlagVector, elements: !35)
6061
; CHECK-NEXT: !35 = !{!36}
6162
; CHECK-NEXT: !36 = !DISubrange(count: 10, lowerBound: 0)
62-
; CHECK-NEXT: !37 = !{!38, !39, !40, !41}
63+
; CHECK-NEXT: !37 = !{!38, !39, !40, !41, !43}
6364
; CHECK-NEXT: !38 = !DILocalVariable(name: "a", arg: 1, scope: !31, file: !1, line: 42, type: !6)
6465
; CHECK-NEXT: !39 = !DILocalVariable(name: "b", arg: 2, scope: !31, file: !1, line: 42, type: !6)
6566
; CHECK-NEXT: !40 = !DILocalVariable(name: "c", arg: 3, scope: !31, file: !1, line: 42, type: !34)
6667
; CHECK-NEXT: !41 = !DILocalVariable(name: "d", scope: !42, file: !1, line: 43, type: !6)
6768
; CHECK-NEXT: !42 = distinct !DILexicalBlock(scope: !31, file: !1, line: 42)
68-
; CHECK-NEXT: !43 = !DILocation(line: 42, scope: !31)
69-
; CHECK-NEXT: !44 = !DILocation(line: 43, scope: !31)
69+
; CHECK-NEXT: !43 = !DILocalVariable(name: "e", scope: !42, file: !1, line: 44, type: !6)
70+
; CHECK-NEXT: !44 = !DILocation(line: 42, scope: !31)
71+
; CHECK-NEXT: !45 = !DILocation(line: 43, scope: !31)

llvm/tools/llvm-c-test/debuginfo.c

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
|* *|
1212
\*===----------------------------------------------------------------------===*/
1313

14-
#include "llvm-c-test.h"
1514
#include "llvm-c/DebugInfo.h"
15+
#include "llvm-c-test.h"
16+
#include "llvm-c/Core.h"
17+
#include "llvm-c/Types.h"
1618

1719
#include <assert.h>
1820
#include <stdio.h>
@@ -172,11 +174,20 @@ int llvm_test_dibuilder(void) {
172174
LLVMDIBuilderCreateAutoVariable(DIB, FooLexicalBlock, "d", 1, File,
173175
43, Int64Ty, true, 0, 0);
174176
LLVMValueRef FooVal1 = LLVMConstInt(LLVMInt64Type(), 0, false);
175-
LLVMMetadataRef FooVarValueExpr =
176-
LLVMDIBuilderCreateConstantValueExpression(DIB, 0);
177+
LLVMMetadataRef FooVarValueExpr1 =
178+
LLVMDIBuilderCreateConstantValueExpression(DIB, 0);
179+
180+
LLVMDIBuilderInsertDbgValueRecordAtEnd(
181+
DIB, FooVal1, FooVar1, FooVarValueExpr1, FooVarsLocation, FooVarBlock);
177182

178-
LLVMDIBuilderInsertDbgValueRecordAtEnd(DIB, FooVal1, FooVar1, FooVarValueExpr,
179-
FooVarsLocation, FooVarBlock);
183+
LLVMMetadataRef FooVar2 = LLVMDIBuilderCreateAutoVariable(
184+
DIB, FooLexicalBlock, "e", 1, File, 44, Int64Ty, true, 0, 0);
185+
LLVMValueRef FooVal2 = LLVMConstInt(LLVMInt64Type(), 1, false);
186+
LLVMMetadataRef FooVarValueExpr2 =
187+
LLVMDIBuilderCreateConstantValueExpression(DIB, 1);
188+
189+
LLVMDIBuilderInsertDbgValueRecordAtEnd(
190+
DIB, FooVal2, FooVar2, FooVarValueExpr2, FooVarsLocation, FooVarBlock);
180191

181192
LLVMMetadataRef MacroFile =
182193
LLVMDIBuilderCreateTempMacroFile(DIB, NULL, 0, File);
@@ -224,14 +235,35 @@ int llvm_test_dibuilder(void) {
224235
LLVMPositionBuilderBeforeInstrAndDbgRecords(Builder, InsertPos);
225236
LLVMValueRef Phi1 = LLVMBuildPhi(Builder, I64, "p1");
226237
LLVMAddIncoming(Phi1, &Zero, &FooEntryBlock, 1);
238+
227239
// Do the same again using the other position-setting function.
228240
LLVMPositionBuilderBeforeDbgRecords(Builder, FooVarBlock, InsertPos);
229241
LLVMValueRef Phi2 = LLVMBuildPhi(Builder, I64, "p2");
230242
LLVMAddIncoming(Phi2, &Zero, &FooEntryBlock, 1);
243+
231244
// Insert a non-phi before the `ret` but not before the debug records to
232245
// test that works as expected.
233246
LLVMPositionBuilder(Builder, FooVarBlock, Ret);
234-
LLVMBuildAdd(Builder, Phi1, Phi2, "a");
247+
LLVMValueRef Add = LLVMBuildAdd(Builder, Phi1, Phi2, "a");
248+
249+
// Iterate over debug records in the add instruction. There should be two.
250+
LLVMDbgRecordRef AddDbgRecordFirst = LLVMGetFirstDbgRecord(Add);
251+
assert(AddDbgRecordFirst != NULL);
252+
LLVMDbgRecordRef AddDbgRecordSecond = LLVMGetNextDbgRecord(AddDbgRecordFirst);
253+
assert(AddDbgRecordSecond != NULL);
254+
LLVMDbgRecordRef AddDbgRecordLast = LLVMGetLastDbgRecord(Add);
255+
assert(AddDbgRecordLast != NULL);
256+
assert(AddDbgRecordSecond == AddDbgRecordLast);
257+
LLVMDbgRecordRef AddDbgRecordOverTheRange =
258+
LLVMGetNextDbgRecord(AddDbgRecordSecond);
259+
assert(AddDbgRecordOverTheRange == NULL);
260+
LLVMDbgRecordRef AddDbgRecordFirstPrev =
261+
LLVMGetPreviousDbgRecord(AddDbgRecordSecond);
262+
assert(AddDbgRecordFirstPrev != NULL);
263+
assert(AddDbgRecordFirst == AddDbgRecordFirstPrev);
264+
LLVMDbgRecordRef AddDbgRecordUnderTheRange =
265+
LLVMGetPreviousDbgRecord(AddDbgRecordFirstPrev);
266+
assert(AddDbgRecordUnderTheRange == NULL);
235267

236268
char *MStr = LLVMPrintModuleToString(M);
237269
puts(MStr);

0 commit comments

Comments
 (0)