Skip to content

Commit 6779ad3

Browse files
committed
[LLVM-C] Add bindings to Instruction::getDbgRecordRange()
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.
1 parent a2f659c commit 6779ad3

File tree

5 files changed

+141
-7
lines changed

5 files changed

+141
-7
lines changed

llvm/docs/ReleaseNotes.rst

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

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

199207
Changes to the CodeGen infrastructure
200208
-------------------------------------

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 a instruction.
158+
LLVMGetLastDbgRecord # Obtain the last debug record attached to a instruction.
159+
LLVMGetNextDbgRecord # Advance a debug record iterator.
160+
LLVMGetPreviousDbgRecord # Go backwards in a debug record iterator.
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: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3682,6 +3682,33 @@ LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst);
36823682
*/
36833683
LLVMValueRef LLVMIsATerminatorInst(LLVMValueRef Inst);
36843684

3685+
/**
3686+
* Obtain the first debug record attached to a instruction.
3687+
*
3688+
* The returned debug record can be used as an iterator. You will likely
3689+
* eventually call into LLVMGetNextDbgRecord() with it.
3690+
*
3691+
* @see llvm::Instruction::getDbgRecordRange()
3692+
*/
3693+
LLVMDbgRecordRef LLVMGetFirstDbgRecord(LLVMValueRef Inst);
3694+
3695+
/**
3696+
* Obtain the last debug record attached to a instruction.
3697+
*
3698+
* @see llvm::Instruction::getDbgRecordRange()
3699+
*/
3700+
LLVMDbgRecordRef LLVMGetLastDbgRecord(LLVMValueRef Inst);
3701+
3702+
/**
3703+
* Advance a debug record iterator.
3704+
*/
3705+
LLVMDbgRecordRef LLVMGetNextDbgRecord(LLVMDbgRecordRef DbgRecord);
3706+
3707+
/**
3708+
* Go backwards in a debug record iterator.
3709+
*/
3710+
LLVMDbgRecordRef LLVMGetPreviousDbgRecord(LLVMDbgRecordRef DbgRecord);
3711+
36853712
/**
36863713
* @defgroup LLVMCCoreValueInstructionCall Call Sites and Invocations
36873714
*

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/tools/llvm-c-test/debuginfo.c

Lines changed: 49 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,46 @@ 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+
// Iterate with a for loop.
251+
LLVMDbgRecordRef DbgRec;
252+
for (DbgRec = LLVMGetFirstDbgRecord(Add); DbgRec;
253+
DbgRec = LLVMGetNextDbgRecord(DbgRec)) {
254+
assert(DbgRec != NULL);
255+
}
256+
for (DbgRec = LLVMGetLastDbgRecord(Add); DbgRec;
257+
DbgRec = LLVMGetPreviousDbgRecord(DbgRec)) {
258+
assert(DbgRec != NULL);
259+
}
260+
// Iterate manually.
261+
LLVMDbgRecordRef AddDbgRecordFirst = LLVMGetFirstDbgRecord(Add);
262+
assert(AddDbgRecordFirst != NULL);
263+
LLVMDbgRecordRef AddDbgRecordSecond = LLVMGetNextDbgRecord(AddDbgRecordFirst);
264+
assert(AddDbgRecordSecond != NULL);
265+
LLVMDbgRecordRef AddDbgRecordLast = LLVMGetLastDbgRecord(Add);
266+
assert(AddDbgRecordLast != NULL);
267+
assert(AddDbgRecordSecond == AddDbgRecordLast);
268+
LLVMDbgRecordRef AddDbgRecordOverTheRange =
269+
LLVMGetNextDbgRecord(AddDbgRecordSecond);
270+
assert(AddDbgRecordOverTheRange == NULL);
271+
LLVMDbgRecordRef AddDbgRecordFirstPrev =
272+
LLVMGetPreviousDbgRecord(AddDbgRecordSecond);
273+
assert(AddDbgRecordFirstPrev != NULL);
274+
assert(AddDbgRecordFirst == AddDbgRecordFirstPrev);
275+
LLVMDbgRecordRef AddDbgRecordUnderTheRange =
276+
LLVMGetPreviousDbgRecord(AddDbgRecordFirstPrev);
277+
assert(AddDbgRecordUnderTheRange == NULL);
235278

236279
char *MStr = LLVMPrintModuleToString(M);
237280
puts(MStr);

0 commit comments

Comments
 (0)