Skip to content

[LLVM-C] Add bindings to Instruction::getDbgRecordRange() #107802

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 20, 2024
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
8 changes: 8 additions & 0 deletions llvm/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,14 @@ Changes to the C API
* The `LLVMSetPersonalityFn` and `LLVMSetInitializer` APIs now support clearing the
personality function and initializer respectively by passing a null pointer.

* The following functions are added to allow iterating over debug records attached to
instructions:

* ``LLVMGetFirstDbgRecord``
* ``LLVMGetLastDbgRecord``
* ``LLVMGetNextDbgRecord``
* ``LLVMGetPreviousDbgRecord``


Changes to the CodeGen infrastructure
-------------------------------------
Expand Down
24 changes: 23 additions & 1 deletion llvm/docs/RemoveDIsDebugInfo.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ LLVMSetIsNewDbgInfoFormat # Convert to the requested debug info format.

New functions (no plans to deprecate)
-------------------------------------
LLVMGetFirstDbgRecord # Obtain the first debug record attached to an instruction.
LLVMGetLastDbgRecord # Obtain the last debug record attached to an instruction.
LLVMGetNextDbgRecord # Get next debug record or NULL.
LLVMGetPreviousDbgRecord # Get previous debug record or NULL.
LLVMDIBuilderInsertDeclareRecordBefore # Insert a debug record (new debug info format).
LLVMDIBuilderInsertDeclareRecordAtEnd # Same as above. See info below.
LLVMDIBuilderInsertDbgValueRecordBefore # Same as above. See info below.
Expand All @@ -172,6 +176,24 @@ If you are trying to insert at the start of a block, or purposfully skip debug i

`LLVMPositionBuilder` and `LLVMPositionBuilderBefore` are unchanged. They insert before the indicated instruction but after any attached debug records.

`LLVMGetFirstDbgRecord`, `LLVMGetLastDbgRecord`, `LLVMGetNextDbgRecord` and `LLVMGetPreviousDbgRecord` can be used for iterating over debug records attached to instructions (provided as `LLVMValueRef`).

```c
LLVMDbgRecordRef DbgRec;
for (DbgRec = LLVMGetFirstDbgRecord(Inst); DbgRec;
DbgRec = LLVMGetNextDbgRecord(DbgRec)) {
// do something with DbgRec
}
```

