Files
LLVMParty-llvm-nanobind/tests/test_builder_memory.cpp
T
Duncan Ogilvie 0ec7df115c Reformat tests
2025-12-23 18:03:49 +01:00

157 lines
5.3 KiB
C++

/**
* Test: test_builder_memory
* Tests LLVM Builder memory operations
*
* LLVM-C APIs covered:
* - LLVMBuildAlloca(), LLVMBuildArrayAlloca()
* - LLVMBuildLoad2(), LLVMBuildStore()
* - LLVMBuildGEP2(), LLVMBuildInBoundsGEP2(), LLVMBuildStructGEP2()
* - LLVMGetVolatile(), LLVMSetVolatile()
* - LLVMGetAlignment(), LLVMSetAlignment()
*/
#include <cstdio>
#include <llvm-c/Analysis.h>
#include <llvm-c/Core.h>
int main() {
LLVMContextRef ctx = LLVMContextCreate();
LLVMModuleRef mod =
LLVMModuleCreateWithNameInContext("test_builder_memory", ctx);
LLVMTypeRef i32 = LLVMInt32TypeInContext(ctx);
LLVMTypeRef i64 = LLVMInt64TypeInContext(ctx);
LLVMTypeRef ptr = LLVMPointerTypeInContext(ctx, 0);
LLVMTypeRef void_ty = LLVMVoidTypeInContext(ctx);
// Array type for array alloca test
LLVMTypeRef arr_ty = LLVMArrayType2(i32, 10);
// Struct type for struct GEP test
LLVMTypeRef struct_elems[] = {i32, i64, i32};
LLVMTypeRef struct_ty = LLVMStructTypeInContext(ctx, struct_elems, 3, 0);
// Function: void memory_ops()
LLVMTypeRef func_ty = LLVMFunctionType(void_ty, nullptr, 0, 0);
LLVMValueRef func = LLVMAddFunction(mod, "memory_ops", func_ty);
LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(ctx, func, "entry");
LLVMBuilderRef builder = LLVMCreateBuilderInContext(ctx);
LLVMPositionBuilderAtEnd(builder, entry);
// Basic alloca
LLVMValueRef alloca_i32 = LLVMBuildAlloca(builder, i32, "local_i32");
// Alloca with explicit alignment
LLVMValueRef alloca_aligned = LLVMBuildAlloca(builder, i64, "local_aligned");
LLVMSetAlignment(alloca_aligned, 16);
// Array alloca (dynamic size)
LLVMValueRef array_size = LLVMConstInt(i32, 5, 0);
LLVMValueRef array_alloca =
LLVMBuildArrayAlloca(builder, i32, array_size, "dynamic_array");
// Static array alloca
LLVMValueRef static_array = LLVMBuildAlloca(builder, arr_ty, "static_array");
// Struct alloca
LLVMValueRef struct_alloca =
LLVMBuildAlloca(builder, struct_ty, "local_struct");
// Store and load
LLVMValueRef val = LLVMConstInt(i32, 42, 0);
LLVMValueRef store = LLVMBuildStore(builder, val, alloca_i32);
LLVMValueRef load = LLVMBuildLoad2(builder, i32, alloca_i32, "loaded");
// Volatile load/store
LLVMValueRef volatile_store = LLVMBuildStore(builder, val, alloca_i32);
LLVMSetVolatile(volatile_store, 1);
LLVMValueRef volatile_load =
LLVMBuildLoad2(builder, i32, alloca_i32, "volatile_loaded");
LLVMSetVolatile(volatile_load, 1);
// Load with alignment
LLVMValueRef aligned_load =
LLVMBuildLoad2(builder, i64, alloca_aligned, "aligned_loaded");
LLVMSetAlignment(aligned_load, 16);
// GEP into array (static)
LLVMValueRef indices[] = {LLVMConstInt(i64, 0, 0), LLVMConstInt(i64, 3, 0)};
LLVMValueRef gep =
LLVMBuildGEP2(builder, arr_ty, static_array, indices, 2, "arr_elem");
// Inbounds GEP
LLVMValueRef inbounds_gep = LLVMBuildInBoundsGEP2(
builder, arr_ty, static_array, indices, 2, "arr_elem_inbounds");
// Struct GEP
LLVMValueRef struct_gep_0 =
LLVMBuildStructGEP2(builder, struct_ty, struct_alloca, 0, "field_0");
LLVMValueRef struct_gep_1 =
LLVMBuildStructGEP2(builder, struct_ty, struct_alloca, 1, "field_1");
LLVMValueRef struct_gep_2 =
LLVMBuildStructGEP2(builder, struct_ty, struct_alloca, 2, "field_2");
// Store to struct fields
LLVMBuildStore(builder, LLVMConstInt(i32, 100, 0), struct_gep_0);
LLVMBuildStore(builder, LLVMConstInt(i64, 200, 0), struct_gep_1);
LLVMBuildStore(builder, LLVMConstInt(i32, 300, 0), struct_gep_2);
// Load from struct fields
LLVMValueRef field_0_val =
LLVMBuildLoad2(builder, i32, struct_gep_0, "field_0_val");
LLVMValueRef field_1_val =
LLVMBuildLoad2(builder, i64, struct_gep_1, "field_1_val");
LLVMBuildRetVoid(builder);
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);
// Print diagnostic comments
printf("; Test: test_builder_memory\n");
printf(";\n");
printf("; Memory operations demonstrated:\n");
printf("; alloca (i32, i64 with alignment, dynamic array, static array, "
"struct)\n");
printf("; store (basic, volatile)\n");
printf("; load (basic, volatile, aligned)\n");
printf("; GEP (array indexing, inbounds)\n");
printf("; struct GEP (field access)\n");
printf(";\n");
printf("; Alignment checks:\n");
printf("; alloca_aligned alignment: %u\n",
LLVMGetAlignment(alloca_aligned));
printf("; aligned_load alignment: %u\n", LLVMGetAlignment(aligned_load));
printf(";\n");
printf("; Volatile checks:\n");
printf("; volatile_store is volatile: %s\n",
LLVMGetVolatile(volatile_store) ? "yes" : "no");
printf("; volatile_load is volatile: %s\n",
LLVMGetVolatile(volatile_load) ? "yes" : "no");
printf("; regular store is volatile: %s\n",
LLVMGetVolatile(store) ? "yes" : "no");
printf("\n");
// Print module IR
char *ir = LLVMPrintModuleToString(mod);
printf("%s", ir);
LLVMDisposeMessage(ir);
// Cleanup
LLVMDisposeModule(mod);
LLVMContextDispose(ctx);
return 0;
}