Skip to content
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

[C API] Add blockaddress getters to C API #81382

Merged
merged 2 commits into from
Feb 12, 2024

Conversation

Benjins
Copy link
Contributor

@Benjins Benjins commented Feb 10, 2024

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

Due to the difficulties of fully supporting 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

This previously was up for review at #77390 . The API changes are the same, but the way of testing it has been changed. Since a full-on cloning of BlockAddress values was considered too difficult, the test instead just verifies that we can access the data as expected using a new function in llvm-c-test

@llvmbot
Copy link
Collaborator

llvmbot commented Feb 10, 2024

@llvm/pr-subscribers-llvm-ir

Author: Benji Smith (Benjins)

Changes

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

Due to the difficulties of fully supporting 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

This previously was up for review at #77390 . The API changes are the same, but the way of testing it has been changed. Since a full-on cloning of BlockAddress values was considered too difficult, the test instead just verifies that we can access the data as expected using a new function in llvm-c-test


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

7 Files Affected:

  • (modified) llvm/docs/ReleaseNotes.rst (+3)
  • (modified) llvm/include/llvm-c/Core.h (+10)
  • (modified) llvm/lib/IR/Core.cpp (+8)
  • (added) llvm/test/Bindings/llvm-c/block_address.ll (+39)
  • (modified) llvm/tools/llvm-c-test/llvm-c-test.h (+1)
  • (modified) llvm/tools/llvm-c-test/main.c (+3)
  • (modified) llvm/tools/llvm-c-test/module.c (+28)
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
+}
+
+
+@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'
+
+@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'
+
+@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'
+
+@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;
+}

Copy link

⚠️ We detected that you are using a GitHub private e-mail address to contribute to the repo.
Please turn off Keep my email addresses private setting in your account.
See LLVM Discourse for more information.

…ters

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
LLVMDisposeModule(M);

return 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't have to go through llvm-c-test with IR input, you can also directly add a unit test in https://github.com/llvm/llvm-project/blob/main/llvm/unittests/IR/ConstantsTest.cpp. Basically just call LLVMBlockAddress and then the getter on that and check that the inputs & outputs are the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Apologies, I didn't realise there was a specific unit test framework. I've changed the test to that in a new commit

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

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

LGTM

@nikic nikic merged commit b726a81 into llvm:main Feb 12, 2024
4 of 5 checks passed
@Benjins Benjins deleted the bns-block-address-c-api-v2 branch February 12, 2024 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants