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; }
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 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; }
static void *find_or_add_global(const char *name) { LLVMValueRef global; global = LLVMGetNamedGlobal(module, name); if (global == NULL) global = LLVMAddGlobal(module, TYPE_INT, name); 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; }
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); }
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); }
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); }
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 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; }
while(count < len) { t = reach_types_next(&c->reach->types, &i); pony_assert(t != NULL); if(t->is_trait || (t->underlying == TK_STRUCT)) continue; uint32_t type_id = t->type_id; if((type_id % 4) == 0) { size_t type_size = (size_t)LLVMABISizeOfType(c->target_data, t->use_type); args[type_id >> 2] = LLVMConstInt(c->i32, type_size, false); count++; } } LLVMTypeRef type = LLVMArrayType(c->i32, len); LLVMValueRef table = LLVMAddGlobal(c->module, type, "__NumSizeTable"); LLVMValueRef value = LLVMConstArray(c->i32, args, len); LLVMSetInitializer(table, value); LLVMSetGlobalConstant(table, true); LLVMSetAlignment(table, 4); LLVMSetLinkage(table, LLVMPrivateLinkage); ponyint_pool_free_size(size, args); return table; }