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; }
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 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); }
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)); }
static LLVMValueRef invoke_fun(compile_t* c, LLVMValueRef fun, LLVMValueRef* args, int count, const char* ret, bool setcc) { if(fun == NULL) return NULL; LLVMBasicBlockRef this_block = LLVMGetInsertBlock(c->builder); LLVMBasicBlockRef then_block = LLVMInsertBasicBlockInContext(c->context, this_block, "invoke"); LLVMMoveBasicBlockAfter(then_block, this_block); LLVMBasicBlockRef else_block = c->frame->invoke_target; LLVMValueRef invoke = LLVMBuildInvoke(c->builder, fun, args, count, then_block, else_block, ret); if(setcc) LLVMSetInstructionCallConv(invoke, c->callconv); LLVMPositionBuilderAtEnd(c->builder, then_block); return invoke; }
static void primitive_call(compile_t* c, const char* method) { size_t i = HASHMAP_BEGIN; reach_type_t* t; while((t = reach_types_next(&c->reach->types, &i)) != NULL) { if(t->underlying != TK_PRIMITIVE) continue; reach_method_t* m = reach_method(t, TK_NONE, method, NULL); if(m == NULL) continue; LLVMValueRef value = codegen_call(c, m->func, &t->instance, 1); if(c->str__final == method) LLVMSetInstructionCallConv(value, LLVMCCallConv); } }
static void gen_main(compile_t* c, gentype_t* main_g, gentype_t* env_g) { LLVMTypeRef params[3]; params[0] = c->i32; params[1] = LLVMPointerType(LLVMPointerType(c->i8, 0), 0); params[2] = LLVMPointerType(LLVMPointerType(c->i8, 0), 0); LLVMTypeRef ftype = LLVMFunctionType(c->i32, params, 3, false); LLVMValueRef func = LLVMAddFunction(c->module, "main", ftype); codegen_startfun(c, func, false); LLVMValueRef args[3]; args[0] = LLVMGetParam(func, 0); LLVMSetValueName(args[0], "argc"); args[1] = LLVMGetParam(func, 1); LLVMSetValueName(args[1], "argv"); args[2] = LLVMGetParam(func, 2); LLVMSetValueName(args[1], "envp"); // Initialise the pony runtime with argc and argv, getting a new argc. args[0] = gencall_runtime(c, "pony_init", args, 2, "argc"); // Create the main actor and become it. LLVMValueRef main_actor = create_main(c, main_g); // Create an Env on the main actor's heap. const char* env_name = "Env"; const char* env_create = genname_fun(env_name, "_create", NULL); LLVMValueRef env_args[4]; env_args[0] = gencall_alloc(c, env_g); env_args[1] = LLVMBuildZExt(c->builder, args[0], c->i64, ""); env_args[2] = args[1]; env_args[3] = args[2]; LLVMValueRef env = gencall_runtime(c, env_create, env_args, 4, "env"); LLVMSetInstructionCallConv(env, GEN_CALLCONV); // Run primitive initialisers using the main actor's heap. primitive_call(c, stringtab("_init"), env); // Create a type for the message. LLVMTypeRef f_params[4]; f_params[0] = c->i32; f_params[1] = c->i32; f_params[2] = c->void_ptr; f_params[3] = LLVMTypeOf(env); LLVMTypeRef msg_type = LLVMStructTypeInContext(c->context, f_params, 4, false); LLVMTypeRef msg_type_ptr = LLVMPointerType(msg_type, 0); // Allocate the message, setting its size and ID. uint32_t index = genfun_vtable_index(c, main_g, stringtab("create"), NULL); size_t msg_size = LLVMABISizeOfType(c->target_data, msg_type); args[0] = LLVMConstInt(c->i32, pool_index(msg_size), false); args[1] = LLVMConstInt(c->i32, index, false); LLVMValueRef msg = gencall_runtime(c, "pony_alloc_msg", args, 2, ""); LLVMValueRef msg_ptr = LLVMBuildBitCast(c->builder, msg, msg_type_ptr, ""); // Set the message contents. LLVMValueRef env_ptr = LLVMBuildStructGEP(c->builder, msg_ptr, 3, ""); LLVMBuildStore(c->builder, env, env_ptr); // Trace the message. gencall_runtime(c, "pony_gc_send", NULL, 0, ""); const char* env_trace = genname_trace(env_name); args[0] = LLVMBuildBitCast(c->builder, env, c->object_ptr, ""); args[1] = LLVMGetNamedFunction(c->module, env_trace); gencall_runtime(c, "pony_traceobject", args, 2, ""); gencall_runtime(c, "pony_send_done", NULL, 0, ""); // Send the message. args[0] = main_actor; args[1] = msg; gencall_runtime(c, "pony_sendv", args, 2, ""); // Start the runtime. LLVMValueRef zero = LLVMConstInt(c->i32, 0, false); LLVMValueRef rc = gencall_runtime(c, "pony_start", &zero, 1, ""); // Run primitive finalisers. We create a new main actor as a context to run // the finalisers in, but we do not initialise or schedule it. LLVMValueRef final_actor = create_main(c, main_g); primitive_call(c, stringtab("_final"), NULL); args[0] = final_actor; gencall_runtime(c, "pony_destroy", args, 1, ""); // Return the runtime exit code. LLVMBuildRet(c->builder, rc); codegen_finishfun(c); // External linkage for main(). LLVMSetLinkage(func, LLVMExternalLinkage); }