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

Conversation

vadorovsky
Copy link
Contributor

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.

@vadorovsky vadorovsky requested a review from nikic as a code owner September 9, 2024 03:29
@llvmbot llvmbot added the llvm:ir label Sep 9, 2024
@llvmbot
Copy link
Member

llvmbot commented Sep 9, 2024

@llvm/pr-subscribers-debuginfo

@llvm/pr-subscribers-llvm-ir

Author: Michal Rostecki (vadorovsky)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/107802.diff

3 Files Affected:

  • (modified) llvm/include/llvm-c/Core.h (+27)
  • (modified) llvm/lib/IR/Core.cpp (+34)
  • (modified) llvm/tools/llvm-c-test/debuginfo.c (+28-3)
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index a0786efb51fdb2..a14c5832396e7b 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 ad 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..f068da1d0a63d9 100644
--- a/llvm/tools/llvm-c-test/debuginfo.c
+++ b/llvm/tools/llvm-c-test/debuginfo.c
@@ -12,6 +12,8 @@
 \*===----------------------------------------------------------------------===*/
 
 #include "llvm-c-test.h"
+#include "llvm-c/Core.h"
+#include "llvm-c/Types.h"
 #include "llvm-c/DebugInfo.h"
 
 #include <assert.h>
@@ -172,10 +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 =
+  LLVMMetadataRef FooVarValueExpr1 =
     LLVMDIBuilderCreateConstantValueExpression(DIB, 0);
 
