mirror of
https://github.com/LLVMParty/llvm-nanobind
synced 2026-06-21 13:43:38 +00:00
157 lines
5.3 KiB
C++
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;
|
|
}
|