[llvm] [LLVM-C] Add bindings to `Instruction::getDbgRecordRange()` (PR #107802)
Michal Rostecki via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 9 05:13:36 PDT 2024
https://github.com/vadorovsky updated https://github.com/llvm/llvm-project/pull/107802
>From bde6a1f5c04cf79692ea1ddee42d133c9cc77160 Mon Sep 17 00:00:00 2001
From: Michal Rostecki <vadorovsky at protonmail.com>
Date: Thu, 22 Aug 2024 18:12:00 +0200
Subject: [PATCH] [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.
---
llvm/docs/ReleaseNotes.rst | 8 +++++
llvm/docs/RemoveDIsDebugInfo.md | 20 ++++++++++-
llvm/include/llvm-c/Core.h | 27 +++++++++++++++
llvm/lib/IR/Core.cpp | 34 ++++++++++++++++++
llvm/tools/llvm-c-test/debuginfo.c | 55 ++++++++++++++++++++++++++----
5 files changed, 137 insertions(+), 7 deletions(-)
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 52456896f2fc6c..d6d3ed5797e207 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -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 in
+ instructions:
+
+ * ``LLVMGetFirstDbgRecord``
+ * ``LLVMGetLastDbgRecord``
+ * ``LLVMGetNextDbgRecord``
+ * ``LLVMGetPreviousDbgRecord``
+
Changes to the CodeGen infrastructure
-------------------------------------
diff --git a/llvm/docs/RemoveDIsDebugInfo.md b/llvm/docs/RemoveDIsDebugInfo.md
index 33c590e7800796..ec680221f39fc2 100644
--- a/llvm/docs/RemoveDIsDebugInfo.md
+++ b/llvm/docs/RemoveDIsDebugInfo.md
@@ -172,6 +172,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 in instructions (provided as `LLVMValueRef`).
+
+```c
+LLVMDbgRecordRef DbgRec;
+for (DbgRec = LLVMGetFirstDbgRecord(Add); DbgRec;
+ DbgRec = LLVMGetNextDbgRecord(DbgRec)) {
+ // do something with DbgRec
+}
+```
+
+```c
+LLVMDbgRecordRef DbgRec;
+for (DbgRec = LLVMGetLastDbgRecord(Add); 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).
@@ -430,4 +448,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).
\ No newline at end of file
+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).
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index a0786efb51fdb2..fd8d08b3ebd67d 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -3682,6 +3682,33 @@ LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst);
*/
LLVMValueRef LLVMIsATerminatorInst(LLVMValueRef Inst);
+/**
+ * Obtain the first debug record in a instruction.
+ *
+ * The returned debug record can be used as an iterator. You will likely
+ * eventually call into LLVMGetNextDbgRecord() with it.
+ *
+ * @see llvm::Instruction::getDbgRecordRange()
+ */
+LLVMDbgRecordRef LLVMGetFirstDbgRecord(LLVMValueRef Inst);
+
+/**
+ * Obtain the last debug record in a instruction.
+ *
+ * @see llvm::Instruction::getDbgRecordRange()
+ */
+LLVMDbgRecordRef LLVMGetLastDbgRecord(LLVMValueRef Inst);
+
+/**
+ * Advance a debug record iterator.
+ */
+LLVMDbgRecordRef LLVMGetNextDbgRecord(LLVMDbgRecordRef DbgRecord);
+
+/**
+ * Go backwards in a debug record iterator.
+ */
+LLVMDbgRecordRef LLVMGetPreviousDbgRecord(LLVMDbgRecordRef DbgRecord);
+
/**
* @defgroup LLVMCCoreValueInstructionCall Call Sites and Invocations
*
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 28f603b2c38c8a..32a04c59d4d260 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -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"
@@ -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();
diff --git a/llvm/tools/llvm-c-test/debuginfo.c b/llvm/tools/llvm-c-test/debuginfo.c
index 49c90f5b87b83a..d41e6d80956497 100644
--- a/llvm/tools/llvm-c-test/debuginfo.c
+++ b/llvm/tools/llvm-c-test/debuginfo.c
@@ -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>
@@ -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);
LLVMMetadataRef MacroFile =
LLVMDIBuilderCreateTempMacroFile(DIB, NULL, 0, File);
@@ -224,14 +235,46 @@ 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.
+ // Iterate with a for loop.
+ LLVMDbgRecordRef DbgRec;
+ for (DbgRec = LLVMGetFirstDbgRecord(Add); DbgRec;
+ DbgRec = LLVMGetNextDbgRecord(DbgRec)) {
+ assert(DbgRec != NULL);
+ }
+ for (DbgRec = LLVMGetLastDbgRecord(Add); DbgRec;
+ DbgRec = LLVMGetPreviousDbgRecord(DbgRec)) {
+ assert(DbgRec != NULL);
+ }
+ // Iterate manually.
+ 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);
More information about the llvm-commits
mailing list