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

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 20 06:34:45 PDT 2024


Author: Michal Rostecki
Date: 2024-09-20T14:34:42+01:00
New Revision: c320df4a2c9d7be10caea9a423d2bfbdcaae6a39

URL: https://github.com/llvm/llvm-project/commit/c320df4a2c9d7be10caea9a423d2bfbdcaae6a39
DIFF: https://github.com/llvm/llvm-project/commit/c320df4a2c9d7be10caea9a423d2bfbdcaae6a39.diff

LOG: [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.

Added: 
    

Modified: 
    llvm/docs/ReleaseNotes.rst
    llvm/docs/RemoveDIsDebugInfo.md
    llvm/include/llvm-c/Core.h
    llvm/lib/IR/Core.cpp
    llvm/test/Bindings/llvm-c/debug_info_new_format.ll
    llvm/tools/llvm-c-test/debuginfo.c

Removed: 
    


################################################################################
diff  --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 6df4c37b092432..660a3785367a39 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -196,6 +196,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
 -------------------------------------

diff  --git a/llvm/docs/RemoveDIsDebugInfo.md b/llvm/docs/RemoveDIsDebugInfo.md
index 33c590e7800796..c9012548f7578e 100644
--- a/llvm/docs/RemoveDIsDebugInfo.md
+++ b/llvm/docs/RemoveDIsDebugInfo.md
@@ -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.
@@ -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).
@@ -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).
\ 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..19e059295018e4 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -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
  *

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/test/Bindings/llvm-c/debug_info_new_format.ll b/llvm/test/Bindings/llvm-c/debug_info_new_format.ll
index a9ba9d7ad05a70..50496cb1605ec8 100644
--- a/llvm/test/Bindings/llvm-c/debug_info_new_format.ll
+++ b/llvm/test/Bindings/llvm-c/debug_info_new_format.ll
@@ -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: }
@@ -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)

diff  --git a/llvm/tools/llvm-c-test/debuginfo.c b/llvm/tools/llvm-c-test/debuginfo.c
index 49c90f5b87b83a..f025f0d32e5181 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,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);


        


More information about the llvm-commits mailing list