void gendesc_init(compile_t* c, reach_type_t* t) { if(t->desc_type == NULL) return; // Initialise the global descriptor. uint32_t event_notify_index = reach_vtable_index(t, c->str__event_notify); uint32_t trait_count = 0; LLVMValueRef trait_list = make_trait_list(c, t, &trait_count); LLVMValueRef args[DESC_LENGTH]; args[DESC_ID] = LLVMConstInt(c->i32, t->type_id, false); args[DESC_SIZE] = LLVMConstInt(c->i32, t->abi_size, false); args[DESC_TRAIT_COUNT] = LLVMConstInt(c->i32, trait_count, false); args[DESC_FIELD_COUNT] = make_field_count(c, t); args[DESC_FIELD_OFFSET] = make_field_offset(c, t); args[DESC_INSTANCE] = make_desc_ptr(t->instance, c->object_ptr); args[DESC_TRACE] = make_desc_ptr(t->trace_fn, c->trace_fn); args[DESC_SERIALISE_TRACE] = make_desc_ptr(t->serialise_trace_fn, c->trace_fn); args[DESC_SERIALISE] = make_desc_ptr(t->serialise_fn, c->serialise_fn); args[DESC_DESERIALISE] = make_desc_ptr(t->deserialise_fn, c->trace_fn); args[DESC_DISPATCH] = make_desc_ptr(t->dispatch_fn, c->dispatch_fn); args[DESC_FINALISE] = make_desc_ptr(t->final_fn, c->final_fn); args[DESC_EVENT_NOTIFY] = LLVMConstInt(c->i32, event_notify_index, false); args[DESC_TRAITS] = trait_list; args[DESC_FIELDS] = make_field_list(c, t); args[DESC_VTABLE] = make_vtable(c, t); LLVMValueRef desc = LLVMConstNamedStruct(t->desc_type, args, DESC_LENGTH); LLVMSetInitializer(t->desc, desc); LLVMSetGlobalConstant(t->desc, true); }
static void gen_main(compile_t* c, reach_type_t* t_main, reach_type_t* t_env) { 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, NULL, NULL); LLVMValueRef args[4]; 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[2], "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 ctx = gencall_runtime(c, "pony_ctx", NULL, 0, ""); codegen_setctx(c, ctx); LLVMValueRef main_actor = create_main(c, t_main, ctx); // Create an Env on the main actor's heap. reach_method_t* m = reach_method(t_env, TK_NONE, c->str__create, NULL); LLVMValueRef env_args[4]; env_args[0] = gencall_alloc(c, t_env); env_args[1] = args[0]; env_args[2] = LLVMBuildBitCast(c->builder, args[1], c->void_ptr, ""); env_args[3] = LLVMBuildBitCast(c->builder, args[2], c->void_ptr, ""); codegen_call(c, m->func, env_args, 4); LLVMValueRef env = env_args[0]; // Run primitive initialisers using the main actor's heap. primitive_call(c, c->str__init); // 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 = reach_vtable_index(t_main, c->str_create); size_t msg_size = (size_t)LLVMABISizeOfType(c->target_data, msg_type); args[0] = LLVMConstInt(c->i32, ponyint_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. args[0] = ctx; gencall_runtime(c, "pony_gc_send", args, 1, ""); args[0] = ctx; args[1] = LLVMBuildBitCast(c->builder, env, c->object_ptr, ""); args[2] = LLVMBuildBitCast(c->builder, t_env->desc, c->descriptor_ptr, ""); args[3] = LLVMConstInt(c->i32, PONY_TRACE_IMMUTABLE, false); gencall_runtime(c, "pony_traceknown", args, 4, ""); args[0] = ctx; gencall_runtime(c, "pony_send_done", args, 1, ""); // Send the message. args[0] = ctx; args[1] = main_actor; args[2] = msg; gencall_runtime(c, "pony_sendv", args, 3, ""); // 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. if(need_primitive_call(c, c->str__final)) { LLVMValueRef final_actor = create_main(c, t_main, ctx); primitive_call(c, c->str__final); args[0] = final_actor; gencall_runtime(c, "ponyint_destroy", args, 1, ""); } // Return the runtime exit code. LLVMBuildRet(c->builder, rc); codegen_finishfun(c); // External linkage for main(). LLVMSetLinkage(func, LLVMExternalLinkage); }