-  LLVMDIBuilderInsertDbgValueRecordAtEnd(DIB, FooVal1, FooVar1, FooVarValueExpr,
+  LLVMDIBuilderInsertDbgValueRecordAtEnd(DIB, FooVal1, FooVar1, FooVarValueExpr1,
+                                         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 =
@@ -224,14 +236,27 @@ 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);
 
   char *MStr = LLVMPrintModuleToString(M);
   puts(MStr);

Copy link

github-actions bot commented Sep 9, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@vadorovsky vadorovsky force-pushed the llvm-c-dbg-record-iter branch 3 times, most recently from 881c490 to c44d0fd Compare September 9, 2024 04:00
@nikic nikic added the debuginfo label Sep 9, 2024
@nikic nikic requested review from jmorse and OCHyams September 9, 2024 07:00
Copy link
Contributor

@OCHyams OCHyams left a comment

Choose a reason for hiding this comment

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

Code changes LGTM, thanks for adding this.

Please could you update the release notes llvm\docs\ReleaseNotes.rst ("Changes to the C API" section) and the migration doc llvm\docs\RemoveDIsDebugInfo.md ("# C-API changes" section)?

Copy link
Member

@weliveindetail weliveindetail left a comment

Choose a reason for hiding this comment

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

Thanks! LGTM, just 2 minor notes: typo in the comment below and the test doesn't exerciseLLVMGetPreviousDbgRecord()

@vadorovsky vadorovsky force-pushed the llvm-c-dbg-record-iter branch from c44d0fd to bde6a1f Compare September 9, 2024 12:13
@vadorovsky
Copy link
Contributor Author

@OCHyams updated both doc files.

@weliveindetail Good catch. I also added test cases with for loops now.

Thanks for review!

@vadorovsky vadorovsky force-pushed the llvm-c-dbg-record-iter branch from bde6a1f to 5ba7f28 Compare September 9, 2024 12:35
Copy link
Contributor

@OCHyams OCHyams left a comment

Choose a reason for hiding this comment

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

Thanks for the update - just a couple of extra comments from me.

Comment on lines 198 to 199
* The following functions are added to allow iterating over debug records in
instructions:
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO: "in" -> "on" or "attached to".

Copy link
Contributor Author

@vadorovsky vadorovsky Sep 9, 2024

Choose a reason for hiding this comment

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

I like "attached to". Will apply in the docstring in Core.h as well.

LLVMDbgRecordRef DbgRec;
for (DbgRec = LLVMGetFirstDbgRecord(Add); DbgRec;
DbgRec = LLVMGetNextDbgRecord(DbgRec)) {
assert(DbgRec != NULL);
Copy link
Contributor

Choose a reason for hiding this comment

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

hmm given the for-loop's condition is that DbgRec is non-null, this assert feels redundant. I think all the functions used in these loops are used in the "manual iteration" below, so we can probably just cut these two loops from the test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure if I'm looking at an old diff or something but I still see the for loops

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now should be pushed, sorry

@@ -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`).
Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry this comment got lost somehow.

Same comment regarding "in" applies here.

Please could you add entries in to the New functions (no plans to deprecate) section (15 or so lines above this) in addition to this part.

Otherwise the docs updates look good, thank you

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@vadorovsky vadorovsky force-pushed the llvm-c-dbg-record-iter branch 2 times, most recently from 8d6bc84 to 6779ad3 Compare September 9, 2024 14:24
Copy link
Contributor

@OCHyams OCHyams left a comment

Choose a reason for hiding this comment

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

Thanks. Once my final nits (sorry) have been addressed I think this LGTM.

I'll let @weliveindetail Accept when they're happy with the patch too.

Comment on lines 157 to 158
LLVMGetFirstDbgRecord # Obtain the first debug record attached to a instruction.
LLVMGetLastDbgRecord # Obtain the last debug record attached to a instruction.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: a -> an

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

LLVMDbgRecordRef DbgRec;
for (DbgRec = LLVMGetFirstDbgRecord(Add); DbgRec;
DbgRec = LLVMGetNextDbgRecord(DbgRec)) {
assert(DbgRec != NULL);
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure if I'm looking at an old diff or something but I still see the for loops

@vadorovsky vadorovsky force-pushed the llvm-c-dbg-record-iter branch 2 times, most recently from 14f5bd0 to d201603 Compare September 10, 2024 14:58
@vadorovsky vadorovsky force-pushed the llvm-c-dbg-record-iter branch from d201603 to 2794bb9 Compare September 13, 2024 06:35
Copy link
Contributor

@OCHyams OCHyams left a comment

Choose a reason for hiding this comment

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

I think @weliveindetail's comments have been addressed, so I'll accept this after these final nit-picks (sorry that I missed them in the last round). Thanks!

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.

Comment on lines 3688 to 3689
* The returned debug record can be used as an iterator. You will likely
* eventually call into LLVMGetNextDbgRecord() with it.
Copy link
Contributor

Choose a reason for hiding this comment

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

We should mention these return null. Something like: "Returns the first DbgRecord attached to Inst or NULL if there are none [...]".

Same thing applies to the other new functions ones below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

I also changed "Returns" to "Return", to make it consistent with the other sentences, which are imperative.

LLVMDbgRecordRef LLVMGetNextDbgRecord(LLVMDbgRecordRef DbgRecord);

/**
* Go backwards in a debug record iterator.
Copy link
Contributor

Choose a reason for hiding this comment

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

Since there are already other changes to make here, I'll raise the nit: "Go backwards using" reads better than "Go backwards in" imo. Or rewording it to something like "Get the next DbgRecord or NULL."

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, I reworded it to "Obtain the next DbgRecord..."

@vadorovsky vadorovsky force-pushed the llvm-c-dbg-record-iter branch from 2794bb9 to 9412984 Compare September 15, 2024 16:44
Copy link
Contributor

@OCHyams OCHyams left a comment

Choose a reason for hiding this comment

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

Because these comments are effectively documentation I've been really nit-picky and added some further suggestions (you should be able to merge these with the web UI).

Other than those bits this LGTM (so I'll accept now), thanks for being patient with this slightly protracted review.

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.
@vadorovsky vadorovsky force-pushed the llvm-c-dbg-record-iter branch from 9412984 to b12c5b3 Compare September 18, 2024 15:29
@vadorovsky
Copy link
Contributor Author

vadorovsky commented Sep 18, 2024

@OCHyams Done.

I don't mind these nitpicks, but I just wanted to mention that many of the nitpicked sentences, like:

  • "Advance a [...] iterator"
  • "Go backwards in [...] iterator"
  • "Obtain the next [...] in [...]"

are not my invention and were already used on other docstrings (e.g. LLVMGet*BasicBlock). I think it would be great to adjust these now too, to avoid inconsistency. Not sure if I should submit a (separate) PR or you would prefer to do that? I don't mind either way.

@OCHyams
Copy link
Contributor

OCHyams commented Sep 19, 2024

@OCHyams Done.

I don't mind these nitpicks, but I just wanted to mention that many of the nitpicked sentences, like:

  • "Advance a [...] iterator"
  • "Go backwards in [...] iterator"
  • "Obtain the next [...] in [...]"

are not my invention and were already used on other docstrings (e.g. LLVMGet*BasicBlock). I think it would be great to adjust these now too, to avoid inconsistency. Not sure if I should submit a (separate) PR or you would prefer to do that? I don't mind either way.

Oh right, I hadn't noticed that, thanks for raising this point. If you're happy to submit another PR for that please do (others may have opinions about whether or not its worth changing the wording of those, but fwiw it seems good to me if we can make things consistent and improve clarity)

Do you have commit access? If not I can merge this one for you.

@vadorovsky
Copy link
Contributor Author

Do you have commit access? If not I can merge this one for you.

I don't, so I would be thankful if you can merge it.

@OCHyams OCHyams merged commit c320df4 into llvm:main Sep 20, 2024
9 checks passed
@vadorovsky vadorovsky deleted the llvm-c-dbg-record-iter branch September 20, 2024 13:37
vadorovsky added a commit to vadorovsky/bpf-linker that referenced this pull request Sep 27, 2024
- Update `llvm-sys` from `191.0.0-rc1` to `191.0.0`.
- Update LLVM to the `rustc/19.1-2024-09-17` branch, which is based
  on the stable LLVM 19.1.0 release.
  - The mentioned branch in our LLVM fork contains also a backport of
    llvm/llvm-project#107802, which is needed for our work on BTF
    relocations.
vadorovsky added a commit to vadorovsky/bpf-linker that referenced this pull request Sep 27, 2024
- Update `llvm-sys` from `191.0.0-rc1` to `191.0.0`.
- Update LLVM to the `rustc/19.1-2024-09-17` branch, which is based
  on the stable LLVM 19.1.0 release.
  - The mentioned branch in our LLVM fork contains a backport of
    llvm/llvm-project#107802, which is needed for our work on BTF
    relocations.
vadorovsky added a commit to aya-rs/bpf-linker that referenced this pull request Sep 27, 2024
- Update `llvm-sys` from `191.0.0-rc1` to `191.0.0`.
- Update LLVM to the `rustc/19.1-2024-09-17` branch, which is based
  on the stable LLVM 19.1.0 release.
  - The mentioned branch in our LLVM fork contains a backport of
    llvm/llvm-project#107802, which is needed for our work on BTF
    relocations.
vadorovsky added a commit to aya-rs/llvm-project that referenced this pull request Dec 2, 2024
)

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants