[clang] [llvm] [clang-tools-extra] [C API] Add blockaddress getters to C API (PR #77390)
Benji Smith via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 24 16:23:53 PST 2024
https://github.com/Benjins updated https://github.com/llvm/llvm-project/pull/77390
>From 43db89c2bc2a42ff1e88deb99b7214e3e37e317c Mon Sep 17 00:00:00 2001
From: Benji Smith <6193112+Benjins at users.noreply.github.com>
Date: Sun, 7 Jan 2024 20:16:25 -0500
Subject: [PATCH 1/2] Refactor llvm-c-test to pre-declare all basic blocks for
all functions
This is necessary for being able to clone blockaddress values, since they can
reference basic blocks in other functions. We declare all basic blocks up front
similar to how all functions are declared, and find them when the function
itself is cloned
---
llvm/tools/llvm-c-test/echo.cpp | 46 +++++++++++++++++++++++++++++++--
1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp
index bc708e2d472edd..5d9e26f875e5da 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");
@@ -432,6 +446,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 +1067,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 +1220,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)
>From 68a433cdda2cc5e310f36a424b37feaf93052e96 Mon Sep 17 00:00:00 2001
From: Benji Smith <6193112+Benjins at users.noreply.github.com>
Date: Sun, 7 Jan 2024 20:43:25 -0500
Subject: [PATCH 2/2] Add LLVMGetBlockAddressFunction and
LLVMGetBlockAddressBasicBlock getters
This allows for accessing the function/basic block that a blockaddress constant
refers to
Tests are added for it in the llvm-c-test echo.ll file
---
llvm/docs/ReleaseNotes.rst | 3 +++
llvm/include/llvm-c/Core.h | 10 ++++++++++
llvm/lib/IR/Core.cpp | 8 ++++++++
llvm/test/Bindings/llvm-c/echo.ll | 26 ++++++++++++++++++++++++++
llvm/tools/llvm-c-test/echo.cpp | 16 ++++++++++++++++
5 files changed, 63 insertions(+)
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 5d9e26f875e5da..153001e0a23931 100644
--- a/llvm/tools/llvm-c-test/echo.cpp
+++ b/llvm/tools/llvm-c-test/echo.cpp
@@ -387,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))
More information about the cfe-commits
mailing list