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; }
LLVMBasicBlockRef JITImpl::getOrCreateMemoryCheckBailoutBlock(unsigned index) { if (index == 0) { if (interpretOneBB) { return interpretOneBB; } } else if (endTraceBB) { return endTraceBB; } LLVMBasicBlockRef savedInsertPoint = LLVMGetInsertBlock(builder); LLVMBasicBlockRef bailoutBB = LLVMAppendBasicBlock(getCurrentFunction(), ""); LLVMPositionBuilderAtEnd(builder, bailoutBB); if (index == 0) { LLVMValueRef args[] = { threadParam }; LLVMValueRef call = emitCallToBeInlined(functions.jitInterpretOne, args, 1); LLVMBuildRet(builder, call); interpretOneBB = bailoutBB; } else { ensureEarlyReturnBB(LLVMGetReturnType(jitFunctionType)); earlyReturnIncomingValues.push_back( LLVMConstInt(LLVMGetReturnType(jitFunctionType), JIT_RETURN_END_TRACE, false)); earlyReturnIncomingBlocks.push_back(LLVMGetInsertBlock(builder)); LLVMBuildBr(builder, earlyReturnBB); endTraceBB = bailoutBB; } LLVMPositionBuilderAtEnd(builder, savedInsertPoint); return bailoutBB; }
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; }
LLVMCompiledProgram LLVM_compile(ASTNode *node) { char *error = NULL; // Used to retrieve messages from functions LLVMLinkInJIT(); LLVMInitializeNativeTarget(); LLVMModuleRef mod = LLVMModuleCreateWithName("calc_module"); LLVMTypeRef program_args[] = { }; LLVMValueRef program = LLVMAddFunction(mod, "program", LLVMFunctionType(LLVMInt32Type(), program_args, 0, 0)); LLVMSetFunctionCallConv(program, LLVMCCallConv); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(program, "entry"); LLVMPositionBuilderAtEnd(builder, entry); LLVMValueRef res = LLVM_visit(node, builder); LLVMBuildRet(builder, res); LLVMVerifyModule(mod, LLVMAbortProcessAction, &error); LLVMDisposeMessage(error); // Handler == LLVMAbortProcessAction -> No need to check errors LLVMDisposeBuilder(builder); return (LLVMCompiledProgram) { .module = mod, .function = program }; }
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; }
int main(int argc, char const *argv[]) { LLVMModuleRef mod = LLVMModuleCreateWithName("sum"); LLVMTypeRef param_types[] = { LLVMInt32Type(), LLVMInt32Type() }; LLVMTypeRef ret_type = LLVMFunctionType(LLVMInt32Type(), /* ret type */ param_types, /* arg types */ 2, /* arg count */ 0 /* is variadic */); LLVMValueRef sum = LLVMAddFunction(mod, "sum", ret_type); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(sum, "entry"); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, entry); LLVMValueRef tmp = LLVMBuildAdd(builder, LLVMGetParam(sum, 0), LLVMGetParam(sum, 1), "tmp"); LLVMBuildRet(builder, tmp); char *error = NULL; LLVMVerifyModule(mod, LLVMAbortProcessAction, &error); LLVMDisposeMessage(error); LLVMExecutionEngineRef engine; error = NULL; LLVMLinkInJIT(); LLVMInitializeNativeTarget(); if (LLVMCreateExecutionEngineForModule(&engine, mod, &error) != 0) { fprintf(stderr, "failed to create execution engine\n"); abort(); } if (error) { fprintf(stderr, "error: %s\n", error); LLVMDisposeMessage(error); exit(EXIT_FAILURE); } if (argc < 3) { fprintf(stderr, "usage: %s x y\n", argv[0]); exit(EXIT_FAILURE); } long long x = strtoll(argv[1], NULL, 10); long long y = strtoll(argv[2], NULL, 10); LLVMGenericValueRef args[] = { LLVMCreateGenericValueOfInt(LLVMInt32Type(), x, 0), LLVMCreateGenericValueOfInt(LLVMInt32Type(), y, 0), }; LLVMGenericValueRef res = LLVMRunFunction(engine, sum, 2, args); printf("%d\n", (int)LLVMGenericValueToInt(res, 0)); // write bitcode to file if (LLVMWriteBitcodeToFile(mod, "sum.bc") != 0) { fprintf(stderr, "error writing bitcode to file\n"); } LLVMDisposeBuilder(builder); LLVMDisposeExecutionEngine(engine); }
static bool genfun_new(compile_t* c, reachable_type_t* t, reachable_method_t* m) { assert(m->func != NULL); AST_GET_CHILDREN(m->r_fun, cap, id, typeparams, params, result, can_error, body); codegen_startfun(c, m->func, m->di_file, m->di_method); name_params(c, t, m, params, m->func); LLVMValueRef value = gen_expr(c, body); if(value == NULL) return false; // Return 'this'. if(t->primitive == NULL) value = LLVMGetParam(m->func, 0); codegen_debugloc(c, ast_childlast(body)); LLVMBuildRet(c->builder, value); codegen_debugloc(c, NULL); codegen_finishfun(c); return true; }
static void pointer_alloc(compile_t* c, reach_type_t* t, reach_type_t* t_elem) { FIND_METHOD("_alloc"); LLVMTypeRef params[2]; params[0] = t->use_type; params[1] = c->intptr; start_function(c, m, t->use_type, params, 2); // Set up a constant integer for the allocation size. size_t size = (size_t)LLVMABISizeOfType(c->target_data, t_elem->use_type); LLVMValueRef l_size = LLVMConstInt(c->intptr, size, false); LLVMValueRef len = LLVMGetParam(m->func, 1); LLVMValueRef args[2]; args[0] = codegen_ctx(c); args[1] = LLVMBuildMul(c->builder, len, l_size, ""); LLVMValueRef result = gencall_runtime(c, "pony_alloc", args, 2, ""); result = LLVMBuildBitCast(c->builder, result, t->use_type, ""); LLVMBuildRet(c->builder, result); codegen_finishfun(c); }
SCM llvm_function_return(SCM scm_self, SCM scm_value) { struct llvm_function_t *self = get_llvm_function(scm_self); struct llvm_value_t *value = get_llvm_value(scm_value); LLVMBuildRet(self->builder, value->value); return SCM_UNSPECIFIED; }
static LLVMValueRef add_test(LLVMModuleRef module, const char *name, lp_func_t lp_func) { LLVMTypeRef v4sf = LLVMVectorType(LLVMFloatType(), 4); LLVMTypeRef args[1] = { v4sf }; LLVMValueRef func = LLVMAddFunction(module, name, LLVMFunctionType(v4sf, args, 1, 0)); LLVMValueRef arg1 = LLVMGetParam(func, 0); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMBasicBlockRef block = LLVMAppendBasicBlock(func, "entry"); LLVMValueRef ret; struct lp_build_context bld; bld.builder = builder; bld.type.floating = 1; bld.type.width = 32; bld.type.length = 4; LLVMSetFunctionCallConv(func, LLVMCCallConv); LLVMPositionBuilderAtEnd(builder, block); ret = lp_func(&bld, arg1); LLVMBuildRet(builder, ret); LLVMDisposeBuilder(builder); return func; }
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; } }
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 gen_return(compile_t* c, ast_t* ast) { ast_t* expr = ast_child(ast); LLVMValueRef value = gen_expr(c, expr); size_t clause; ast_t* try_expr = ast_try_clause(ast, &clause); // Do the then block only if we return in the body or else clause. // In the then block, return without doing the then block. if((try_expr != NULL) && (clause != 2)) gen_expr(c, ast_childidx(try_expr, 2)); LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(codegen_fun(c))); LLVMTypeRef r_type = LLVMGetReturnType(f_type); codegen_debugloc(c, ast); if(LLVMGetTypeKind(r_type) != LLVMVoidTypeKind) { LLVMValueRef ret = gen_assign_cast(c, r_type, value, ast_type(expr)); codegen_scope_lifetime_end(c); LLVMBuildRet(c->builder, ret); } else { codegen_scope_lifetime_end(c); LLVMBuildRetVoid(c->builder); } codegen_debugloc(c, NULL); return GEN_NOVALUE; }
static bool genfun_allocator(compile_t* c, gentype_t* g) { // No allocator for primitive types or pointers. if((g->primitive != NULL) || is_pointer(g->ast)) return true; const char* funname = genname_fun(g->type_name, "Alloc", NULL); LLVMTypeRef ftype = LLVMFunctionType(g->use_type, NULL, 0, false); LLVMValueRef fun = codegen_addfun(c, funname, ftype); codegen_startfun(c, fun, false); LLVMValueRef result; switch(g->underlying) { case TK_PRIMITIVE: case TK_CLASS: // Allocate the object or return the global instance. result = gencall_alloc(c, g); break; case TK_ACTOR: // Allocate the actor. result = gencall_create(c, g); break; default: assert(0); return false; } LLVMBuildRet(c->builder, result); codegen_finishfun(c); return true; }
static void pointer_offset(compile_t* c, reach_type_t* t, reach_type_t* t_elem) { FIND_METHOD("_offset"); LLVMTypeRef params[3]; params[0] = t->use_type; params[1] = c->intptr; start_function(c, m, t->use_type, params, 2); // Set up a constant integer for the allocation size. size_t size = (size_t)LLVMABISizeOfType(c->target_data, t_elem->use_type); LLVMValueRef l_size = LLVMConstInt(c->intptr, size, false); LLVMValueRef ptr = LLVMGetParam(m->func, 0); LLVMValueRef n = LLVMGetParam(m->func, 1); // Return ptr + (n * sizeof(len)). LLVMValueRef src = LLVMBuildPtrToInt(c->builder, ptr, c->intptr, ""); LLVMValueRef offset = LLVMBuildMul(c->builder, n, l_size, ""); LLVMValueRef result = LLVMBuildAdd(c->builder, src, offset, ""); result = LLVMBuildIntToPtr(c->builder, result, t->use_type, ""); LLVMBuildRet(c->builder, result); codegen_finishfun(c); BOX_FUNCTION(); }
static void maybe_none(compile_t* c, reach_type_t* t) { FIND_METHOD("none"); start_function(c, m, t->use_type, &t->use_type, 1); LLVMBuildRet(c->builder, LLVMConstNull(t->use_type)); codegen_finishfun(c); }
static void pointer_unsafe(compile_t* c, reach_type_t* t) { FIND_METHOD("_unsafe"); start_function(c, m, t->use_type, &t->use_type, 1); LLVMBuildRet(c->builder, LLVMGetParam(m->func, 0)); codegen_finishfun(c); }
static void number_conversion(compile_t* c, num_conv_t* from, num_conv_t* to, bool native128) { if(!native128 && ((from->is_float && (to->size > 64)) || (to->is_float && (from->size > 64))) ) { return; } reach_type_t* t = reach_type_name(c->reach, from->type_name); if(t == NULL) return; FIND_METHOD(to->fun_name); start_function(c, m, to->type, &from->type, 1); LLVMValueRef arg = LLVMGetParam(m->func, 0); LLVMValueRef result; if(from->is_float) { if(to->is_float) { if(from->size < to->size) result = LLVMBuildFPExt(c->builder, arg, to->type, ""); else if(from->size > to->size) result = LLVMBuildFPTrunc(c->builder, arg, to->type, ""); else result = arg; } else if(to->is_signed) { result = LLVMBuildFPToSI(c->builder, arg, to->type, ""); } else { result = LLVMBuildFPToUI(c->builder, arg, to->type, ""); } } else if(to->is_float) { if(from->is_signed) result = LLVMBuildSIToFP(c->builder, arg, to->type, ""); else result = LLVMBuildUIToFP(c->builder, arg, to->type, ""); } else if(from->size > to->size) { result = LLVMBuildTrunc(c->builder, arg, to->type, ""); } else if(from->size < to->size) { if(from->is_signed) result = LLVMBuildSExt(c->builder, arg, to->type, ""); else result = LLVMBuildZExt(c->builder, arg, to->type, ""); } else { result = arg; } LLVMBuildRet(c->builder, result); codegen_finishfun(c); BOX_FUNCTION(); }
static void f64__nan(compile_t* c, reach_type_t* t) { FIND_METHOD("_nan"); start_function(c, m, c->f64, &c->f64, 1); LLVMValueRef result = LLVMConstNaN(c->f64); LLVMBuildRet(c->builder, result); codegen_finishfun(c); }
static void pointer_create(compile_t* c, reach_type_t* t) { FIND_METHOD("create"); start_function(c, m, t->use_type, &t->use_type, 1); LLVMValueRef result = LLVMConstNull(t->use_type); LLVMBuildRet(c->builder, result); codegen_finishfun(c); }
static LLVMValueRef genfun_newbe(compile_t* c, gentype_t* g, const char *name, ast_t* typeargs) { ast_t* fun = get_fun(g, name, typeargs); LLVMValueRef func = get_prototype(c, g, name, typeargs, fun); if(func == NULL) { ast_free_unattached(fun); return NULL; } codegen_startfun(c, func, ast_debug(fun)); name_params(c, g->ast, ast_childidx(fun, 3), func); genfun_dwarf(c, g, name, typeargs, fun); if(!gen_field_init(c, g)) { ast_free_unattached(fun); return NULL; } ast_t* body = ast_childidx(fun, 6); LLVMValueRef value = gen_expr(c, body); if(value == NULL) { ast_free_unattached(fun); return NULL; } LLVMBuildRetVoid(c->builder); codegen_finishfun(c); // Generate the sender. LLVMValueRef sender = get_sender(c, g, name, typeargs); codegen_startfun(c, sender, false); LLVMValueRef this_ptr = LLVMGetParam(sender, 0); // Send the arguments in a message to 'this'. uint32_t index = genfun_vtable_index(c, g, name, typeargs); LLVMTypeRef msg_type_ptr = send_message(c, fun, this_ptr, sender, index); genfun_dwarf_return(c, body); // Return 'this'. LLVMBuildRet(c->builder, this_ptr); codegen_finishfun(c); // Add the dispatch case. add_dispatch_case(c, g, fun, index, func, msg_type_ptr); ast_free_unattached(fun); return func; }
static void pointer_usize(compile_t* c, reach_type_t* t) { FIND_METHOD("usize"); start_function(c, m, c->intptr, &t->use_type, 1); LLVMValueRef ptr = LLVMGetParam(m->func, 0); LLVMValueRef result = LLVMBuildPtrToInt(c->builder, ptr, c->intptr, ""); LLVMBuildRet(c->builder, result); codegen_finishfun(c); }
static void platform_debug(compile_t* c, reach_type_t* t) { FIND_METHOD("debug"); start_function(c, m, c->ibool, &t->use_type, 1); LLVMValueRef result = LLVMConstInt(c->ibool, !c->opt->release, false); LLVMBuildRet(c->builder, result); codegen_finishfun(c); BOX_FUNCTION(); }
static void f64_bits(compile_t* c, reach_type_t* t) { FIND_METHOD("bits"); start_function(c, m, c->i64, &c->f64, 1); LLVMValueRef result = LLVMBuildBitCast(c->builder, LLVMGetParam(m->func, 0), c->i64, ""); LLVMBuildRet(c->builder, result); codegen_finishfun(c); BOX_FUNCTION(); }
static void platform_x86(compile_t* c, reach_type_t* t) { FIND_METHOD("x86"); start_function(c, m, c->ibool, &t->use_type, 1); LLVMValueRef result = LLVMConstInt(c->ibool, target_is_x86(c->opt->triple), false); LLVMBuildRet(c->builder, result); codegen_finishfun(c); BOX_FUNCTION(); }
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); }
static LLVMValueRef make_unbox_function(compile_t* c, gentype_t* g, const char* name) { LLVMValueRef fun = LLVMGetNamedFunction(c->module, name); if(fun == NULL) return LLVMConstNull(c->void_ptr); // Create a new unboxing function that forwards to the real function. LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(fun)); int count = LLVMCountParamTypes(f_type); // If it takes no arguments, it's a special number constructor. Don't put it // in the vtable. if(count == 0) return LLVMConstNull(c->void_ptr); size_t buf_size = count *sizeof(LLVMTypeRef); LLVMTypeRef* params = (LLVMTypeRef*)pool_alloc_size(buf_size); LLVMGetParamTypes(f_type, params); LLVMTypeRef ret_type = LLVMGetReturnType(f_type); // It's the same type, but it takes the boxed type instead of the primitive // type as the receiver. params[0] = g->structure_ptr; const char* unbox_name = genname_unbox(name); LLVMTypeRef unbox_type = LLVMFunctionType(ret_type, params, count, false); LLVMValueRef unbox_fun = codegen_addfun(c, unbox_name, unbox_type); codegen_startfun(c, unbox_fun, false); // Extract the primitive type from element 1 and call the real function. LLVMValueRef this_ptr = LLVMGetParam(unbox_fun, 0); LLVMValueRef primitive_ptr = LLVMBuildStructGEP(c->builder, this_ptr, 1, ""); LLVMValueRef primitive = LLVMBuildLoad(c->builder, primitive_ptr, ""); LLVMValueRef* args = (LLVMValueRef*)pool_alloc_size(buf_size); args[0] = primitive; for(int i = 1; i < count; i++) args[i] = LLVMGetParam(unbox_fun, i); LLVMValueRef result = codegen_call(c, fun, args, count); LLVMBuildRet(c->builder, result); codegen_finishfun(c); pool_free_size(buf_size, params); pool_free_size(buf_size, args); return LLVMConstBitCast(unbox_fun, c->void_ptr); }
static void f64_from_bits(compile_t* c, reach_type_t* t) { FIND_METHOD("from_bits"); LLVMTypeRef params[2]; params[0] = c->f64; params[1] = c->i64; start_function(c, m, c->f64, params, 2); LLVMValueRef result = LLVMBuildBitCast(c->builder, LLVMGetParam(m->func, 1), c->f64, ""); LLVMBuildRet(c->builder, result); codegen_finishfun(c); }
static void maybe_create(compile_t* c, reach_type_t* t, reach_type_t* t_elem) { FIND_METHOD("create"); LLVMTypeRef params[2]; params[0] = t->use_type; params[1] = t_elem->use_type; start_function(c, m, t->use_type, params, 2); LLVMValueRef param = LLVMGetParam(m->func, 1); LLVMValueRef result = LLVMBuildBitCast(c->builder, param, t->use_type, ""); LLVMBuildRet(c->builder, result); codegen_finishfun(c); }
static void maybe_is_none(compile_t* c, reach_type_t* t) { // Returns true if the receiver is null. FIND_METHOD("is_none"); start_function(c, m, c->ibool, &t->use_type, 1); LLVMValueRef receiver = LLVMGetParam(m->func, 0); LLVMValueRef test = LLVMBuildIsNull(c->builder, receiver, ""); LLVMValueRef value = LLVMBuildZExt(c->builder, test, c->ibool, ""); LLVMBuildRet(c->builder, value); codegen_finishfun(c); BOX_FUNCTION(); }