[llvm] [C API] Add blockaddress getters to C API (PR #77390)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 8 14:56:25 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-ir
Author: Benji Smith (Benjins)
<details>
<summary>Changes</summary>
Exposes getters for the function and basic block associated with blockaddress constants to the C API. Tests for them are added, which required a tweak to llvm-c-test to declare basic blocks ahead of any actual function cloning, since the blockaddress constants may reference basic blocks in arbitrary other functions
----------------------------
This PR is split into two commits for reviewing sake. The first commit is the refactor of `echo.cpp` to pre-declare all basic blocks in `declare_symbols` along with the functions. The second commit contains the pertinent change to the C API
---
Full diff: https://github.com/llvm/llvm-project/pull/77390.diff
5 Files Affected:
- (modified) llvm/docs/ReleaseNotes.rst (+3)
- (modified) llvm/include/llvm-c/Core.h (+10)
- (modified) llvm/lib/IR/Core.cpp (+8)
- (modified) llvm/test/Bindings/llvm-c/echo.ll (+26)
- (modified) llvm/tools/llvm-c-test/echo.cpp (+60-2)
``````````diff
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 52610e7de18751..24dc9614d97dc5 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -246,6 +246,9 @@ Changes to the C API
the fast-math flags of an instruction, as well as ``LLVMCanValueUseFastMathFlags``
for checking if an instruction can use such flags
+* Added ``LLVMGetBlockAddressFunction`` and ``LLVMGetBlockAddressBasicBlock``
+ functions for accessing the values in a blockaddress constant
+
Changes to the CodeGen infrastructure
-------------------------------------
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 83530ae7b51324..1b9683a1d490ad 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -2328,6 +2328,16 @@ LLVMValueRef LLVMConstShuffleVector(LLVMValueRef VectorAConstant,
LLVMValueRef MaskConstant);
LLVMValueRef LLVMBlockAddress(LLVMValueRef F, LLVMBasicBlockRef BB);
+/**
+ * Gets the function associated with a given BlockAddress constant value
+ */
+LLVMValueRef LLVMGetBlockAddressFunction(LLVMValueRef BlockAddr);
+
+/**
+ * Gets the basic block associated with a given BlockAddress constant value
+ */
+LLVMBasicBlockRef LLVMGetBlockAddressBasicBlock(LLVMValueRef BlockAddr);
+
/** Deprecated: Use LLVMGetInlineAsm instead. */
LLVMValueRef LLVMConstInlineAsm(LLVMTypeRef Ty,
const char *AsmString, const char *Constraints,
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index fb30fbce0ba22e..d6d159ab8b9e83 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -1805,6 +1805,14 @@ LLVMValueRef LLVMBlockAddress(LLVMValueRef F, LLVMBasicBlockRef BB) {
return wrap(BlockAddress::get(unwrap<Function>(F), unwrap(BB)));
}
+LLVMValueRef LLVMGetBlockAddressFunction(LLVMValueRef BlockAddr) {
+ return wrap(unwrap<BlockAddress>(BlockAddr)->getFunction());
+}
+
+LLVMBasicBlockRef LLVMGetBlockAddressBasicBlock(LLVMValueRef BlockAddr) {
+ return wrap(unwrap<BlockAddress>(BlockAddr)->getBasicBlock());
+}
+
/*--.. Operations on global variables, functions, and aliases (globals) ....--*/
LLVMModuleRef LLVMGetGlobalParent(LLVMValueRef Global) {
diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll
index be0207599478b8..c69c921823a510 100644
--- a/llvm/test/Bindings/llvm-c/echo.ll
+++ b/llvm/test/Bindings/llvm-c/echo.ll
@@ -334,6 +334,32 @@ define void @test_fast_math_flags_call_outer(float %a) {
ret void
}
+define ptr @test_block_address_01() {
+entry:
+ br label %block_0
+block_0:
+ ret ptr blockaddress(@test_block_address_01, %block_0)
+}
+
+define ptr @test_block_address_02() {
+entry:
+ ret ptr blockaddress(@test_block_address_01, %block_0)
+}
+
+define ptr @test_block_address_03() {
+entry:
+ br label %block_1
+block_1:
+ ret ptr blockaddress(@test_block_address_04, %block_2)
+}
+
+define ptr @test_block_address_04() {
+entry:
+ br label %block_2
+block_2:
+ ret ptr blockaddress(@test_block_address_03, %block_1)
+}
+
!llvm.dbg.cu = !{!0, !2}
!llvm.module.flags = !{!3}
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp
index bc708e2d472edd..153001e0a23931 100644
--- a/llvm/tools/llvm-c-test/echo.cpp
+++ b/llvm/tools/llvm-c-test/echo.cpp
@@ -238,6 +238,20 @@ static LLVMValueRef clone_constant(LLVMValueRef Cst, LLVMModuleRef M) {
return Ret;
}
+static LLVMBasicBlockRef find_bb_in_func(LLVMValueRef Fn, const char *BBName) {
+ LLVMBasicBlockRef CurBB = LLVMGetFirstBasicBlock(Fn);
+ while (CurBB != nullptr) {
+
+ const char *CurBBName = LLVMGetBasicBlockName(CurBB);
+ if (strcmp(CurBBName, BBName) == 0)
+ return CurBB;
+
+ CurBB = LLVMGetNextBasicBlock(CurBB);
+ }
+
+ return nullptr;
+}
+
static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
if (!LLVMIsAConstant(Cst))
report_fatal_error("Expected a constant");
@@ -373,6 +387,22 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
return LLVMConstVector(Elts.data(), EltCount);
}
+ if (LLVMIsABlockAddress(Cst)) {
+ check_value_kind(Cst, LLVMBlockAddressValueKind);
+ LLVMValueRef SrcFunc = LLVMGetBlockAddressFunction(Cst);
+ LLVMBasicBlockRef SrcBB = LLVMGetBlockAddressBasicBlock(Cst);
+
+ LLVMValueRef DstFunc = clone_constant(SrcFunc, M);
+
+ LLVMBasicBlockRef DstBB =
+ find_bb_in_func(DstFunc, LLVMGetBasicBlockName(SrcBB));
+ if (DstBB == nullptr)
+ report_fatal_error(
+ "Could not find basic block with expected name for blockaddress");
+
+ return LLVMBlockAddress(DstFunc, DstBB);
+ }
+
// At this point, if it's not a constant expression, it's a kind of constant
// which is not supported
if (!LLVMIsAConstantExpr(Cst))
@@ -432,6 +462,17 @@ static LLVMValueRef clone_inline_asm(LLVMValueRef Asm, LLVMModuleRef M) {
CanUnwind);
}
+static LLVMBasicBlockRef declare_bb_in_func(LLVMValueRef DstFn,
+ LLVMBasicBlockRef Src) {
+ const char *Name = LLVMGetBasicBlockName(Src);
+
+ if (find_bb_in_func(DstFn, Name) != nullptr)
+ report_fatal_error("Trying to re-declare existing basic block");
+
+ LLVMBasicBlockRef DstBB = LLVMAppendBasicBlock(DstFn, Name);
+ return DstBB;
+}
+
struct FunCloner {
LLVMValueRef Fun;
LLVMModuleRef M;
@@ -1042,8 +1083,15 @@ struct FunCloner {
if (Name != VName)
report_fatal_error("Basic block name mismatch");
- LLVMBasicBlockRef BB = LLVMAppendBasicBlock(Fun, Name);
- return BBMap[Src] = BB;
+ // Scan for existing basic blocks that we forward-declared
+ // If a basic block is not cached in BBMap already, then it should exist
+ // in Fun, since we should have pre-declared all basic blocks earlier in
+ // declare_symbols
+ if (LLVMBasicBlockRef ExistingBB = find_bb_in_func(Fun, Name))
+ return BBMap[Src] = ExistingBB;
+
+ report_fatal_error("Trying to declare new basic block");
+ return nullptr;
}
LLVMBasicBlockRef CloneBB(LLVMBasicBlockRef Src) {
@@ -1188,6 +1236,16 @@ static void declare_symbols(LLVMModuleRef Src, LLVMModuleRef M) {
}
}
+ // Declare any basic blocks in this function:
+ // We need to do this here, in case any blockaddress value's are used,
+ // in which case we may reference basic blocks in any function
+ // Therefore, declare them before actually cloning any function
+ LLVMBasicBlockRef CurSrcBB = LLVMGetFirstBasicBlock(Cur);
+ while (CurSrcBB != nullptr) {
+ declare_bb_in_func(F, CurSrcBB);
+ CurSrcBB = LLVMGetNextBasicBlock(CurSrcBB);
+ }
+
Next = LLVMGetNextFunction(Cur);
if (Next == nullptr) {
if (Cur != End)
``````````
</details>
https://github.com/llvm/llvm-project/pull/77390
More information about the llvm-commits
mailing list