```c
LLVMDbgRecordRef DbgRec;
for (DbgRec = LLVMGetLastDbgRecord(Inst); DbgRec;
DbgRec = LLVMGetPreviousDbgRecord(DbgRec)) {
// do something with DbgRec
}
````

# The new "Debug Record" model

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).
Expand Down Expand Up @@ -430,4 +452,4 @@ This can technically lead to trouble in the vanishingly rare scenario where an o

## Anything else?

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).
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).
35 changes: 35 additions & 0 deletions llvm/include/llvm-c/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -3682,6 +3682,41 @@ LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst);
*/
LLVMValueRef LLVMIsATerminatorInst(LLVMValueRef Inst);

/**
* Obtain the first debug record attached to an instruction.
*
* Use LLVMGetNextDbgRecord() and LLVMGetPreviousDbgRecord() to traverse the
* sequence of DbgRecords.
*
* Return the first DbgRecord attached to Inst or NULL if there are none.
*
* @see llvm::Instruction::getDbgRecordRange()
*/
LLVMDbgRecordRef LLVMGetFirstDbgRecord(LLVMValueRef Inst);

/**
* Obtain the last debug record attached to an instruction.
*
* Return the last DbgRecord attached to Inst or NULL if there are none.
*
* @see llvm::Instruction::getDbgRecordRange()
*/
LLVMDbgRecordRef LLVMGetLastDbgRecord(LLVMValueRef Inst);

/**
* Obtain the next DbgRecord in the sequence or NULL if there are no more.
*
* @see llvm::Instruction::getDbgRecordRange()
*/
LLVMDbgRecordRef LLVMGetNextDbgRecord(LLVMDbgRecordRef DbgRecord);

/**
* Obtain the previous DbgRecord in the sequence or NULL if there are no more.
*
* @see llvm::Instruction::getDbgRecordRange()
*/
LLVMDbgRecordRef LLVMGetPreviousDbgRecord(LLVMDbgRecordRef DbgRecord);

/**
* @defgroup LLVMCCoreValueInstructionCall Call Sites and Invocations
*
Expand Down
34 changes: 34 additions & 0 deletions llvm/lib/IR/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
//===----------------------------------------------------------------------===//

#include "llvm-c/Core.h"
#include "llvm-c/Types.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugProgramInstruction.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
Expand Down Expand Up @@ -2975,6 +2977,38 @@ LLVMValueRef LLVMIsATerminatorInst(LLVMValueRef Inst) {
return (I && I->isTerminator()) ? wrap(I) : nullptr;
}

LLVMDbgRecordRef LLVMGetFirstDbgRecord(LLVMValueRef Inst) {
Instruction *Instr = unwrap<Instruction>(Inst);
auto I = Instr->DebugMarker->StoredDbgRecords.begin();
if (I == Instr->DebugMarker->StoredDbgRecords.end())
return nullptr;
return wrap(&*I);
}

LLVMDbgRecordRef LLVMGetLastDbgRecord(LLVMValueRef Inst) {
Instruction *Instr = unwrap<Instruction>(Inst);
auto I = Instr->DebugMarker->StoredDbgRecords.rbegin();
if (I == Instr->DebugMarker->StoredDbgRecords.rend())
return nullptr;
return wrap(&*I);
}

LLVMDbgRecordRef LLVMGetNextDbgRecord(LLVMDbgRecordRef Rec) {
DbgRecord *Record = unwrap<DbgRecord>(Rec);
simple_ilist<DbgRecord>::iterator I(Record);
if (++I == Record->getInstruction()->DebugMarker->StoredDbgRecords.end())
return nullptr;
return wrap(&*I);
}

LLVMDbgRecordRef LLVMGetPreviousDbgRecord(LLVMDbgRecordRef Rec) {
DbgRecord *Record = unwrap<DbgRecord>(Rec);
simple_ilist<DbgRecord>::iterator I(Record);
if (I == Record->getInstruction()->DebugMarker->StoredDbgRecords.begin())
return nullptr;
return wrap(&*--I);
}

unsigned LLVMGetNumArgOperands(LLVMValueRef Instr) {
if (FuncletPadInst *FPI = dyn_cast<FuncletPadInst>(unwrap(Instr))) {
return FPI->arg_size();
Expand Down
16 changes: 9 additions & 7 deletions llvm/test/Bindings/llvm-c/debug_info_new_format.ll
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@

; CHECK: define i64 @foo(i64 %0, i64 %1, <10 x i64> %2) !dbg !31 {
; CHECK-NEXT: entry:
; CHECK-NEXT: #dbg_declare(i64 0, !38, !DIExpression(), !43)
; CHECK-NEXT: #dbg_declare(i64 0, !39, !DIExpression(), !43)
; CHECK-NEXT: #dbg_declare(i64 0, !40, !DIExpression(), !43)
; CHECK-NEXT: #dbg_declare(i64 0, !38, !DIExpression(), !44)
; CHECK-NEXT: #dbg_declare(i64 0, !39, !DIExpression(), !44)
; CHECK-NEXT: #dbg_declare(i64 0, !40, !DIExpression(), !44)
; CHECK-NEXT: br label %vars
; CHECK: vars:
; CHECK-NEXT: %p1 = phi i64 [ 0, %entry ]
; CHECK-NEXT: %p2 = phi i64 [ 0, %entry ]
; CHECK-NEXT: #dbg_value(i64 0, !41, !DIExpression(DW_OP_constu, 0, DW_OP_stack_value), !44)
; CHECK-NEXT: #dbg_value(i64 0, !41, !DIExpression(DW_OP_constu, 0, DW_OP_stack_value), !45)
; CHECK-NEXT: #dbg_value(i64 1, !43, !DIExpression(DW_OP_constu, 1, DW_OP_stack_value), !45)
; CHECK-NEXT: %a = add i64 %p1, %p2
; CHECK-NEXT: ret i64 0
; CHECK-NEXT: }
Expand Down Expand Up @@ -59,11 +60,12 @@
; CHECK-NEXT: !34 = !DICompositeType(tag: DW_TAG_array_type, baseType: !6, size: 640, flags: DIFlagVector, elements: !35)
; CHECK-NEXT: !35 = !{!36}
; CHECK-NEXT: !36 = !DISubrange(count: 10, lowerBound: 0)
; CHECK-NEXT: !37 = !{!38, !39, !40, !41}
; CHECK-NEXT: !37 = !{!38, !39, !40, !41, !43}
; CHECK-NEXT: !38 = !DILocalVariable(name: "a", arg: 1, scope: !31, file: !1, line: 42, type: !6)
; CHECK-NEXT: !39 = !DILocalVariable(name: "b", arg: 2, scope: !31, file: !1, line: 42, type: !6)
; CHECK-NEXT: !40 = !DILocalVariable(name: "c", arg: 3, scope: !31, file: !1, line: 42, type: !34)
; CHECK-NEXT: !41 = !DILocalVariable(name: "d", scope: !42, file: !1, line: 43, type: !6)
; CHECK-NEXT: !42 = distinct !DILexicalBlock(scope: !31, file: !1, line: 42)
; CHECK-NEXT: !43 = !DILocation(line: 42, scope: !31)
; CHECK-NEXT: !44 = !DILocation(line: 43, scope: !31)
; CHECK-NEXT: !43 = !DILocalVariable(name: "e", scope: !42, file: !1, line: 44, type: !6)
; CHECK-NEXT: !44 = !DILocation(line: 42, scope: !31)
; CHECK-NEXT: !45 = !DILocation(line: 43, scope: !31)
44 changes: 38 additions & 6 deletions llvm/tools/llvm-c-test/debuginfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
|* *|
\*===----------------------------------------------------------------------===*/

#include "llvm-c-test.h"
#include "llvm-c/DebugInfo.h"
#include "llvm-c-test.h"
#include "llvm-c/Core.h"
#include "llvm-c/Types.h"

#include <assert.h>
#include <stdio.h>
Expand Down Expand Up @@ -172,11 +174,20 @@ int llvm_test_dibuilder(void) {
LLVMDIBuilderCreateAutoVariable(DIB, FooLexicalBlock, "d", 1, File,
43, Int64Ty, true, 0, 0);
LLVMValueRef FooVal1 = LLVMConstInt(LLVMInt64Type(), 0, false);
LLVMMetadataRef FooVarValueExpr =
LLVMDIBuilderCreateConstantValueExpression(DIB, 0);
LLVMMetadataRef FooVarValueExpr1 =
LLVMDIBuilderCreateConstantValueExpression(DIB, 0);

LLVMDIBuilderInsertDbgValueRecordAtEnd(
DIB, FooVal1, FooVar1, FooVarValueExpr1, FooVarsLocation, FooVarBlock);

LLVMDIBuilderInsertDbgValueRecordAtEnd(DIB, FooVal1, FooVar1, FooVarValueExpr,
FooVarsLocation, FooVarBlock);
LLVMMetadataRef FooVar2 = LLVMDIBuilderCreateAutoVariable(
DIB, FooLexicalBlock, "e", 1, File, 44, Int64Ty, true, 0, 0);
LLVMValueRef FooVal2 = LLVMConstInt(LLVMInt64Type(), 1, false);
LLVMMetadataRef FooVarValueExpr2 =
LLVMDIBuilderCreateConstantValueExpression(DIB, 1);

LLVMDIBuilderInsertDbgValueRecordAtEnd(
DIB, FooVal2, FooVar2, FooVarValueExpr2, FooVarsLocation, FooVarBlock);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does llvm\test\Bindings\llvm-c\debug_info.ll not need any updates with this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It needed an update indeed, should be fixed now. That was most likely the reason behind red CI builds.


LLVMMetadataRef MacroFile =
LLVMDIBuilderCreateTempMacroFile(DIB, NULL, 0, File);
Expand Down Expand Up @@ -224,14 +235,35 @@ int llvm_test_dibuilder(void) {
LLVMPositionBuilderBeforeInstrAndDbgRecords(Builder, InsertPos);
LLVMValueRef Phi1 = LLVMBuildPhi(Builder, I64, "p1");
LLVMAddIncoming(Phi1, &Zero, &FooEntryBlock, 1);

// Do the same again using the other position-setting function.
LLVMPositionBuilderBeforeDbgRecords(Builder, FooVarBlock, InsertPos);
LLVMValueRef Phi2 = LLVMBuildPhi(Builder, I64, "p2");
LLVMAddIncoming(Phi2, &Zero, &FooEntryBlock, 1);

// Insert a non-phi before the `ret` but not before the debug records to
// test that works as expected.
LLVMPositionBuilder(Builder, FooVarBlock, Ret);
LLVMBuildAdd(Builder, Phi1, Phi2, "a");
LLVMValueRef Add = LLVMBuildAdd(Builder, Phi1, Phi2, "a");

// Iterate over debug records in the add instruction. There should be two.
LLVMDbgRecordRef AddDbgRecordFirst = LLVMGetFirstDbgRecord(Add);
assert(AddDbgRecordFirst != NULL);
LLVMDbgRecordRef AddDbgRecordSecond = LLVMGetNextDbgRecord(AddDbgRecordFirst);
assert(AddDbgRecordSecond != NULL);
LLVMDbgRecordRef AddDbgRecordLast = LLVMGetLastDbgRecord(Add);
assert(AddDbgRecordLast != NULL);
assert(AddDbgRecordSecond == AddDbgRecordLast);
LLVMDbgRecordRef AddDbgRecordOverTheRange =
LLVMGetNextDbgRecord(AddDbgRecordSecond);
assert(AddDbgRecordOverTheRange == NULL);
LLVMDbgRecordRef AddDbgRecordFirstPrev =
LLVMGetPreviousDbgRecord(AddDbgRecordSecond);
assert(AddDbgRecordFirstPrev != NULL);
assert(AddDbgRecordFirst == AddDbgRecordFirstPrev);
LLVMDbgRecordRef AddDbgRecordUnderTheRange =
LLVMGetPreviousDbgRecord(AddDbgRecordFirstPrev);
assert(AddDbgRecordUnderTheRange == NULL);

char *MStr = LLVMPrintModuleToString(M);
puts(MStr);
Expand Down
Loading