void gendesc_init(compile_t* c, gentype_t* g) { // Initialise the global descriptor. uint32_t size = (uint32_t)LLVMABISizeOfType(c->target_data, g->structure); // Generate a separate type ID for every type. LLVMValueRef args[DESC_LENGTH]; args[DESC_ID] = make_type_id(c, g->type_name); args[DESC_SIZE] = LLVMConstInt(c->i32, size, false); args[DESC_TRAIT_COUNT] = make_trait_count(c, g); args[DESC_FIELD_COUNT] = make_field_count(c, g); args[DESC_TRACE] = make_function_ptr(c, genname_trace(g->type_name), c->trace_fn); args[DESC_SERIALISE] = make_function_ptr(c, genname_serialise(g->type_name), c->trace_fn); args[DESC_DESERIALISE] = make_function_ptr(c, genname_deserialise(g->type_name), c->trace_fn); args[DESC_DISPATCH] = make_function_ptr(c, genname_dispatch(g->type_name), c->dispatch_fn); args[DESC_FINALISE] = make_function_ptr(c, genname_finalise(g->type_name), c->final_fn); args[DESC_EVENT_NOTIFY] = LLVMConstInt(c->i32, genfun_vtable_index(c, g, stringtab("_event_notify"), NULL), false); args[DESC_TRAITS] = make_trait_list(c, g); args[DESC_FIELDS] = make_field_list(c, g); args[DESC_VTABLE] = make_vtable(c, g); LLVMValueRef desc = LLVMConstNamedStruct(g->desc_type, args, DESC_LENGTH); LLVMSetInitializer(g->desc, desc); LLVMSetGlobalConstant(g->desc, true); }
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 LLVMValueRef dispatch_function(compile_t* c, ast_t* from, gentype_t* g, LLVMValueRef l_value, const char* method_name, ast_t* typeargs) { LLVMValueRef func; if(g->use_type == c->object_ptr) { // Virtual, get the function by selector colour. uint32_t index = genfun_vtable_index(c, g, method_name, typeargs); assert(index != (uint32_t)-1); // Get the function from the vtable. func = gendesc_vtable(c, l_value, index); // Cast to the right function type. LLVMTypeRef f_type = genfun_sig(c, g, method_name, typeargs); if(f_type == NULL) { ast_error(from, "couldn't create a signature for '%s'", method_name); return NULL; } f_type = LLVMPointerType(f_type, 0); func = LLVMBuildBitCast(c->builder, func, f_type, "method"); } else { // Static, get the actual function. func = genfun_proto(c, g, method_name, typeargs); if(func == NULL) { ast_error(from, "couldn't locate '%s'", method_name); return NULL; } } return func; }
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); }