static LLVMValueRef CreateFibFunction(LLVMModuleRef M, LLVMContextRef Context) { LLVMBuilderRef B = LLVMCreateBuilderInContext(Context); // Create the fib function and insert it into module M. This function is said // to return an int and take an int parameter. LLVMTypeRef ParamTypes[] = {LLVMInt32TypeInContext(Context)}; LLVMTypeRef ReturnType = LLVMInt32TypeInContext(Context); LLVMTypeRef FunctionTy = LLVMFunctionType(ReturnType, ParamTypes, 1, 0); LLVMValueRef FibF = LLVMAddFunction(M, "fib", FunctionTy); // Add a basic block to the function. LLVMBasicBlockRef BB = LLVMAppendBasicBlockInContext(Context, FibF, "EntryBlock"); // Get pointers to the constants. LLVMValueRef One = LLVMConstInt(LLVMInt32TypeInContext(Context), 1, 0); LLVMValueRef Two = LLVMConstInt(LLVMInt32TypeInContext(Context), 2, 0); // Get pointer to the integer argument of the add1 function... LLVMValueRef ArgX = LLVMGetFirstParam(FibF); // Get the arg. LLVMSetValueName(ArgX, "AnArg"); // Give it a nice symbolic name for fun. // Create the true_block. LLVMBasicBlockRef RetBB = LLVMAppendBasicBlockInContext(Context, FibF, "return"); // Create an exit block. LLVMBasicBlockRef RecurseBB = LLVMAppendBasicBlockInContext(Context, FibF, "recurse"); // Create the "if (arg <= 2) goto exitbb" LLVMPositionBuilderAtEnd(B, BB); LLVMValueRef CondInst = LLVMBuildICmp(B, LLVMIntSLE, ArgX, Two, "cond"); LLVMBuildCondBr(B, CondInst, RetBB, RecurseBB); // Create: ret int 1 LLVMPositionBuilderAtEnd(B, RetBB); LLVMBuildRet(B, One); // create fib(x-1) LLVMPositionBuilderAtEnd(B, RecurseBB); LLVMValueRef Sub = LLVMBuildSub(B, ArgX, One, "arg"); LLVMValueRef CallFibX1 = LLVMBuildCall(B, FibF, &Sub, 1, "fibx1"); LLVMSetTailCall(CallFibX1, 1); // create fib(x-2) LLVMPositionBuilderAtEnd(B, RecurseBB); Sub = LLVMBuildSub(B, ArgX, Two, "arg"); LLVMValueRef CallFibX2 = LLVMBuildCall(B, FibF, &Sub, 1, "fibx2"); LLVMSetTailCall(CallFibX2, 1); // fib(x-1)+fib(x-2) LLVMPositionBuilderAtEnd(B, RecurseBB); LLVMValueRef Sum = LLVMBuildAdd(B, CallFibX1, CallFibX2, "addresult"); // Create the return instruction and add it to the basic block LLVMPositionBuilderAtEnd(B, RecurseBB); LLVMBuildRet(B, Sum); return FibF; }
int main() { LLVMContextRef context = LLVMGetGlobalContext(); LLVMModuleRef module = LLVMModuleCreateWithName("test-101"); LLVMBuilderRef builder = LLVMCreateBuilder(); // LLVMInt32Type() // LLVMFunctionType(rtnType, paramType, parmCnt, isVarArg) // LLVMAddFunction(module, name, functionType) LLVMTypeRef main = LLVMFunctionType(LLVMInt32Type(), NULL, 0, 0); LLVMValueRef mainFn = LLVMAddFunction(module, "main", main); LLVMBasicBlockRef mainBlk = LLVMAppendBasicBlock(mainFn, "entry"); LLVMPositionBuilderAtEnd(builder, mainBlk); LLVMValueRef str = LLVMBuildGlobalStringPtr(builder, "Hello World!", "str"); LLVMTypeRef args[1]; args[0] = LLVMPointerType(LLVMInt8Type(), 0); LLVMTypeRef puts = LLVMFunctionType(LLVMInt32Type(), args, 1, 0); LLVMValueRef putsFn = LLVMAddFunction(module, "puts", puts); LLVMBuildCall(builder, putsFn, &str, 1, ""); LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 0, 0)); LLVMDumpModule(module); return 0; }
static void donotoptimise_apply(compile_t* c, reach_type_t* t, reach_method_t* m) { const char* strtab_name = m->name; m->intrinsic = true; ast_t* typearg = ast_child(m->typeargs); reach_type_t* t_elem = reach_type(c->reach, typearg); LLVMTypeRef params[2]; params[0] = t->use_type; params[1] = t_elem->use_type; start_function(c, m, m->result->use_type, params, 2); LLVMValueRef obj = LLVMGetParam(m->func, 1); LLVMTypeRef void_fn = LLVMFunctionType(c->void_type, &t_elem->use_type, 1, false); LLVMValueRef asmstr = LLVMConstInlineAsm(void_fn, "", "imr,~{memory}", true, false); LLVMBuildCall(c->builder, asmstr, &obj, 1, ""); LLVMBuildRet(c->builder, m->result->instance); codegen_finishfun(c); BOX_FUNCTION(); }
LLVMValueRef JITImpl:: emitCallToBeInlined(LLVMValueRef fn, LLVMValueRef *args, unsigned numArgs) { LLVMValueRef call = LLVMBuildCall(builder, fn, args, numArgs, ""); calls.push_back(call); return call; }
/** * Generates LLVM IR to call debug_printf. */ static LLVMValueRef lp_build_print_args(struct gallivm_state* gallivm, int argcount, LLVMValueRef* args) { LLVMBuilderRef builder = gallivm->builder; LLVMContextRef context = gallivm->context; LLVMValueRef func_printf; LLVMTypeRef printf_type; int i; assert(args); assert(argcount > 0); assert(LLVMTypeOf(args[0]) == LLVMPointerType(LLVMInt8TypeInContext(context), 0)); /* Cast any float arguments to doubles as printf expects */ for (i = 1; i < argcount; i++) { LLVMTypeRef type = LLVMTypeOf(args[i]); if (LLVMGetTypeKind(type) == LLVMFloatTypeKind) args[i] = LLVMBuildFPExt(builder, args[i], LLVMDoubleTypeInContext(context), ""); } printf_type = LLVMFunctionType(LLVMInt32TypeInContext(context), NULL, 0, 1); func_printf = lp_build_const_int_pointer(gallivm, func_to_pointer((func_pointer)debug_printf)); func_printf = LLVMBuildBitCast(builder, func_printf, LLVMPointerType(printf_type, 0), "debug_printf"); return LLVMBuildCall(builder, func_printf, args, argcount, ""); }
static void make_rdtscp(compile_t* c) { if(target_is_x86(c->opt->triple)) { // i64 @llvm.x86.rdtscp(i8*) LLVMTypeRef f_type = LLVMFunctionType(c->i64, &c->void_ptr, 1, false); LLVMValueRef rdtscp = LLVMAddFunction(c->module, "llvm.x86.rdtscp", f_type); // i64 @internal.x86.rdtscp(i32*) LLVMTypeRef i32_ptr = LLVMPointerType(c->i32, 0); f_type = LLVMFunctionType(c->i64, &i32_ptr, 1, false); LLVMValueRef fun = codegen_addfun(c, "internal.x86.rdtscp", f_type); LLVMSetFunctionCallConv(fun, LLVMCCallConv); codegen_startfun(c, fun, NULL, NULL); // Cast i32* to i8* and call the intrinsic. LLVMValueRef arg = LLVMGetParam(fun, 0); arg = LLVMBuildBitCast(c->builder, arg, c->void_ptr, ""); LLVMValueRef result = LLVMBuildCall(c->builder, rdtscp, &arg, 1, ""); LLVMBuildRet(c->builder, result); codegen_finishfun(c); } else { (void)c; } }
LLVMValueRef codegen_call(compile_t* c, LLVMValueRef fun, LLVMValueRef* args, size_t count) { LLVMValueRef result = LLVMBuildCall(c->builder, fun, args, (int)count, ""); LLVMSetInstructionCallConv(result, c->callconv); return result; }
JITFunctionInfo *JITImpl:: getJITFunctionOrStubImpl(JITCoreInfo &coreInfo, uint32_t pc) { JITFunctionInfo *&info = coreInfo.functionMap[pc]; if (info) return info; LLVMBasicBlockRef savedInsertPoint = LLVMGetInsertBlock(builder); LLVMValueRef f = LLVMAddFunction(module, "", jitFunctionType); LLVMSetFunctionCallConv(f, LLVMFastCallConv); LLVMBasicBlockRef entryBB = LLVMAppendBasicBlock(f, "entry"); LLVMPositionBuilderAtEnd(builder, entryBB); LLVMValueRef args[] = { LLVMGetParam(f, 0) }; LLVMValueRef call = LLVMBuildCall(builder, functions.jitStubImpl, args, 1, ""); LLVMBuildRet(builder, call); if (DEBUG_JIT) { LLVMDumpValue(f); LLVMVerifyFunction(f, LLVMAbortProcessAction); } JITInstructionFunction_t code = reinterpret_cast<JITInstructionFunction_t>( LLVMGetPointerToGlobal(executionEngine, f)); info = new JITFunctionInfo(pc, f, code, true); LLVMPositionBuilderAtEnd(builder, savedInsertPoint); return info; }
static bool trace_fields(compile_t* c, gentype_t* g, LLVMValueRef ctx, LLVMValueRef object, int extra) { bool need_trace = false; for(int i = 0; i < g->field_count; i++) { LLVMValueRef field = LLVMBuildStructGEP(c->builder, object, i + extra, ""); if(g->field_keys[i] != TK_EMBED) { // Call the trace function indirectly depending on rcaps. LLVMValueRef value = LLVMBuildLoad(c->builder, field, ""); need_trace |= gentrace(c, ctx, value, g->fields[i]); } else { // Call the trace function directly without marking the field. const char* fun = genname_trace(genname_type(g->fields[i])); LLVMValueRef trace_fn = LLVMGetNamedFunction(c->module, fun); if(trace_fn != NULL) { LLVMValueRef args[2]; args[0] = ctx; args[1] = LLVMBuildBitCast(c->builder, field, c->object_ptr, ""); LLVMBuildCall(c->builder, trace_fn, args, 2, ""); need_trace = true; } } } return need_trace; }
LLVMValueRef gencall_runtime(compile_t* c, const char *name, LLVMValueRef* args, int count, const char* ret) { LLVMValueRef func = LLVMGetNamedFunction(c->module, name); pony_assert(func != NULL); return LLVMBuildCall(c->builder, func, args, count, ret); }
LLVMValueRef build_utcb_get(struct llvm_ctx *ctx) { LLVMTypeRef fntype = LLVMFunctionType(ctx->wordt, NULL, 0, 0); LLVMValueRef func = LLVMConstInlineAsm(fntype, "movl %gs:0,$0\n", "=r,~{dirflag},~{fpsr},~{flags}", 0, 0); LLVMValueRef call = LLVMBuildCall(ctx->builder, func, NULL, 0, "utcbget"); LLVMSetTailCall(call, 1); return LLVMBuildIntToPtr(ctx->builder, call, LLVMPointerType(ctx->wordt, 0), "utcb.wordp"); }
/* call a function to decode the structure. */ void decode_packed_struct_fncall( struct llvm_ctx *ctx, LLVMValueRef dstptr, IDL_tree ctyp, LLVMValueRef first_mr, LLVMValueRef bit_offset) { V decode_fn = get_struct_decoder_fn(ctx, ctyp); const struct packed_format *fmt = packed_format_of(ctyp); assert(fmt != NULL); if(fmt->num_bits < BITS_PER_WORD) { /* decoder function does have a bit-offset parameter. */ V parms[3] = { dstptr, first_mr, bit_offset }; LLVMBuildCall(ctx->builder, decode_fn, parms, 3, ""); } else { V parms[2] = { dstptr, first_mr }; LLVMBuildCall(ctx->builder, decode_fn, parms, 2, ""); } }
LLVMValueRef codegen_call(compile_t* c, LLVMValueRef fun, LLVMValueRef* args, size_t count) { LLVMValueRef result = LLVMBuildCall(c->builder, fun, args, (int)count, ""); if(!c->opt->library) LLVMSetInstructionCallConv(result, GEN_CALLCONV); return result; }
void gencall_lifetime_end(compile_t* c, LLVMValueRef ptr) { LLVMValueRef func = LLVMLifetimeEnd(c->module); LLVMTypeRef type = LLVMGetElementType(LLVMTypeOf(ptr)); size_t size = (size_t)LLVMABISizeOfType(c->target_data, type); LLVMValueRef args[2]; args[0] = LLVMConstInt(c->i64, size, false); args[1] = LLVMBuildBitCast(c->builder, ptr, c->void_ptr, ""); LLVMBuildCall(c->builder, func, args, 2, ""); }
void gencall_throw(compile_t* c) { LLVMValueRef func = LLVMGetNamedFunction(c->module, "pony_throw"); if(c->frame->invoke_target != NULL) invoke_fun(c, func, NULL, 0, "", false); else LLVMBuildCall(c->builder, func, NULL, 0, ""); LLVMBuildUnreachable(c->builder); }
void JITImpl:: emitJumpToNextFragment(JITCoreInfo &coreInfo, uint32_t targetPc, JITFunctionInfo *caller) { LLVMValueRef next = getJITFunctionOrStub(coreInfo, targetPc, caller); LLVMValueRef args[] = { threadParam }; LLVMValueRef call = LLVMBuildCall(builder, next, args, 1, ""); LLVMSetTailCall(call, true); LLVMSetInstructionCallConv(call, LLVMFastCallConv); LLVMBuildRet(builder, call); }
LLVMValueRef gencall_runtime(compile_t* c, const char *name, LLVMValueRef* args, int count, const char* ret) { // Disable debug anchor dwarf_location(&c->dwarf, NULL); LLVMValueRef func = LLVMGetNamedFunction(c->module, name); if(func == NULL) return NULL; return LLVMBuildCall(c->builder, func, args, count, ret); }
void gencall_memmove(compile_t* c, LLVMValueRef dst, LLVMValueRef src, LLVMValueRef n) { LLVMValueRef func = LLVMMemmove(c->module, target_is_ilp32(c->opt->triple)); LLVMValueRef args[5]; args[0] = dst; args[1] = src; args[2] = n; args[3] = LLVMConstInt(c->i32, 1, false); args[4] = LLVMConstInt(c->i1, 0, false); LLVMBuildCall(c->builder, func, args, 5, ""); }
LLVMValueRef lp_build_intrinsic(LLVMBuilderRef builder, const char *name, LLVMTypeRef ret_type, LLVMValueRef *args, unsigned num_args, unsigned attr_mask) { LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder))); LLVMValueRef function, call; bool set_callsite_attrs = HAVE_LLVM >= 0x0400 && !(attr_mask & LP_FUNC_ATTR_LEGACY); function = LLVMGetNamedFunction(module, name); if(!function) { LLVMTypeRef arg_types[LP_MAX_FUNC_ARGS]; unsigned i; assert(num_args <= LP_MAX_FUNC_ARGS); for(i = 0; i < num_args; ++i) { assert(args[i]); arg_types[i] = LLVMTypeOf(args[i]); } function = lp_declare_intrinsic(module, name, ret_type, arg_types, num_args); /* * If llvm removes an intrinsic we use, we'll hit this abort (rather * than a call to address zero in the jited code). */ if (LLVMGetIntrinsicID(function) == 0) { _debug_printf("llvm (version 0x%x) found no intrinsic for %s, going to crash...\n", HAVE_LLVM, name); abort(); } if (!set_callsite_attrs) lp_add_func_attributes(function, attr_mask); if (gallivm_debug & GALLIVM_DEBUG_IR) { lp_debug_dump_value(function); } } call = LLVMBuildCall(builder, function, args, num_args, ""); if (set_callsite_attrs) lp_add_func_attributes(call, attr_mask); return call; }
LLVMValueRef build_recv_stritem_len( struct llvm_ctx *ctx, LLVMValueRef *nullpos_p, LLVMValueRef tpos) { LLVMValueRef args[2] = { ctx->utcb, tpos }; LLVMValueRef agg = LLVMBuildCall(ctx->builder, get_stritem_len_fn(ctx), args, 2, "stritemlen.rval"); LLVMSetTailCall(agg, 1); *nullpos_p = LLVMBuildExtractValue(ctx->builder, agg, 0, "stritemlen.rval.len"); return LLVMBuildExtractValue(ctx->builder, agg, 1, "stritemlen.rval.new.tpos"); }
LLVMValueRef encode_packed_struct_fncall( struct llvm_ctx *ctx, LLVMValueRef first_mr_word, LLVMValueRef bit_offset, IDL_tree ctyp, LLVMValueRef src_base) { V fn = get_struct_encoder_fn(ctx, ctyp); const struct packed_format *fmt = packed_format_of(ctyp); assert(fmt != NULL); if(fmt->num_bits < BITS_PER_WORD) { /* subword structure; pass bit offset & value. */ if(bit_offset == NULL) bit_offset = CONST_INT(0); /* NOTE: (word) const void *, word, i32 */ V parms[3] = { src_base, first_mr_word, bit_offset }; return LLVMBuildCall(ctx->builder, fn, parms, 3, "wordval.next"); } else { assert(bit_offset == NULL); /* NOTE: (void) const void *, i32 */ V parms[2] = { src_base, first_mr_word }; LLVMBuildCall(ctx->builder, fn, parms, 2, ""); return NULL; } }
static LLVMValueRef translateStringBinOp(NodeKind Op, LLVMValueRef ValueE1, LLVMValueRef ValueE2) { LLVMValueRef StrCmpFn = LLVMGetNamedFunction(Module, "strcmp"); LLVMValueRef CmpArgs[] = { ValueE1, ValueE2 }, CallStrCmp = LLVMBuildCall(Builder, StrCmpFn, CmpArgs, 2, ""), ZeroConst = LLVMConstInt(LLVMInt32Type(), 0, 1); switch (Op) { case LtOp: return LLVMBuildICmp(Builder, LLVMIntSLT, CallStrCmp, ZeroConst, ""); case LeOp: return LLVMBuildICmp(Builder, LLVMIntSLE, CallStrCmp, ZeroConst, ""); case GtOp: return LLVMBuildICmp(Builder, LLVMIntSGT, CallStrCmp, ZeroConst, ""); case GeOp: return LLVMBuildICmp(Builder, LLVMIntSGE, CallStrCmp, ZeroConst, ""); case EqOp: return LLVMBuildICmp(Builder, LLVMIntEQ, CallStrCmp, ZeroConst, ""); case DiffOp: return LLVMBuildICmp(Builder, LLVMIntNE, CallStrCmp, ZeroConst, ""); default: return NULL; } }
static void donotoptimise_observe(compile_t* c, reach_type_t* t) { FIND_METHOD("observe"); start_function(c, m, m->result->use_type, &t->use_type, 1); LLVMTypeRef void_fn = LLVMFunctionType(c->void_type, NULL, 0, false); LLVMValueRef asmstr = LLVMConstInlineAsm(void_fn, "", "~{memory}", true, false); LLVMBuildCall(c->builder, asmstr, NULL, 0, ""); LLVMBuildRet(c->builder, m->result->instance); codegen_finishfun(c); BOX_FUNCTION(); }
LLVMValueRef build_l4_ipc_call( struct llvm_ctx *ctx, LLVMValueRef arg_to, LLVMValueRef arg_timeouts, LLVMValueRef arg_fromspec, LLVMValueRef arg_mr0, LLVMValueRef *from_p, LLVMValueRef *mr1_p, LLVMValueRef *mr2_p) { LLVMTypeRef params[5]; for(int i=0; i<5; i++) params[i] = ctx->wordt; LLVMTypeRef ipc_result_type = LLVMStructTypeInContext(ctx->ctx, params, 4, 0); LLVMTypeRef ipc_type = LLVMFunctionType(ipc_result_type, params, 5, 0); LLVMValueRef fn = LLVMConstInlineAsm(ipc_type, /* NOTE: this compensates against LLVM 3.3's inability to save %ebp * over an asm statement. clearly a bug, but w/e. * * it's been around since at least LLVM 3.2. */ " pushl %ebp\n" "\tcall __L4_Ipc\n" "\tmovl %ebp, %ecx\n" "\tpopl %ebp\n", "={ax},={si},={bx},={cx},{ax},{cx},{dx},{si},{di},~{dirflag},~{fpsr},~{flags}", 1, 0); LLVMValueRef args[5] = { arg_to, arg_timeouts, arg_fromspec, arg_mr0, LLVMBuildPtrToInt(ctx->builder, ctx->utcb, ctx->wordt, "l4ipc.utcb"), }; LLVMValueRef result = LLVMBuildCall(ctx->builder, fn, args, 5, "l4ipc"); LLVMSetTailCall(result, 1); if(from_p != NULL) { *from_p = LLVMBuildExtractValue(ctx->builder, result, 0, "from"); } if(mr1_p != NULL) { *mr1_p = LLVMBuildExtractValue(ctx->builder, result, 2, "mr1"); } if(mr2_p != NULL) { *mr2_p = LLVMBuildExtractValue(ctx->builder, result, 3, "mr2"); } return LLVMBuildExtractValue(ctx->builder, result, 1, "mr0"); }
/** * lp_build_assert. * * Build an assertion in LLVM IR by building a function call to the * lp_assert() function above. * * \param condition should be an 'i1' or 'i32' value * \param msg a string to print if the assertion fails. */ LLVMValueRef lp_build_assert(LLVMBuilderRef builder, LLVMValueRef condition, const char *msg) { LLVMModuleRef module; LLVMTypeRef arg_types[2]; LLVMValueRef msg_string, assert_func, params[2], r; module = LLVMGetGlobalParent(LLVMGetBasicBlockParent( LLVMGetInsertBlock(builder))); msg_string = lp_build_const_string_variable(module, msg, strlen(msg) + 1); arg_types[0] = LLVMInt32Type(); arg_types[1] = LLVMPointerType(LLVMInt8Type(), 0); /* lookup the lp_assert function */ assert_func = LLVMGetNamedFunction(module, "lp_assert"); /* Create the assertion function if not found */ if (!assert_func) { LLVMTypeRef func_type = LLVMFunctionType(LLVMVoidType(), arg_types, 2, 0); assert_func = LLVMAddFunction(module, "lp_assert", func_type); LLVMSetFunctionCallConv(assert_func, LLVMCCallConv); LLVMSetLinkage(assert_func, LLVMExternalLinkage); LLVMAddGlobalMapping(lp_build_engine, assert_func, func_to_pointer((func_pointer)lp_assert)); } assert(assert_func); /* build function call param list */ params[0] = LLVMBuildZExt(builder, condition, arg_types[0], ""); params[1] = LLVMBuildBitCast(builder, msg_string, arg_types[1], ""); /* check arg types */ assert(LLVMTypeOf(params[0]) == arg_types[0]); assert(LLVMTypeOf(params[1]) == arg_types[1]); r = LLVMBuildCall(builder, assert_func, params, 2, ""); return r; }
static bool trace_tuple(compile_t* c, LLVMValueRef ctx, LLVMValueRef value, ast_t* type) { // Invoke the trace function directly. Do not trace the address of the tuple. const char* type_name = genname_type(type); const char* trace_name = genname_tracetuple(type_name); LLVMValueRef trace_fn = LLVMGetNamedFunction(c->module, trace_name); // There will be no trace function if the tuple doesn't need tracing. if(trace_fn == NULL) return false; LLVMValueRef args[2]; args[0] = ctx; args[1] = value; LLVMBuildCall(c->builder, trace_fn, args, 2, ""); return true; }
JITInstructionFunction_t JITImpl::getFunctionThunk(JITFunctionInfo &info) { LLVMValueRef f = LLVMAddFunction(module, "", jitFunctionType); LLVMValueRef thread = LLVMGetParam(f, 0); LLVMBasicBlockRef entryBB = LLVMAppendBasicBlock(f, "entry"); LLVMPositionBuilderAtEnd(builder, entryBB); LLVMValueRef args[] = { thread }; LLVMValueRef call = LLVMBuildCall(builder, info.value, args, 1, ""); LLVMSetTailCall(call, true); LLVMSetInstructionCallConv(call, LLVMFastCallConv); LLVMBuildRet(builder, call); if (DEBUG_JIT) { LLVMDumpValue(f); LLVMVerifyFunction(f, LLVMAbortProcessAction); } return reinterpret_cast<JITInstructionFunction_t>( LLVMGetPointerToGlobal(executionEngine, f)); }
SCM llvm_build_call(SCM scm_function, SCM scm_llvm, SCM scm_return_type, SCM scm_function_name, SCM scm_argument_types, SCM scm_values) { SCM retval; struct llvm_function_t *function = get_llvm_function(scm_function); struct llvm_module_t *llvm = get_llvm(scm_llvm); char *function_name = scm_to_locale_string(scm_function_name); LLVMValueRef function_pointer = LLVMAddFunction(llvm->module, function_name, function_type(scm_return_type, scm_argument_types)); free(function_name); // LLVMAddFunctionAttr(function_pointer, LLVMExternalLinkage); int n_values = scm_ilength(scm_values); LLVMValueRef *values = scm_gc_malloc_pointerless(n_values * sizeof(LLVMValueRef), "llvm-build-call"); for (int i=0; i<n_values; i++) { values[i] = get_llvm_value(scm_car(scm_values))->value; scm_values = scm_cdr(scm_values); }; struct llvm_value_t *result = (struct llvm_value_t *)scm_gc_calloc(sizeof(struct llvm_value_t), "llvmvalue"); SCM_NEWSMOB(retval, llvm_value_tag, result); result->value = LLVMBuildCall(function->builder, function_pointer, values, n_values, "x"); return retval; }
/** * lp_build_printf. * * Build printf call in LLVM IR. The output goes to stdout. * The additional variable arguments need to have type * LLVMValueRef. */ LLVMValueRef lp_build_printf(struct gallivm_state *gallivm, const char *fmt, ...) { va_list arglist; int i = 0; int argcount = lp_get_printf_arg_count(fmt); LLVMBuilderRef builder = gallivm->builder; LLVMContextRef context = gallivm->context; LLVMModuleRef module = gallivm->module; LLVMValueRef params[50]; LLVMValueRef fmtarg = lp_build_const_string_variable(module, context, fmt, strlen(fmt) + 1); LLVMValueRef int0 = lp_build_const_int32(gallivm, 0); LLVMValueRef index[2]; LLVMValueRef func_printf = LLVMGetNamedFunction(module, "printf"); assert(Elements(params) >= argcount + 1); index[0] = index[1] = int0; if (!func_printf) { LLVMTypeRef printf_type = LLVMFunctionType(LLVMIntTypeInContext(context, 32), NULL, 0, 1); func_printf = LLVMAddFunction(module, "printf", printf_type); } params[0] = LLVMBuildGEP(builder, fmtarg, index, 2, ""); va_start(arglist, fmt); for (i = 1; i <= argcount; i++) { LLVMValueRef val = va_arg(arglist, LLVMValueRef); LLVMTypeRef type = LLVMTypeOf(val); /* printf wants doubles, so lets convert so that * we can actually print them */ if (LLVMGetTypeKind(type) == LLVMFloatTypeKind) val = LLVMBuildFPExt(builder, val, LLVMDoubleTypeInContext(context), ""); params[i] = val; } va_end(arglist); return LLVMBuildCall(builder, func_printf, params, argcount + 1, ""); }
LLVMValueRef gen_call(struct node *ast) { LLVMValueRef func, *arg_list = NULL; struct node *n; int arg_count, i; func = LLVMBuildBitCast(builder, rvalue_to_lvalue(codegen(ast->one)), LLVMPointerType(TYPE_FUNC, 0), ""); arg_count = count_chain(ast->two); arg_list = calloc(sizeof(LLVMValueRef), arg_count); if (arg_count > 0 && arg_list == NULL) generror("out of memory"); for (i = 0, n = ast->two; i < arg_count; i++, n = n->two) arg_list[arg_count - i - 1] = codegen(n->one); return LLVMBuildCall(builder, func, arg_list, arg_count, ""); }