void gendesc_table(compile_t* c) { uint32_t len = c->reach->next_type_id; size_t size = len * sizeof(LLVMValueRef); LLVMValueRef* args = (LLVMValueRef*)ponyint_pool_alloc_size(size); reach_type_t* t; size_t i = HASHMAP_BEGIN; while((t = reach_types_next(&c->reach->types, &i)) != NULL) { LLVMValueRef desc; if(t->desc != NULL) desc = LLVMBuildBitCast(c->builder, t->desc, c->descriptor_ptr, ""); else desc = LLVMConstNull(c->descriptor_ptr); args[t->type_id] = desc; } LLVMTypeRef type = LLVMArrayType(c->descriptor_ptr, len); LLVMValueRef table = LLVMAddGlobal(c->module, type, "__DescTable"); LLVMValueRef value = LLVMConstArray(c->descriptor_ptr, args, len); LLVMSetInitializer(table, value); LLVMSetGlobalConstant(table, true); LLVMValueRef table_size = LLVMAddGlobal(c->module, c->intptr, "__DescTableSize"); LLVMSetInitializer(table_size, LLVMConstInt(c->intptr, len, false)); LLVMSetGlobalConstant(table_size, true); ponyint_pool_free_size(size, args); }
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 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; }
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 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); }
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); }
void registerHeap(SymbolTable *TyTable, LLVMContextRef Con) { char *Name, Buf[] = "struct.Heap", BufRA[] = "struct.RA"; Name = (char*) malloc(strlen(Buf) * sizeof(char)); strcpy(Name, Buf); RAType = symTableFindGlobal(TyTable, BufRA); HeapType = LLVMStructCreateNamed(Con, Name); symTableInsertGlobal(TyTable, Name, HeapType); LLVMTypeRef AttrTy[] = { LLVMPointerType(RAType, 0), LLVMPointerType(HeapType, 0) }; LLVMStructSetBody(HeapType, AttrTy, 2, 0); // Initializing Head of Heap. HeapHead = LLVMAddGlobal(Module, LLVMPointerType(HeapType, 0), "global.HeapHead"); LLVMTypeRef HeapHeadConType = LLVMGetElementType(LLVMTypeOf(HeapHead)); LLVMSetInitializer(HeapHead, LLVMConstPointerNull(HeapHeadConType)); // Defining functions. createPushHeapFunction(); createPopHeapFunction(); }
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 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; }
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; }
LLVMValueRef gen_simpledef(struct node *ast) { LLVMValueRef global, init; global = find_or_add_global(ast->one->val); init = LLVMConstShl(codegen(ast->two), CONST(WORDPOW)); LLVMSetInitializer(global, init); return NULL; }
static LLVMValueRef translateStringLit(ASTNode *Node) { int Length = strlen(Node->Value); LLVMValueRef GlobVar = LLVMAddGlobal(Module, LLVMArrayType(LLVMInt8Type(), Length+1), "global.var"); LLVMSetInitializer(GlobVar, LLVMConstString(Node->Value, Length, 0)); LLVMValueRef LocalVar = LLVMBuildAlloca(Builder, LLVMArrayType(LLVMInt8Type(), Length+1), "local.string."); LLVMValueRef LocalI8 = LLVMBuildBitCast(Builder, LocalVar, LLVMPointerType(LLVMInt8Type(), 0), ""); copyMemory(LocalI8, GlobVar, getSConstInt(Length+1)); return wrapValue(LocalI8); }
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 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 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); }
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; }
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 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; }
LLVMValueRef gen_funcdef(struct node *ast) { LLVMValueRef global, func, retval; LLVMTypeRef func_type, *param_types; LLVMBasicBlockRef body_block, ret_block; int param_count, i; if (hcreate(SYMTAB_SIZE) == 0) generror(">s"); param_count = count_chain(ast->two); param_types = calloc(sizeof(LLVMTypeRef), param_count); if (param_count > 0 && param_types == NULL) generror("out of memory"); for (i = 0; i < param_count; i++) param_types[i] = TYPE_INT; func_type = LLVMFunctionType(TYPE_INT, param_types, param_count, 0); func = LLVMAddFunction(module, ".gfunc", func_type); LLVMSetLinkage(func, LLVMPrivateLinkage); /* TODO: How to specify stack alignment? Should be 16 bytes */ LLVMAddFunctionAttr(func, LLVMStackAlignment); global = find_or_add_global(ast->one->val); LLVMSetInitializer(global, LLVMBuildPtrToInt(builder, func, TYPE_INT, "")); body_block = LLVMAppendBasicBlock(func, ""); ret_block = LLVMAppendBasicBlock(func, ""); LLVMPositionBuilderAtEnd(builder, body_block); retval = LLVMBuildAlloca(builder, TYPE_INT, ""); LLVMBuildStore(builder, CONST(0), retval); symtab_enter(ast->one->val, global); symtab_enter(".return", ret_block); symtab_enter(".retval", retval); label_count = 0; predeclare_labels(ast->three); if (ast->two) codegen(ast->two); codegen(ast->three); LLVMBuildBr(builder, ret_block); /* TODO: Untangle out-of-order blocks */ LLVMPositionBuilderAtEnd(builder, ret_block); LLVMBuildRet(builder, LLVMBuildLoad(builder, retval, "")); LLVMMoveBasicBlockAfter(ret_block, LLVMGetLastBasicBlock(func)); /* TODO: Handle failed verification and print internal compiler error */ LLVMVerifyFunction(func, LLVMPrintMessageAction); hdestroy(); return NULL; }