mirror of
https://github.com/LLVMParty/llvm-nanobind
synced 2026-06-21 13:43:38 +00:00
152 lines
4.8 KiB
C++
152 lines
4.8 KiB
C++
/**
|
|
* Test: test_basic_block
|
|
* Tests LLVM BasicBlock creation and manipulation
|
|
*
|
|
* LLVM-C APIs covered:
|
|
* - LLVMAppendBasicBlockInContext()
|
|
* - LLVMGetBasicBlockName()
|
|
* - LLVMGetBasicBlockParent()
|
|
* - LLVMGetEntryBasicBlock()
|
|
* - LLVMCountBasicBlocks()
|
|
* - LLVMGetFirstBasicBlock(), LLVMGetNextBasicBlock(), LLVMGetLastBasicBlock()
|
|
* - LLVMGetFirstInstruction(), LLVMGetLastInstruction()
|
|
* - LLVMGetBasicBlockTerminator()
|
|
* - LLVMMoveBasicBlockBefore(), LLVMMoveBasicBlockAfter()
|
|
* - LLVMCreateBasicBlockInContext()
|
|
* - LLVMDeleteBasicBlock()
|
|
*/
|
|
|
|
#include <cstdio>
|
|
#include <llvm-c/Analysis.h>
|
|
#include <llvm-c/Core.h>
|
|
|
|
int main() {
|
|
LLVMContextRef ctx = LLVMContextCreate();
|
|
LLVMModuleRef mod =
|
|
LLVMModuleCreateWithNameInContext("test_basic_block", ctx);
|
|
|
|
LLVMTypeRef i32 = LLVMInt32TypeInContext(ctx);
|
|
LLVMTypeRef void_ty = LLVMVoidTypeInContext(ctx);
|
|
|
|
// Create a function to hold basic blocks
|
|
LLVMTypeRef func_ty = LLVMFunctionType(void_ty, nullptr, 0, 0);
|
|
LLVMValueRef func = LLVMAddFunction(mod, "test_func", func_ty);
|
|
|
|
// Append basic blocks
|
|
LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(ctx, func, "entry");
|
|
LLVMBasicBlockRef middle = LLVMAppendBasicBlockInContext(ctx, func, "middle");
|
|
LLVMBasicBlockRef exit_bb = LLVMAppendBasicBlockInContext(ctx, func, "exit");
|
|
|
|
// Get block names
|
|
const char *entry_name = LLVMGetBasicBlockName(entry);
|
|
const char *middle_name = LLVMGetBasicBlockName(middle);
|
|
const char *exit_name = LLVMGetBasicBlockName(exit_bb);
|
|
|
|
// Get parent function
|
|
LLVMValueRef entry_parent = LLVMGetBasicBlockParent(entry);
|
|
|
|
// Get entry basic block
|
|
LLVMBasicBlockRef func_entry = LLVMGetEntryBasicBlock(func);
|
|
|
|
// Count basic blocks
|
|
unsigned bb_count = LLVMCountBasicBlocks(func);
|
|
|
|
// Create a builder to add instructions
|
|
LLVMBuilderRef builder = LLVMCreateBuilderInContext(ctx);
|
|
|
|
// Add instructions to entry block
|
|
LLVMPositionBuilderAtEnd(builder, entry);
|
|
LLVMBuildBr(builder, middle);
|
|
|
|
// Add instructions to middle block
|
|
LLVMPositionBuilderAtEnd(builder, middle);
|
|
LLVMBuildBr(builder, exit_bb);
|
|
|
|
// Add instructions to exit block
|
|
LLVMPositionBuilderAtEnd(builder, exit_bb);
|
|
LLVMBuildRetVoid(builder);
|
|
|
|
// Get first/last instructions
|
|
LLVMValueRef entry_first = LLVMGetFirstInstruction(entry);
|
|
LLVMValueRef entry_last = LLVMGetLastInstruction(entry);
|
|
LLVMValueRef exit_terminator = LLVMGetBasicBlockTerminator(exit_bb);
|
|
|
|
// Create unattached block
|
|
LLVMBasicBlockRef unattached =
|
|
LLVMCreateBasicBlockInContext(ctx, "unattached");
|
|
|
|
// Attach unattached block to function
|
|
LLVMAppendExistingBasicBlock(func, unattached);
|
|
LLVMPositionBuilderAtEnd(builder, unattached);
|
|
LLVMBuildUnreachable(builder);
|
|
|
|
// Block count after adding unattached
|
|
unsigned bb_count_after = LLVMCountBasicBlocks(func);
|
|
|
|
// Move blocks around: move unattached before exit
|
|
LLVMMoveBasicBlockBefore(unattached, exit_bb);
|
|
|
|
// Iterate through blocks
|
|
int block_index = 0;
|
|
printf("; Test: test_basic_block\n");
|
|
printf(";\n");
|
|
printf("; Basic block info:\n");
|
|
printf("; entry name: %s\n", entry_name);
|
|
printf("; middle name: %s\n", middle_name);
|
|
printf("; exit name: %s\n", exit_name);
|
|
printf(";\n");
|
|
printf("; Parent checks:\n");
|
|
printf("; entry parent is func: %s\n", entry_parent == func ? "yes" : "no");
|
|
printf("; func entry block is entry: %s\n",
|
|
func_entry == entry ? "yes" : "no");
|
|
printf(";\n");
|
|
printf("; Block counts:\n");
|
|
printf("; initial count: %u\n", bb_count);
|
|
printf("; after adding unattached: %u\n", bb_count_after);
|
|
printf(";\n");
|
|
printf("; Instruction checks:\n");
|
|
printf("; entry has first instruction: %s\n",
|
|
entry_first != nullptr ? "yes" : "no");
|
|
printf("; entry first == last (single inst): %s\n",
|
|
entry_first == entry_last ? "yes" : "no");
|
|
printf("; exit has terminator: %s\n",
|
|
exit_terminator != nullptr ? "yes" : "no");
|
|
printf(";\n");
|
|
printf("; Block iteration (after move):\n");
|
|
for (LLVMBasicBlockRef bb = LLVMGetFirstBasicBlock(func); bb;
|
|
bb = LLVMGetNextBasicBlock(bb)) {
|
|
printf("; [%d] %s\n", block_index++, LLVMGetBasicBlockName(bb));
|
|
}
|
|
|
|
// Get last block
|
|
LLVMBasicBlockRef last_bb = LLVMGetLastBasicBlock(func);
|
|
printf(";\n");
|
|
printf("; Last block: %s\n", LLVMGetBasicBlockName(last_bb));
|
|
|
|
LLVMDisposeBuilder(builder);
|
|
|
|
// Verify module
|
|
char *error = nullptr;
|
|
if (LLVMVerifyModule(mod, LLVMReturnStatusAction, &error)) {
|
|
fprintf(stderr, "; Verification failed: %s\n", error);
|
|
LLVMDisposeMessage(error);
|
|
LLVMDisposeModule(mod);
|
|
LLVMContextDispose(ctx);
|
|
return 1;
|
|
}
|
|
LLVMDisposeMessage(error);
|
|
|
|
printf("\n");
|
|
|
|
// Print module IR
|
|
char *ir = LLVMPrintModuleToString(mod);
|
|
printf("%s", ir);
|
|
LLVMDisposeMessage(ir);
|
|
|
|
// Cleanup
|
|
LLVMDisposeModule(mod);
|
|
LLVMContextDispose(ctx);
|
|
|
|
return 0;
|
|
}
|