LLVMValueRef gen_string(compile_t* c, ast_t* ast) { ast_t* type = ast_type(ast); const char* name = ast_name(ast); size_t len = ast_name_len(ast); LLVMValueRef args[4]; args[0] = LLVMConstInt(c->i32, 0, false); args[1] = LLVMConstInt(c->i32, 0, false); LLVMValueRef str = LLVMConstStringInContext(c->context, name, (int)len, false); LLVMValueRef g_str = LLVMAddGlobal(c->module, LLVMTypeOf(str), ""); LLVMSetLinkage(g_str, LLVMPrivateLinkage); LLVMSetInitializer(g_str, str); LLVMSetGlobalConstant(g_str, true); LLVMValueRef str_ptr = LLVMConstInBoundsGEP(g_str, args, 2); reach_type_t* t = reach_type(c->reach, type); args[0] = t->desc; args[1] = LLVMConstInt(c->intptr, len, false); args[2] = LLVMConstInt(c->intptr, len + 1, false); args[3] = str_ptr; LLVMValueRef inst = LLVMConstNamedStruct(t->structure, args, 4); LLVMValueRef g_inst = LLVMAddGlobal(c->module, t->structure, ""); LLVMSetInitializer(g_inst, inst); LLVMSetGlobalConstant(g_inst, true); LLVMSetLinkage(g_inst, LLVMPrivateLinkage); return g_inst; }
static void set_method_external_interface(reach_type_t* t, const char* name, uint32_t vtable_index) { size_t i = HASHMAP_BEGIN; reach_type_t* sub; while((sub = reach_type_cache_next(&t->subtypes, &i)) != NULL) { reach_method_name_t* n = reach_method_name(sub, name); if(n == NULL) continue; size_t j = HASHMAP_BEGIN; reach_method_t* m; while((m = reach_mangled_next(&n->r_mangled, &j)) != NULL) { if(m->vtable_index == vtable_index) { compile_method_t* c_m = (compile_method_t*)m->c_method; LLVMSetFunctionCallConv(c_m->func, LLVMCCallConv); LLVMSetLinkage(c_m->func, LLVMExternalLinkage); break; } } } }
void genprim_string_deserialise(compile_t* c, reach_type_t* t) { // Generate the deserisalise function. t->deserialise_fn = codegen_addfun(c, genname_serialise(t->name), c->trace_type); codegen_startfun(c, t->deserialise_fn, NULL, NULL); LLVMSetFunctionCallConv(t->deserialise_fn, LLVMCCallConv); LLVMSetLinkage(t->deserialise_fn, LLVMExternalLinkage); LLVMValueRef ctx = LLVMGetParam(t->deserialise_fn, 0); LLVMValueRef arg = LLVMGetParam(t->deserialise_fn, 1); LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, t->structure_ptr, ""); gendeserialise_typeid(c, t, object); // Deserialise the string contents. LLVMValueRef alloc = field_value(c, object, 2); LLVMValueRef ptr_offset = field_value(c, object, 3); ptr_offset = LLVMBuildPtrToInt(c->builder, ptr_offset, c->intptr, ""); LLVMValueRef args[3]; args[0] = ctx; args[1] = ptr_offset; args[2] = alloc; LLVMValueRef ptr_addr = gencall_runtime(c, "pony_deserialise_block", args, 3, ""); LLVMValueRef ptr = LLVMBuildStructGEP(c->builder, object, 3, ""); LLVMBuildStore(c->builder, ptr_addr, ptr); LLVMBuildRetVoid(c->builder); codegen_finishfun(c); }
void genprim_string_serialise_trace(compile_t* c, reach_type_t* t) { // Generate the serialise_trace function. t->serialise_trace_fn = codegen_addfun(c, genname_serialise_trace(t->name), c->serialise_type); codegen_startfun(c, t->serialise_trace_fn, NULL, NULL); LLVMSetFunctionCallConv(t->serialise_trace_fn, LLVMCCallConv); LLVMSetLinkage(t->serialise_trace_fn, LLVMExternalLinkage); LLVMValueRef ctx = LLVMGetParam(t->serialise_trace_fn, 0); LLVMValueRef arg = LLVMGetParam(t->serialise_trace_fn, 1); LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, t->use_type, ""); // Read the size. LLVMValueRef size = field_value(c, object, 1); LLVMValueRef alloc = LLVMBuildAdd(c->builder, size, LLVMConstInt(c->intptr, 1, false), ""); // Reserve space for the contents. LLVMValueRef ptr = field_value(c, object, 3); LLVMValueRef args[3]; args[0] = ctx; args[1] = ptr; args[2] = alloc; gencall_runtime(c, "pony_serialise_reserve", args, 3, ""); LLVMBuildRetVoid(c->builder); codegen_finishfun(c); }
static void make_serialise(compile_t* c, reach_type_t* t) { // Use the trace function as the serialise_trace function. t->serialise_trace_fn = t->trace_fn; // Generate the serialise function. t->serialise_fn = codegen_addfun(c, genname_serialise(t->name), c->serialise_type); codegen_startfun(c, t->serialise_fn, NULL, NULL); LLVMSetFunctionCallConv(t->serialise_fn, LLVMCCallConv); LLVMSetLinkage(t->serialise_fn, LLVMExternalLinkage); LLVMValueRef ctx = LLVMGetParam(t->serialise_fn, 0); LLVMValueRef arg = LLVMGetParam(t->serialise_fn, 1); LLVMValueRef addr = LLVMGetParam(t->serialise_fn, 2); LLVMValueRef offset = LLVMGetParam(t->serialise_fn, 3); LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, t->structure_ptr, ""); LLVMValueRef offset_addr = LLVMBuildInBoundsGEP(c->builder, addr, &offset, 1, ""); serialise(c, t, ctx, object, offset_addr); LLVMBuildRetVoid(c->builder); codegen_finishfun(c); }
static void make_dispatch(compile_t* c, reach_type_t* t) { // Do nothing if we're not an actor. if(t->underlying != TK_ACTOR) return; // Create a dispatch function. const char* dispatch_name = genname_dispatch(t->name); t->dispatch_fn = codegen_addfun(c, dispatch_name, c->dispatch_type); LLVMSetFunctionCallConv(t->dispatch_fn, LLVMCCallConv); LLVMSetLinkage(t->dispatch_fn, LLVMExternalLinkage); codegen_startfun(c, t->dispatch_fn, NULL, NULL); LLVMBasicBlockRef unreachable = codegen_block(c, "unreachable"); // Read the message ID. LLVMValueRef msg = LLVMGetParam(t->dispatch_fn, 2); LLVMValueRef id_ptr = LLVMBuildStructGEP(c->builder, msg, 1, ""); LLVMValueRef id = LLVMBuildLoad(c->builder, id_ptr, "id"); // Store a reference to the dispatch switch. When we build behaviours, we // will add cases to this switch statement based on message ID. t->dispatch_switch = LLVMBuildSwitch(c->builder, id, unreachable, 0); // Mark the default case as unreachable. LLVMPositionBuilderAtEnd(c->builder, unreachable); LLVMBuildUnreachable(c->builder); codegen_finishfun(c); }
LLVMValueRef codegen_addfun(compile_t* c, const char* name, LLVMTypeRef type) { // Add the function and set the calling convention and the linkage type. LLVMValueRef fun = LLVMAddFunction(c->module, name, type); LLVMSetFunctionCallConv(fun, c->callconv); LLVMSetLinkage(fun, c->linkage); LLVMValueRef arg = LLVMGetFirstParam(fun); uint32_t i = 1; while(arg != NULL) { LLVMTypeRef type = LLVMTypeOf(arg); if(LLVMGetTypeKind(type) == LLVMPointerTypeKind) { LLVMTypeRef elem = LLVMGetElementType(type); if(LLVMGetTypeKind(elem) == LLVMStructTypeKind) { size_t size = (size_t)LLVMABISizeOfType(c->target_data, elem); LLVMSetDereferenceable(fun, i, size); } } arg = LLVMGetNextParam(arg); i++; } return fun; }
static LLVMValueRef make_trait_list(compile_t* c, reach_type_t* t, uint32_t* final_count) { // The list is an array of integers. uint32_t* tid; size_t tid_size; uint32_t count = trait_count(t, &tid, &tid_size); // If we have no traits, return a null pointer to a list. if(count == 0) return LLVMConstNull(LLVMPointerType(LLVMArrayType(c->i32, 0), 0)); // Create a constant array of trait identifiers. size_t list_size = count * sizeof(LLVMValueRef); LLVMValueRef* list = (LLVMValueRef*)ponyint_pool_alloc_size(list_size); for(uint32_t i = 0; i < count; i++) list[i] = LLVMConstInt(c->i32, tid[i], false); LLVMValueRef trait_array = LLVMConstArray(c->i32, list, count); // Create a global to hold the array. const char* name = genname_traitlist(t->name); LLVMTypeRef list_type = LLVMArrayType(c->i32, count); LLVMValueRef global = LLVMAddGlobal(c->module, list_type, name); LLVMSetGlobalConstant(global, true); LLVMSetLinkage(global, LLVMPrivateLinkage); LLVMSetInitializer(global, trait_array); ponyint_pool_free_size(tid_size, tid); ponyint_pool_free_size(list_size, list); *final_count = count; return global; }
static void make_global_instance(compile_t* c, gentype_t* g) { // Not a primitive type. if(g->underlying != TK_PRIMITIVE) return; // No instance for base types. if(g->primitive != NULL) return; // Check for an existing instance. const char* inst_name = genname_instance(g->type_name); g->instance = LLVMGetNamedGlobal(c->module, inst_name); if(g->instance != NULL) return; // Create a unique global instance. LLVMValueRef args[1]; args[0] = g->desc; LLVMValueRef value = LLVMConstNamedStruct(g->structure, args, 1); g->instance = LLVMAddGlobal(c->module, g->structure, inst_name); LLVMSetInitializer(g->instance, value); LLVMSetGlobalConstant(g->instance, true); LLVMSetLinkage(g->instance, LLVMInternalLinkage); }
int main (void) { LLVMModuleRef module = LLVMModuleCreateWithName("kal"); LLVMBuilderRef builder = LLVMCreateBuilder(); // LLVMInitializeNativeTarget(); LLVMTypeRef funcType = LLVMFunctionType(LLVMVoidType(), NULL, 0, 0); LLVMValueRef func = LLVMAddFunction(module, "main", funcType); LLVMSetLinkage(func, LLVMExternalLinkage); LLVMBasicBlockRef block = LLVMAppendBasicBlock(func, "entry"); LLVMPositionBuilderAtEnd(builder, block); LLVMValueRef cond = LLVMBuildICmp(builder, LLVMIntNE, LLVMConstInt(LLVMInt32Type(), 2, 0), LLVMConstInt(LLVMInt32Type(), 1, 0), "ifcond"); LLVMValueRef owning_block = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)); //TODO: WRONG?? //LLVMValueRef owning_block = LLVMBasicBlockAsValue(LLVMGetPreviousBasicBlock(LLVMGetInsertBlock(builder))); // 2. Generate new blocks for cases. LLVMBasicBlockRef then_ref = LLVMAppendBasicBlock(owning_block, "then"); LLVMBasicBlockRef else_ref = LLVMAppendBasicBlock(owning_block, "else"); LLVMBasicBlockRef merge_ref = LLVMAppendBasicBlock(owning_block, "ifmerge"); // 3. Branch conditionally on then or else. LLVMBuildCondBr(builder, cond, then_ref, else_ref); // 4. Build then branch prologue. LLVMPositionBuilderAtEnd(builder, then_ref); LLVMValueRef hi1 = LLVMBuildXor(builder, LLVMGetUndef(LLVMInt32Type()), LLVMGetUndef(LLVMInt32Type()), "subtmp"); // 5. Connect then branch to merge block. LLVMBuildBr(builder, merge_ref); then_ref = LLVMGetInsertBlock(builder); // 6. Build else branch prologue. LLVMPositionBuilderAtEnd(builder, else_ref); LLVMValueRef hi2 = LLVMBuildXor(builder, LLVMGetUndef(LLVMInt32Type()), LLVMGetUndef(LLVMInt32Type()), "subtmp2"); // 7. Connect else branch to merge block. LLVMBuildBr(builder, merge_ref); else_ref = LLVMGetInsertBlock(builder); // 8. Position ourselves after the merge block. LLVMPositionBuilderAtEnd(builder, merge_ref); // 9. Build the phi node. // LLVMValueRef phi = LLVMBuildPhi(builder, LLVMDoubleType(), "phi"); // 10. Add incoming edges. // LLVMAddIncoming(phi, &hi1, &then_ref, 1); // LLVMAddIncoming(phi, &hi2, &else_ref, 1); LLVMDumpModule(module); LLVMDisposeBuilder(builder); LLVMDisposeModule(module); return 0; }
static LLVMValueRef make_field_list(compile_t* c, gentype_t* g) { // The list is an array of field descriptors. int count; if(g->underlying == TK_TUPLETYPE) count = g->field_count; else count = 0; LLVMTypeRef type = LLVMArrayType(c->field_descriptor, count); // If we aren't a tuple, return a null pointer to a list. if(count == 0) return LLVMConstNull(LLVMPointerType(type, 0)); // Create a constant array of field descriptors. size_t buf_size = count *sizeof(LLVMValueRef); LLVMValueRef* list = (LLVMValueRef*)pool_alloc_size(buf_size); for(int i = 0; i < count; i++) { gentype_t fg; if(!gentype(c, g->fields[i], &fg)) return NULL; LLVMValueRef fdesc[2]; fdesc[0] = LLVMConstInt(c->i32, LLVMOffsetOfElement(c->target_data, g->primitive, i), false); if(fg.desc != NULL) { // We are a concrete type. fdesc[1] = LLVMConstBitCast(fg.desc, c->descriptor_ptr); } else { // We aren't a concrete type. fdesc[1] = LLVMConstNull(c->descriptor_ptr); } list[i] = LLVMConstStructInContext(c->context, fdesc, 2, false); } LLVMValueRef field_array = LLVMConstArray(c->field_descriptor, list, count); // Create a global to hold the array. const char* name = genname_fieldlist(g->type_name); LLVMValueRef global = LLVMAddGlobal(c->module, type, name); LLVMSetGlobalConstant(global, true); LLVMSetLinkage(global, LLVMInternalLinkage); LLVMSetInitializer(global, field_array); pool_free_size(buf_size, list); return global; }
LLVMValueRef lp_build_const_string_variable(LLVMModuleRef module, LLVMContextRef context, const char *str, int len) { LLVMValueRef string = LLVMAddGlobal(module, LLVMArrayType(LLVMInt8TypeInContext(context), len + 1), ""); LLVMSetGlobalConstant(string, TRUE); LLVMSetLinkage(string, LLVMInternalLinkage); LLVMSetInitializer(string, LLVMConstStringInContext(context, str, len + 1, TRUE)); return string; }
void gendesc_type(compile_t* c, reach_type_t* t) { switch(t->underlying) { case TK_TUPLETYPE: case TK_PRIMITIVE: case TK_STRUCT: case TK_CLASS: case TK_ACTOR: break; default: return; } const char* desc_name = genname_descriptor(t->name); uint32_t traits = trait_count(t, NULL, NULL); uint32_t fields = 0; uint32_t vtable_size = 0; if(t->underlying == TK_TUPLETYPE) fields = t->field_count; else vtable_size = t->vtable_size; t->desc_type = LLVMStructCreateNamed(c->context, desc_name); LLVMTypeRef params[DESC_LENGTH]; params[DESC_ID] = c->i32; params[DESC_SIZE] = c->i32; params[DESC_TRAIT_COUNT] = c->i32; params[DESC_FIELD_COUNT] = c->i32; params[DESC_FIELD_OFFSET] = c->i32; params[DESC_INSTANCE] = c->object_ptr; params[DESC_TRACE] = c->trace_fn; params[DESC_SERIALISE_TRACE] = c->trace_fn; params[DESC_SERIALISE] = c->serialise_fn; params[DESC_DESERIALISE] = c->trace_fn; params[DESC_DISPATCH] = c->dispatch_fn; params[DESC_FINALISE] = c->final_fn; params[DESC_EVENT_NOTIFY] = c->i32; params[DESC_TRAITS] = LLVMPointerType(LLVMArrayType(c->i32, traits), 0); params[DESC_FIELDS] = LLVMPointerType( LLVMArrayType(c->field_descriptor, fields), 0); params[DESC_VTABLE] = LLVMArrayType(c->void_ptr, vtable_size); LLVMStructSetBody(t->desc_type, params, DESC_LENGTH, false); t->desc = LLVMAddGlobal(c->module, t->desc_type, desc_name); LLVMSetGlobalConstant(t->desc, true); LLVMSetLinkage(t->desc, LLVMPrivateLinkage); }
static void set_method_external_nominal(reach_type_t* t, const char* name) { reach_method_name_t* n = reach_method_name(t, name); if(n != NULL) { size_t i = HASHMAP_BEGIN; reach_method_t* m; while((m = reach_methods_next(&n->r_methods, &i)) != NULL) { LLVMSetFunctionCallConv(m->func, LLVMCCallConv); LLVMSetLinkage(m->func, LLVMExternalLinkage); } } }
LLVMValueRef gen_string(compile_t* c, ast_t* ast) { ast_t* type = ast_type(ast); const char* name = ast_name(ast); size_t len = strlen(name); LLVMValueRef args[4]; args[0] = LLVMConstInt(c->i32, 0, false); args[1] = LLVMConstInt(c->i32, 0, false); LLVMValueRef str = LLVMConstStringInContext(c->context, name, (int)len, false); LLVMValueRef g_str = LLVMAddGlobal(c->module, LLVMTypeOf(str), "$strval"); LLVMSetLinkage(g_str, LLVMInternalLinkage); LLVMSetInitializer(g_str, str); LLVMSetGlobalConstant(g_str, true); LLVMValueRef str_ptr = LLVMConstInBoundsGEP(g_str, args, 2); gentype_t g; if(!gentype(c, type, &g)) return NULL; args[0] = g.desc; args[1] = LLVMConstInt(c->i64, len, false); args[2] = LLVMConstInt(c->i64, 0, false); args[3] = str_ptr; LLVMValueRef inst = LLVMConstNamedStruct(g.structure, args, 4); LLVMValueRef g_inst = LLVMAddGlobal(c->module, g.structure, "$string"); LLVMSetInitializer(g_inst, inst); LLVMSetGlobalConstant(g_inst, true); LLVMSetLinkage(g_inst, LLVMInternalLinkage); return g_inst; }
static LLVMValueRef make_trait_list(compile_t* c, gentype_t* g) { // The list is an array of integers. uint32_t count = trait_count(c, g); // If we have no traits, return a null pointer to a list. if(count == 0) return LLVMConstNull(LLVMPointerType(LLVMArrayType(c->i32, 0), 0)); // Sort the trait identifiers. size_t tid_size = count * sizeof(uint32_t); uint32_t* tid = (uint32_t*)pool_alloc_size(tid_size); reachable_type_t* t = reach_type(c->reachable, g->type_name); assert(t != NULL); size_t i = HASHMAP_BEGIN; size_t index = 0; reachable_type_t* provide; while((provide = reachable_type_cache_next(&t->subtypes, &i)) != NULL) tid[index++] = provide->type_id; qsort(tid, index, sizeof(uint32_t), cmp_uint32); index = unique_uint32(tid, index); // Create a constant array of trait identifiers. size_t list_size = index * sizeof(LLVMValueRef); LLVMValueRef* list = (LLVMValueRef*)pool_alloc_size(list_size); for(i = 0; i < index; i++) list[i] = LLVMConstInt(c->i32, tid[i], false); count = (uint32_t)index; LLVMValueRef trait_array = LLVMConstArray(c->i32, list, count); // Create a global to hold the array. const char* name = genname_traitlist(g->type_name); LLVMTypeRef type = LLVMArrayType(c->i32, count); LLVMValueRef global = LLVMAddGlobal(c->module, type, name); LLVMSetGlobalConstant(global, true); LLVMSetLinkage(global, LLVMInternalLinkage); LLVMSetInitializer(global, trait_array); pool_free_size(tid_size, tid); pool_free_size(list_size, list); return global; }
static void make_global_descriptor(compile_t* c, gentype_t* g) { // Fetch or create a descriptor type. if(g->underlying == TK_TUPLETYPE) g->field_count = (int)ast_childcount(g->ast); // Check for an existing descriptor. g->desc_type = gendesc_type(c, g); g->desc = LLVMGetNamedGlobal(c->module, g->desc_name); if(g->desc != NULL) return; g->desc = LLVMAddGlobal(c->module, g->desc_type, g->desc_name); LLVMSetGlobalConstant(g->desc, true); LLVMSetLinkage(g->desc, LLVMInternalLinkage); }
/** * 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; }
LLVMValueRef codegen_addfun(compile_t* c, const char* name, LLVMTypeRef type, bool pony_abi) { // Add the function and set the calling convention and the linkage type. LLVMValueRef fun = LLVMAddFunction(c->module, name, type); LLVMSetFunctionCallConv(fun, c->callconv); LLVMSetLinkage(fun, c->linkage); LLVMSetUnnamedAddr(fun, true); if(pony_abi) { LLVMValueRef md = LLVMMDNodeInContext(c->context, NULL, 0); LLVMSetMetadataStr(fun, "pony.abi", md); } LLVMValueRef arg = LLVMGetFirstParam(fun); uint32_t i = 1; while(arg != NULL) { LLVMTypeRef type = LLVMTypeOf(arg); if(LLVMGetTypeKind(type) == LLVMPointerTypeKind) { LLVMTypeRef elem = LLVMGetElementType(type); if(LLVMGetTypeKind(elem) == LLVMStructTypeKind) { size_t size = (size_t)LLVMABISizeOfType(c->target_data, elem); #if PONY_LLVM >= 309 LLVM_DECLARE_ATTRIBUTEREF(deref_attr, dereferenceable, size); LLVMAddAttributeAtIndex(fun, i, deref_attr); #else LLVMSetDereferenceable(fun, i, size); #endif } } arg = LLVMGetNextParam(arg); i++; } return fun; }
LLVMValueRef gen_vecdef(struct node *ast) { LLVMValueRef global, array, init, *ival_list; struct node *n; int size, initsize, i; initsize = count_chain(ast->three); if (ast->two) size = LLVMConstIntGetZExtValue(codegen(ast->two)); else size = 0; if (initsize > size) size = initsize; ival_list = calloc(sizeof(LLVMValueRef), size); if (size > 0 && ival_list == NULL) generror("out of memory"); for (i = 0, n = ast->three; i < initsize; i++, n = n->two) /* TODO: handle NAMES (convert global pointer to int) */ ival_list[initsize - i - 1] = codegen(n->one); for (i = initsize; i < size; i++) ival_list[i] = CONST(0); global = find_or_add_global(ast->one->val); array = LLVMAddGlobal(module, TYPE_ARRAY(size), ".gvec"); LLVMSetLinkage(array, LLVMPrivateLinkage); if (initsize) init = LLVMConstArray(TYPE_INT, ival_list, size); else init = LLVMConstNull(TYPE_ARRAY(size)); LLVMSetInitializer(array, init); LLVMSetInitializer(global, LLVMBuildPtrToInt(builder, array, TYPE_INT, "")); return NULL; }
static LLVMValueRef make_type_id(compile_t* c, const char* type_name) { // Generate a named constant for the type that is set to a unique integer // value for that type. const char* name = genname_typeid(type_name); LLVMValueRef global = LLVMGetNamedGlobal(c->module, name); // Return the constant initialiser, not the global. if(global != NULL) return LLVMGetInitializer(global); global = LLVMAddGlobal(c->module, c->i32, name); LLVMSetGlobalConstant(global, true); LLVMSetLinkage(global, LLVMInternalLinkage); LLVMValueRef id = LLVMConstInt(c->i32, c->next_type_id++, false); LLVMSetInitializer(global, id); return id; }
static void set_method_external_interface(reach_type_t* t, const char* name) { set_method_external_nominal(t, name); size_t i = HASHMAP_BEGIN; reach_type_t* sub; while((sub = reach_type_cache_next(&t->subtypes, &i)) != NULL) { reach_method_name_t* n = reach_method_name(sub, name); if(n == NULL) continue; size_t j = HASHMAP_BEGIN; reach_method_t* m; while((m = reach_methods_next(&n->r_methods, &j)) != NULL) { LLVMSetFunctionCallConv(m->func, LLVMCCallConv); LLVMSetLinkage(m->func, LLVMExternalLinkage); } } }
static LLVMValueRef make_str(const char *str) { LLVMValueRef global, strval, chars[MAX_STRSIZE]; const char *p; int size = 0; /* Skip leading " */ p = str + 1; while (p && size < MAX_STRSIZE - 1) chars[size++] = CONST(pack_char(&p)); chars[size++] = CONST(EOT); global = LLVMAddGlobal(module, TYPE_ARRAY(size), ".gstr"); LLVMSetLinkage(global, LLVMPrivateLinkage); strval = LLVMConstArray(TYPE_INT, chars, size); LLVMSetInitializer(global, strval); return lvalue_to_rvalue(global); }
void genprim_array_serialise_trace(compile_t* c, reach_type_t* t) { // Generate the serialise_trace function. t->serialise_trace_fn = codegen_addfun(c, genname_serialise_trace(t->name), c->trace_type); codegen_startfun(c, t->serialise_trace_fn, NULL, NULL); LLVMSetFunctionCallConv(t->serialise_trace_fn, LLVMCCallConv); LLVMSetLinkage(t->serialise_trace_fn, LLVMExternalLinkage); LLVMValueRef ctx = LLVMGetParam(t->serialise_trace_fn, 0); LLVMValueRef arg = LLVMGetParam(t->serialise_trace_fn, 1); LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, t->use_type, ""); // Read the size. LLVMValueRef size = field_value(c, object, 1); // Calculate the size of the element type. ast_t* typeargs = ast_childidx(t->ast, 2); ast_t* typearg = ast_child(typeargs); reach_type_t* t_elem = reach_type(c->reach, typearg); size_t abisize = (size_t)LLVMABISizeOfType(c->target_data, t_elem->use_type); LLVMValueRef l_size = LLVMConstInt(c->intptr, abisize, false); // Reserve space for the array elements. LLVMValueRef pointer = field_value(c, object, 3); LLVMValueRef args[3]; args[0] = ctx; args[1] = pointer; args[2] = LLVMBuildMul(c->builder, size, l_size, ""); gencall_runtime(c, "pony_serialise_reserve", args, 3, ""); // Trace the array elements. trace_array_elements(c, t, ctx, object, pointer); LLVMBuildRetVoid(c->builder); codegen_finishfun(c); }
LLVMValueRef gen_string(compile_t* c, ast_t* ast) { const char* name = ast_name(ast); genned_string_t k; k.string = name; size_t index = HASHMAP_UNKNOWN; genned_string_t* string = genned_strings_get(&c->strings, &k, &index); if(string != NULL) return string->global; ast_t* type = ast_type(ast); pony_assert(is_literal(type, "String")); reach_type_t* t = reach_type(c->reach, type); compile_type_t* c_t = (compile_type_t*)t->c_type; size_t len = ast_name_len(ast); LLVMValueRef args[4]; args[0] = c_t->desc; args[1] = LLVMConstInt(c->intptr, len, false); args[2] = LLVMConstInt(c->intptr, len + 1, false); args[3] = codegen_string(c, name, len); LLVMValueRef inst = LLVMConstNamedStruct(c_t->structure, args, 4); LLVMValueRef g_inst = LLVMAddGlobal(c->module, c_t->structure, ""); LLVMSetInitializer(g_inst, inst); LLVMSetGlobalConstant(g_inst, true); LLVMSetLinkage(g_inst, LLVMPrivateLinkage); LLVMSetUnnamedAddr(g_inst, true); string = POOL_ALLOC(genned_string_t); string->string = name; string->global = g_inst; genned_strings_putindex(&c->strings, string, index); return g_inst; }
LLVMValueRef lp_declare_intrinsic(LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMTypeRef *arg_types, unsigned num_args) { LLVMTypeRef function_type; LLVMValueRef function; assert(!LLVMGetNamedFunction(module, name)); function_type = LLVMFunctionType(ret_type, arg_types, num_args, 0); function = LLVMAddFunction(module, name, function_type); LLVMSetFunctionCallConv(function, LLVMCCallConv); LLVMSetLinkage(function, LLVMExternalLinkage); assert(LLVMIsDeclaration(function)); return function; }
void genprim_array_trace(compile_t* c, reach_type_t* t) { codegen_startfun(c, t->trace_fn, NULL, NULL); LLVMSetFunctionCallConv(t->trace_fn, LLVMCCallConv); LLVMSetLinkage(t->trace_fn, LLVMExternalLinkage); LLVMValueRef ctx = LLVMGetParam(t->trace_fn, 0); LLVMValueRef arg = LLVMGetParam(t->trace_fn, 1); // Read the base pointer. LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, t->use_type, ""); LLVMValueRef pointer = field_value(c, object, 3); // Trace the base pointer. LLVMValueRef args[2]; args[0] = ctx; args[1] = pointer; gencall_runtime(c, "pony_trace", args, 2, ""); trace_array_elements(c, t, ctx, object, pointer); LLVMBuildRetVoid(c->builder); codegen_finishfun(c); }
static void make_global_instance(compile_t* c, reach_type_t* t) { // Not a primitive type. if(t->underlying != TK_PRIMITIVE) return; // No instance for machine word types. if(t->primitive != NULL) return; // Create a unique global instance. const char* inst_name = genname_instance(t->name); LLVMValueRef args[1]; args[0] = t->desc; LLVMValueRef value = LLVMConstNamedStruct(t->structure, args, 1); t->instance = LLVMAddGlobal(c->module, t->structure, inst_name); LLVMSetInitializer(t->instance, value); LLVMSetGlobalConstant(t->instance, true); LLVMSetLinkage(t->instance, LLVMPrivateLinkage); }
static void make_deserialise(compile_t* c, reach_type_t* t) { // Generate the deserialise function. t->deserialise_fn = codegen_addfun(c, genname_deserialise(t->name), c->trace_type); codegen_startfun(c, t->deserialise_fn, NULL, NULL); LLVMSetFunctionCallConv(t->deserialise_fn, LLVMCCallConv); LLVMSetLinkage(t->deserialise_fn, LLVMExternalLinkage); LLVMValueRef ctx = LLVMGetParam(t->deserialise_fn, 0); LLVMValueRef arg = LLVMGetParam(t->deserialise_fn, 1); LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, t->structure_ptr, ""); // At this point, the serialised contents have been copied to the allocated // object. deserialise(c, t, ctx, object); LLVMBuildRetVoid(c->builder); codegen_finishfun(c); }
static LLVMValueRef make_trait_list(compile_t* c, gentype_t* g) { // The list is an array of integers. uint32_t count = trait_count(c, g); LLVMTypeRef type = LLVMArrayType(c->i32, count); // If we have no traits, return a null pointer to a list. if(count == 0) return LLVMConstNull(LLVMPointerType(type, 0)); // Create a constant array of trait identifiers. size_t buf_size = count *sizeof(LLVMValueRef); LLVMValueRef* list = (LLVMValueRef*)pool_alloc_size(buf_size); reachable_type_t* t = reach_type(c->reachable, g->type_name); assert(t != NULL); size_t i = HASHMAP_BEGIN; size_t index = 0; reachable_type_t* provide; while((provide = reachable_type_cache_next(&t->subtypes, &i)) != NULL) list[index++] = make_type_id(c, provide->name); LLVMValueRef trait_array = LLVMConstArray(c->i32, list, count); // Create a global to hold the array. const char* name = genname_traitlist(g->type_name); LLVMValueRef global = LLVMAddGlobal(c->module, type, name); LLVMSetGlobalConstant(global, true); LLVMSetLinkage(global, LLVMInternalLinkage); LLVMSetInitializer(global, trait_array); pool_free_size(buf_size, list); return global; }