Files
Duncan Ogilvie 0ec7df115c Reformat tests
2025-12-23 18:03:49 +01:00

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;
}