mirror of
https://github.com/LLVMParty/llvm-nanobind
synced 2026-06-21 13:43:38 +00:00
146 lines
5.2 KiB
C++
146 lines
5.2 KiB
C++
/**
|
|
* Test: test_builder_arithmetic
|
|
* Tests LLVM Builder arithmetic instruction creation
|
|
*
|
|
* LLVM-C APIs covered:
|
|
* - LLVMCreateBuilderInContext(), LLVMDisposeBuilder()
|
|
* - LLVMPositionBuilderAtEnd()
|
|
* - LLVMBuildAdd(), LLVMBuildNSWAdd(), LLVMBuildNUWAdd()
|
|
* - LLVMBuildSub(), LLVMBuildNSWSub(), LLVMBuildNUWSub()
|
|
* - LLVMBuildMul(), LLVMBuildNSWMul(), LLVMBuildNUWMul()
|
|
* - LLVMBuildSDiv(), LLVMBuildUDiv(), LLVMBuildExactSDiv()
|
|
* - LLVMBuildSRem(), LLVMBuildURem()
|
|
* - LLVMBuildFAdd(), LLVMBuildFSub(), LLVMBuildFMul(), LLVMBuildFDiv(),
|
|
* LLVMBuildFRem()
|
|
* - LLVMBuildShl(), LLVMBuildLShr(), LLVMBuildAShr()
|
|
* - LLVMBuildAnd(), LLVMBuildOr(), LLVMBuildXor()
|
|
* - LLVMBuildNeg(), LLVMBuildNSWNeg(), LLVMBuildFNeg(), LLVMBuildNot()
|
|
*/
|
|
|
|
#include <cstdio>
|
|
#include <llvm-c/Analysis.h>
|
|
#include <llvm-c/Core.h>
|
|
|
|
int main() {
|
|
LLVMContextRef ctx = LLVMContextCreate();
|
|
LLVMModuleRef mod =
|
|
LLVMModuleCreateWithNameInContext("test_builder_arithmetic", ctx);
|
|
|
|
LLVMTypeRef i32 = LLVMInt32TypeInContext(ctx);
|
|
LLVMTypeRef i64 = LLVMInt64TypeInContext(ctx);
|
|
LLVMTypeRef f64 = LLVMDoubleTypeInContext(ctx);
|
|
|
|
// Integer arithmetic function: i32 int_arith(i32, i32)
|
|
LLVMTypeRef int_params[] = {i32, i32};
|
|
LLVMTypeRef int_func_ty = LLVMFunctionType(i32, int_params, 2, 0);
|
|
LLVMValueRef int_func = LLVMAddFunction(mod, "int_arith", int_func_ty);
|
|
|
|
LLVMValueRef a = LLVMGetParam(int_func, 0);
|
|
LLVMValueRef b = LLVMGetParam(int_func, 1);
|
|
LLVMSetValueName2(a, "a", 1);
|
|
LLVMSetValueName2(b, "b", 1);
|
|
|
|
LLVMBasicBlockRef int_entry =
|
|
LLVMAppendBasicBlockInContext(ctx, int_func, "entry");
|
|
LLVMBuilderRef builder = LLVMCreateBuilderInContext(ctx);
|
|
LLVMPositionBuilderAtEnd(builder, int_entry);
|
|
|
|
// Basic arithmetic
|
|
LLVMValueRef add = LLVMBuildAdd(builder, a, b, "add");
|
|
LLVMValueRef sub = LLVMBuildSub(builder, a, b, "sub");
|
|
LLVMValueRef mul = LLVMBuildMul(builder, a, b, "mul");
|
|
LLVMValueRef sdiv = LLVMBuildSDiv(builder, a, b, "sdiv");
|
|
LLVMValueRef udiv = LLVMBuildUDiv(builder, a, b, "udiv");
|
|
LLVMValueRef srem = LLVMBuildSRem(builder, a, b, "srem");
|
|
LLVMValueRef urem = LLVMBuildURem(builder, a, b, "urem");
|
|
|
|
// With overflow flags
|
|
LLVMValueRef nsw_add = LLVMBuildNSWAdd(builder, a, b, "nsw_add");
|
|
LLVMValueRef nuw_add = LLVMBuildNUWAdd(builder, a, b, "nuw_add");
|
|
LLVMValueRef nsw_sub = LLVMBuildNSWSub(builder, a, b, "nsw_sub");
|
|
LLVMValueRef nuw_sub = LLVMBuildNUWSub(builder, a, b, "nuw_sub");
|
|
LLVMValueRef nsw_mul = LLVMBuildNSWMul(builder, a, b, "nsw_mul");
|
|
LLVMValueRef nuw_mul = LLVMBuildNUWMul(builder, a, b, "nuw_mul");
|
|
LLVMValueRef exact_sdiv = LLVMBuildExactSDiv(builder, a, b, "exact_sdiv");
|
|
|
|
// Bitwise operations
|
|
LLVMValueRef and_op = LLVMBuildAnd(builder, a, b, "and");
|
|
LLVMValueRef or_op = LLVMBuildOr(builder, a, b, "or");
|
|
LLVMValueRef xor_op = LLVMBuildXor(builder, a, b, "xor");
|
|
|
|
// Shift operations
|
|
LLVMValueRef shl = LLVMBuildShl(builder, a, b, "shl");
|
|
LLVMValueRef lshr = LLVMBuildLShr(builder, a, b, "lshr");
|
|
LLVMValueRef ashr = LLVMBuildAShr(builder, a, b, "ashr");
|
|
|
|
// Unary operations
|
|
LLVMValueRef neg = LLVMBuildNeg(builder, a, "neg");
|
|
LLVMValueRef nsw_neg = LLVMBuildNSWNeg(builder, a, "nsw_neg");
|
|
LLVMValueRef not_op = LLVMBuildNot(builder, a, "not");
|
|
|
|
// Return something to make function complete
|
|
LLVMBuildRet(builder, add);
|
|
|
|
// Floating point arithmetic function: f64 float_arith(f64, f64)
|
|
LLVMTypeRef fp_params[] = {f64, f64};
|
|
LLVMTypeRef fp_func_ty = LLVMFunctionType(f64, fp_params, 2, 0);
|
|
LLVMValueRef fp_func = LLVMAddFunction(mod, "float_arith", fp_func_ty);
|
|
|
|
LLVMValueRef x = LLVMGetParam(fp_func, 0);
|
|
LLVMValueRef y = LLVMGetParam(fp_func, 1);
|
|
LLVMSetValueName2(x, "x", 1);
|
|
LLVMSetValueName2(y, "y", 1);
|
|
|
|
LLVMBasicBlockRef fp_entry =
|
|
LLVMAppendBasicBlockInContext(ctx, fp_func, "entry");
|
|
LLVMPositionBuilderAtEnd(builder, fp_entry);
|
|
|
|
// Floating point operations
|
|
LLVMValueRef fadd = LLVMBuildFAdd(builder, x, y, "fadd");
|
|
LLVMValueRef fsub = LLVMBuildFSub(builder, x, y, "fsub");
|
|
LLVMValueRef fmul = LLVMBuildFMul(builder, x, y, "fmul");
|
|
LLVMValueRef fdiv = LLVMBuildFDiv(builder, x, y, "fdiv");
|
|
LLVMValueRef frem = LLVMBuildFRem(builder, x, y, "frem");
|
|
LLVMValueRef fneg = LLVMBuildFNeg(builder, x, "fneg");
|
|
|
|
LLVMBuildRet(builder, fadd);
|
|
|
|
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_arithmetic\n");
|
|
printf(";\n");
|
|
printf("; Integer operations demonstrated:\n");
|
|
printf("; add, sub, mul, sdiv, udiv, srem, urem\n");
|
|
printf(
|
|
"; nsw_add, nuw_add, nsw_sub, nuw_sub, nsw_mul, nuw_mul, exact_sdiv\n");
|
|
printf("; and, or, xor, shl, lshr, ashr\n");
|
|
printf("; neg, nsw_neg, not\n");
|
|
printf(";\n");
|
|
printf("; Floating point operations demonstrated:\n");
|
|
printf("; fadd, fsub, fmul, fdiv, frem, fneg\n");
|
|
printf("\n");
|
|
|
|
// Print module IR
|
|
char *ir = LLVMPrintModuleToString(mod);
|
|
printf("%s", ir);
|
|
LLVMDisposeMessage(ir);
|
|
|
|
// Cleanup
|
|
LLVMDisposeModule(mod);
|
|
LLVMContextDispose(ctx);
|
|
|
|
return 0;
|
|
}
|