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); }
void reach_dump(reach_t* r) { printf("REACH\n"); size_t i = HASHMAP_BEGIN; reach_type_t* t; while((t = reach_types_next(&r->types, &i)) != NULL) { printf(" %d: %s, %s\n", t->type_id, t->name, t->mangle); size_t j = HASHMAP_BEGIN; reach_method_name_t* n; printf(" size: " __zu "\n", t->abi_size); printf(" vtable: %d\n", t->vtable_size); while((n = reach_method_names_next(&t->methods, &j)) != NULL) { size_t k = HASHMAP_BEGIN; reach_method_t* m; while((m = reach_mangled_next(&n->r_mangled, &k)) != NULL) printf(" %d: %s\n", m->vtable_index, m->mangled_name); } j = HASHMAP_BEGIN; reach_type_t* t2; while((t2 = reach_type_cache_next(&t->subtypes, &j)) != NULL) { printf(" %s\n", t2->name); } } }
static void add_traits_to_type(reach_t* r, reach_type_t* t, pass_opt_t* opt) { size_t i = HASHMAP_BEGIN; reach_type_t* t2; while((t2 = reach_types_next(&r->types, &i)) != NULL) { if(ast_id(t2->ast) != TK_NOMINAL) continue; ast_t* def = (ast_t*)ast_data(t2->ast); switch(ast_id(def)) { case TK_INTERFACE: case TK_TRAIT: if(is_subtype(t->ast, t2->ast, NULL, opt)) { reach_type_cache_put(&t->subtypes, t2); reach_type_cache_put(&t2->subtypes, t); add_methods_to_type(r, t2, t, opt); } break; default: {} } } }
static void print_types(compile_t* c, FILE* fp, printbuf_t* buf) { size_t i = HASHMAP_BEGIN; reach_type_t* t; while((t = reach_types_next(&c->reach->types, &i)) != NULL) { // Print the docstring if we have one. ast_t* def = (ast_t*)ast_data(t->ast); if (def != NULL) { ast_t* docstring = ast_childidx(def, 6); if(ast_id(docstring) == TK_STRING) fprintf(fp, "/*\n%s*/\n", ast_name(docstring)); } if(!is_pointer(t->ast) && !is_maybe(t->ast) && !is_machine_word(t->ast)) { // Forward declare an opaque type. fprintf(fp, "typedef struct %s %s;\n\n", t->name, t->name); // Function signature for the allocator. printbuf(buf, "/* Allocate a %s without initialising it. */\n%s* %s_Alloc();\n\n", t->name, t->name, t->name ); } print_methods(c, t, buf); } }
LLVMValueRef gen_numeric_size_table(compile_t* c) { uint32_t len = c->reach->numeric_type_count; if(len == 0) return NULL; size_t size = len * sizeof(LLVMValueRef); LLVMValueRef* args = (LLVMValueRef*)ponyint_pool_alloc_size(size); uint32_t count = 0; reach_type_t* t; size_t i = HASHMAP_BEGIN; 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++; } }
static bool need_primitive_call(compile_t* c, const char* method) { size_t i = HASHMAP_BEGIN; reach_type_t* t; while((t = reach_types_next(&c->reach->types, &i)) != NULL) { if(t->underlying != TK_PRIMITIVE) continue; reach_method_name_t* n = reach_method_name(t, method); if(n == NULL) continue; return true; } return false; }
static void add_types_to_trait(reach_t* r, reach_type_t* t, pass_opt_t* opt) { size_t i = HASHMAP_BEGIN; reach_type_t* t2; ast_t* def = (ast_t*)ast_data(t->ast); bool interface = ast_id(def) == TK_INTERFACE; while((t2 = reach_types_next(&r->types, &i)) != NULL) { if(ast_id(t2->ast) != TK_NOMINAL) continue; ast_t* def2 = (ast_t*)ast_data(t2->ast); switch(ast_id(def2)) { case TK_INTERFACE: { // Use the same typeid. if(interface && is_eqtype(t->ast, t2->ast, NULL, opt)) t->type_id = t2->type_id; break; } case TK_PRIMITIVE: case TK_CLASS: case TK_ACTOR: if(is_subtype(t2->ast, t->ast, NULL, opt)) { reach_type_cache_put(&t->subtypes, t2); reach_type_cache_put(&t2->subtypes, t); add_methods_to_type(r, t, t2, opt); } break; default: {} } } }
static void primitive_call(compile_t* c, const char* method) { size_t i = HASHMAP_BEGIN; reach_type_t* t; while((t = reach_types_next(&c->reach->types, &i)) != NULL) { if(t->underlying != TK_PRIMITIVE) continue; reach_method_t* m = reach_method(t, TK_NONE, method, NULL); if(m == NULL) continue; LLVMValueRef value = codegen_call(c, m->func, &t->instance, 1); if(c->str__final == method) LLVMSetInstructionCallConv(value, LLVMCCallConv); } }
bool gentypes(compile_t* c) { reach_type_t* t; size_t i; genprim_builtins(c); if(c->opt->verbosity >= VERBOSITY_INFO) fprintf(stderr, " Data prototypes\n"); i = HASHMAP_BEGIN; while((t = reach_types_next(&c->reach->types, &i)) != NULL) { if(!make_opaque_struct(c, t)) return false; gendesc_type(c, t); make_debug_info(c, t); make_box_type(c, t); make_dispatch(c, t); gentrace_prototype(c, t); } gendesc_table(c); if(c->opt->verbosity >= VERBOSITY_INFO) fprintf(stderr, " Data types\n"); i = HASHMAP_BEGIN; while((t = reach_types_next(&c->reach->types, &i)) != NULL) { if(!make_struct(c, t)) return false; make_global_instance(c, t); } if(c->opt->verbosity >= VERBOSITY_INFO) fprintf(stderr, " Function prototypes\n"); i = HASHMAP_BEGIN; while((t = reach_types_next(&c->reach->types, &i)) != NULL) { // The ABI size for machine words and tuples is the boxed size. if(t->structure != NULL) t->abi_size = (size_t)LLVMABISizeOfType(c->target_data, t->structure); make_debug_final(c, t); make_pointer_methods(c, t); if(!genfun_method_sigs(c, t)) return false; } if(c->opt->verbosity >= VERBOSITY_INFO) fprintf(stderr, " Functions\n"); i = HASHMAP_BEGIN; while((t = reach_types_next(&c->reach->types, &i)) != NULL) { if(!genfun_method_bodies(c, t)) return false; } if(c->opt->verbosity >= VERBOSITY_INFO) fprintf(stderr, " Descriptors\n"); i = HASHMAP_BEGIN; while((t = reach_types_next(&c->reach->types, &i)) != NULL) { if(!make_trace(c, t)) return false; if(!genserialise(c, t)) return false; gendesc_init(c, t); } return true; }