[llvm] [C API] Add blockaddress getters to C API (PR #81382)

Benji Smith via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 11 04:53:27 PST 2024


https://github.com/Benjins updated https://github.com/llvm/llvm-project/pull/81382

>From b11bbd790beb281e799f3a1048be9275756c4e69 Mon Sep 17 00:00:00 2001
From: Benji Smith <benjsith at gmail.com>
Date: Sun, 7 Jan 2024 20:43:25 -0500
Subject: [PATCH 1/2] Add LLVMGetBlockAddressFunction and
 LLVMGetBlockAddressBasicBlock getters

This allows for accessing the function/basic block that a blockaddress constant
refers to

Due to the difficulties of cloning BlockAddress values in echo.cpp, tests are
instead done using a unit test as part of llvm-c-test, with a new test file,
block_address.ll
---
 llvm/docs/ReleaseNotes.rst                 |  3 ++
 llvm/include/llvm-c/Core.h                 | 10 ++++++
 llvm/lib/IR/Core.cpp                       |  8 +++++
 llvm/test/Bindings/llvm-c/block_address.ll | 39 ++++++++++++++++++++++
 llvm/tools/llvm-c-test/llvm-c-test.h       |  1 +
 llvm/tools/llvm-c-test/main.c              |  3 ++
 llvm/tools/llvm-c-test/module.c            | 28 ++++++++++++++++
 7 files changed, 92 insertions(+)
 create mode 100644 llvm/test/Bindings/llvm-c/block_address.ll

diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 05d8eea3add419..120e8b637136a6 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -122,6 +122,9 @@ Changes to the Python bindings
 Changes to the C API
 --------------------
 
+* 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..09746bdaf0c94e 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/block_address.ll b/llvm/test/Bindings/llvm-c/block_address.ll
new file mode 100644
index 00000000000000..f1284b8839b17a
--- /dev/null
+++ b/llvm/test/Bindings/llvm-c/block_address.ll
@@ -0,0 +1,39 @@
+; RUN: llvm-as < %s | llvm-c-test --module-list-global-block-address-values | FileCheck %s
+
+
+define void @test_block_address_01() {
+entry:
+  br label %block_0
+block_0:
+  ret void
+}
+
+define void @test_block_address_02() {
+entry:
+  br label %block_0
+block_0:
+  ret void
+}
+
+define void @test_block_address_03() {
+entry:
+  br label %block_0
+block_0:
+  br label %block_1
+block_1:
+  ret void
+}
+
+
+ at g_block_address_01 = global ptr blockaddress(@test_block_address_01, %block_0)
+;CHECK: BlockAddress 'g_block_address_01' Func 'test_block_address_01' Basic Block 'block_0'
+
+ at g_block_address_02 = global ptr blockaddress(@test_block_address_02, %block_0)
+;CHECK: BlockAddress 'g_block_address_02' Func 'test_block_address_02' Basic Block 'block_0'
+
+ at g_block_address_03 = global ptr blockaddress(@test_block_address_03, %block_0)
+;CHECK: BlockAddress 'g_block_address_03' Func 'test_block_address_03' Basic Block 'block_0'
+
+ at g_block_address_04 = global ptr blockaddress(@test_block_address_03, %block_1)
+;CHECK: BlockAddress 'g_block_address_04' Func 'test_block_address_03' Basic Block 'block_1'
+
diff --git a/llvm/tools/llvm-c-test/llvm-c-test.h b/llvm/tools/llvm-c-test/llvm-c-test.h
index 00566660257e07..ad9a63806065e5 100644
--- a/llvm/tools/llvm-c-test/llvm-c-test.h
+++ b/llvm/tools/llvm-c-test/llvm-c-test.h
@@ -28,6 +28,7 @@ LLVMModuleRef llvm_load_module(bool Lazy, bool New);
 int llvm_module_dump(bool Lazy, bool New);
 int llvm_module_list_functions(void);
 int llvm_module_list_globals(void);
+int llvm_module_list_global_block_address_values(void);
 
 // calc.c
 int llvm_calc(void);
diff --git a/llvm/tools/llvm-c-test/main.c b/llvm/tools/llvm-c-test/main.c
index badbe4b13b6ba5..ecef9b34a4c364 100644
--- a/llvm/tools/llvm-c-test/main.c
+++ b/llvm/tools/llvm-c-test/main.c
@@ -111,6 +111,9 @@ int main(int argc, char **argv) {
     return llvm_test_diagnostic_handler();
   } else if (argc == 2 && !strcmp(argv[1], "--test-dibuilder")) {
     return llvm_test_dibuilder();
+  } else if (argc == 2 &&
+             !strcmp(argv[1], "--module-list-global-block-address-values")) {
+    return llvm_module_list_global_block_address_values();
   } else {
     print_usage();
   }
diff --git a/llvm/tools/llvm-c-test/module.c b/llvm/tools/llvm-c-test/module.c
index 9fc86cfe5404b3..989f96b6cf1dee 100644
--- a/llvm/tools/llvm-c-test/module.c
+++ b/llvm/tools/llvm-c-test/module.c
@@ -136,3 +136,31 @@ int llvm_module_list_globals(void) {
 
   return 0;
 }
+
+int llvm_module_list_global_block_address_values(void) {
+  LLVMModuleRef M = llvm_load_module(false, false);
+  LLVMValueRef g;
+
+  g = LLVMGetFirstGlobal(M);
+  while (g) {
+    LLVMValueRef GInit = LLVMGetInitializer(g);
+
+    if (GInit && LLVMIsABlockAddress(GInit)) {
+      const char *GlobalName = LLVMGetValueName(g);
+      LLVMValueRef Func = LLVMGetBlockAddressFunction(GInit);
+      LLVMBasicBlockRef BB = LLVMGetBlockAddressBasicBlock(GInit);
+
+      const char *FuncName = LLVMGetValueName(Func);
+      const char *BBName = LLVMGetBasicBlockName(BB);
+
+      printf("BlockAddress '%s' Func '%s' Basic Block '%s'\n", GlobalName,
+             FuncName, BBName);
+    }
+
+    g = LLVMGetNextGlobal(g);
+  }
+
+  LLVMDisposeModule(M);
+
+  return 0;
+}

>From 4a5c13d353fed6ede2c956755a838d9cbffe20b1 Mon Sep 17 00:00:00 2001
From: Benji Smith <6193112+Benjins at users.noreply.github.com>
Date: Sun, 11 Feb 2024 07:46:56 -0500
Subject: [PATCH 2/2] Change blockaddress C API test from llvm-c-test to a unit
 test

---
 llvm/test/Bindings/llvm-c/block_address.ll | 39 ----------------------
 llvm/tools/llvm-c-test/llvm-c-test.h       |  1 -
 llvm/tools/llvm-c-test/main.c              |  3 --
 llvm/tools/llvm-c-test/module.c            | 28 ----------------
 llvm/unittests/IR/ConstantsTest.cpp        | 39 ++++++++++++++++++++++
 5 files changed, 39 insertions(+), 71 deletions(-)
 delete mode 100644 llvm/test/Bindings/llvm-c/block_address.ll

diff --git a/llvm/test/Bindings/llvm-c/block_address.ll b/llvm/test/Bindings/llvm-c/block_address.ll
deleted file mode 100644
index f1284b8839b17a..00000000000000
--- a/llvm/test/Bindings/llvm-c/block_address.ll
+++ /dev/null
@@ -1,39 +0,0 @@
-; RUN: llvm-as < %s | llvm-c-test --module-list-global-block-address-values | FileCheck %s
-
-
-define void @test_block_address_01() {
-entry:
-  br label %block_0
-block_0:
-  ret void
-}
-
-define void @test_block_address_02() {
-entry:
-  br label %block_0
-block_0:
-  ret void
-}
-
-define void @test_block_address_03() {
-entry:
-  br label %block_0
-block_0:
-  br label %block_1
-block_1:
-  ret void
-}
-
-
- at g_block_address_01 = global ptr blockaddress(@test_block_address_01, %block_0)
-;CHECK: BlockAddress 'g_block_address_01' Func 'test_block_address_01' Basic Block 'block_0'
-
- at g_block_address_02 = global ptr blockaddress(@test_block_address_02, %block_0)
-;CHECK: BlockAddress 'g_block_address_02' Func 'test_block_address_02' Basic Block 'block_0'
-
- at g_block_address_03 = global ptr blockaddress(@test_block_address_03, %block_0)
-;CHECK: BlockAddress 'g_block_address_03' Func 'test_block_address_03' Basic Block 'block_0'
-
- at g_block_address_04 = global ptr blockaddress(@test_block_address_03, %block_1)
-;CHECK: BlockAddress 'g_block_address_04' Func 'test_block_address_03' Basic Block 'block_1'
-
diff --git a/llvm/tools/llvm-c-test/llvm-c-test.h b/llvm/tools/llvm-c-test/llvm-c-test.h
index ad9a63806065e5..00566660257e07 100644
--- a/llvm/tools/llvm-c-test/llvm-c-test.h
+++ b/llvm/tools/llvm-c-test/llvm-c-test.h
@@ -28,7 +28,6 @@ LLVMModuleRef llvm_load_module(bool Lazy, bool New);
 int llvm_module_dump(bool Lazy, bool New);
 int llvm_module_list_functions(void);
 int llvm_module_list_globals(void);
-int llvm_module_list_global_block_address_values(void);
 
 // calc.c
 int llvm_calc(void);
diff --git a/llvm/tools/llvm-c-test/main.c b/llvm/tools/llvm-c-test/main.c
index ecef9b34a4c364..badbe4b13b6ba5 100644
--- a/llvm/tools/llvm-c-test/main.c
+++ b/llvm/tools/llvm-c-test/main.c
@@ -111,9 +111,6 @@ int main(int argc, char **argv) {
     return llvm_test_diagnostic_handler();
   } else if (argc == 2 && !strcmp(argv[1], "--test-dibuilder")) {
     return llvm_test_dibuilder();
-  } else if (argc == 2 &&
-             !strcmp(argv[1], "--module-list-global-block-address-values")) {
-    return llvm_module_list_global_block_address_values();
   } else {
     print_usage();
   }
diff --git a/llvm/tools/llvm-c-test/module.c b/llvm/tools/llvm-c-test/module.c
index 989f96b6cf1dee..9fc86cfe5404b3 100644
--- a/llvm/tools/llvm-c-test/module.c
+++ b/llvm/tools/llvm-c-test/module.c
@@ -136,31 +136,3 @@ int llvm_module_list_globals(void) {
 
   return 0;
 }
-
-int llvm_module_list_global_block_address_values(void) {
-  LLVMModuleRef M = llvm_load_module(false, false);
-  LLVMValueRef g;
-
-  g = LLVMGetFirstGlobal(M);
-  while (g) {
-    LLVMValueRef GInit = LLVMGetInitializer(g);
-
-    if (GInit && LLVMIsABlockAddress(GInit)) {
-      const char *GlobalName = LLVMGetValueName(g);
-      LLVMValueRef Func = LLVMGetBlockAddressFunction(GInit);
-      LLVMBasicBlockRef BB = LLVMGetBlockAddressBasicBlock(GInit);
-
-      const char *FuncName = LLVMGetValueName(Func);
-      const char *BBName = LLVMGetBasicBlockName(BB);
-
-      printf("BlockAddress '%s' Func '%s' Basic Block '%s'\n", GlobalName,
-             FuncName, BBName);
-    }
-
-    g = LLVMGetNextGlobal(g);
-  }
-
-  LLVMDisposeModule(M);
-
-  return 0;
-}
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 314264b77a7101..1d6a92c498b061 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -736,5 +736,44 @@ TEST(ConstantsTest, ComdatUserTracking) {
   EXPECT_TRUE(Users.size() == 0);
 }
 
+// Verify that the C API getters for BlockAddress work
+TEST(ConstantsTest, BlockAddressCAPITest) {
+  const char *BlockAddressIR = R"(
+    define void @test_block_address_func() {
+    entry:
+      br label %block_bb_0
+    block_bb_0:
+      ret void
+    }
+  )";
+
+  LLVMContext Context;
+  SMDiagnostic Error;
+  std::unique_ptr<Module> M =
+      parseAssemblyString(BlockAddressIR, Error, Context);
+
+  EXPECT_TRUE(M.get() != nullptr);
+
+  // Get the function
+  auto *Func = M->getFunction("test_block_address_func");
+  EXPECT_TRUE(Func != nullptr);
+
+  // Get the second basic block, since we can't use the entry one
+  const BasicBlock &BB = *(++Func->begin());
+  EXPECT_EQ(BB.getName(), "block_bb_0");
+
+  // Construct the C API values
+  LLVMValueRef BlockAddr = LLVMBlockAddress(wrap(Func), wrap(&BB));
+  EXPECT_TRUE(LLVMIsABlockAddress(BlockAddr));
+
+  // Get the Function/BasicBlock values back out
+  auto *OutFunc = unwrap(LLVMGetBlockAddressFunction(BlockAddr));
+  auto *OutBB = unwrap(LLVMGetBlockAddressBasicBlock(BlockAddr));
+
+  // Verify that they round-tripped properly
+  EXPECT_EQ(Func, OutFunc);
+  EXPECT_EQ(&BB, OutBB);
+}
+
 } // end anonymous namespace
 } // end namespace llvm



More information about the llvm-commits mailing list