diff options
Diffstat (limited to 'src/tilde_proc.cpp')
| -rw-r--r-- | src/tilde_proc.cpp | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp index dbebae853..b60e797c3 100644 --- a/src/tilde_proc.cpp +++ b/src/tilde_proc.cpp @@ -1,3 +1,293 @@ +gb_internal TB_FunctionPrototype *cg_procedure_type_as_prototype(cgModule *m, Type *type) { + GB_ASSERT(type != nullptr); + type = base_type(type); + GB_ASSERT(type->kind == Type_Proc); + TypeProc *pt = &type->Proc; + + auto params = array_make<TB_PrototypeParam>(heap_allocator(), 0, pt->param_count); + if (pt->params) for (Entity *e : pt->params->Tuple.variables) { + TB_PrototypeParam param = {}; + + Type *t = core_type(e->type); + i64 sz = type_size_of(t); + switch (t->kind) { + case Type_Basic: + switch (t->Basic.kind) { + case Basic_bool: + case Basic_b8: + case Basic_b16: + case Basic_b32: + case Basic_b64: + case Basic_i8: + case Basic_u8: + case Basic_i16: + case Basic_u16: + case Basic_i32: + case Basic_u32: + case Basic_i64: + case Basic_u64: + case Basic_i128: + case Basic_u128: + case Basic_rune: + case Basic_int: + case Basic_uint: + case Basic_uintptr: + param.dt = TB_TYPE_INTN(cast(u16)(8*sz)); + break; + + case Basic_f16: param.dt = TB_TYPE_I16; break; + case Basic_f32: param.dt = TB_TYPE_F32; break; + case Basic_f64: param.dt = TB_TYPE_F64; break; + + case Basic_complex32: + case Basic_complex64: + case Basic_complex128: + case Basic_quaternion64: + case Basic_quaternion128: + case Basic_quaternion256: + param.dt = TB_TYPE_PTR; + break; + + + case Basic_rawptr: + param.dt = TB_TYPE_PTR; + break; + case Basic_string: // ^u8 + int + param.dt = TB_TYPE_PTR; + break; + case Basic_cstring: // ^u8 + param.dt = TB_TYPE_PTR; + break; + case Basic_any: // rawptr + ^Type_Info + param.dt = TB_TYPE_PTR; + break; + + case Basic_typeid: + param.dt = TB_TYPE_INTN(cast(u16)(8*sz)); + break; + + // Endian Specific Types + case Basic_i16le: + case Basic_u16le: + case Basic_i32le: + case Basic_u32le: + case Basic_i64le: + case Basic_u64le: + case Basic_i128le: + case Basic_u128le: + case Basic_i16be: + case Basic_u16be: + case Basic_i32be: + case Basic_u32be: + case Basic_i64be: + case Basic_u64be: + case Basic_i128be: + case Basic_u128be: + param.dt = TB_TYPE_INTN(cast(u16)(8*sz)); + break; + + case Basic_f16le: param.dt = TB_TYPE_I16; break; + case Basic_f32le: param.dt = TB_TYPE_F32; break; + case Basic_f64le: param.dt = TB_TYPE_F64; break; + + case Basic_f16be: param.dt = TB_TYPE_I16; break; + case Basic_f32be: param.dt = TB_TYPE_F32; break; + case Basic_f64be: param.dt = TB_TYPE_F64; break; + } + + case Type_Pointer: + case Type_MultiPointer: + case Type_Proc: + param.dt = TB_TYPE_PTR; + break; + + default: + switch (sz) { + case 1: param.dt = TB_TYPE_I8; break; + case 2: param.dt = TB_TYPE_I16; break; + case 4: param.dt = TB_TYPE_I32; break; + case 8: param.dt = TB_TYPE_I64; break; + default: + param.dt = TB_TYPE_PTR; + break; + } + } + + if (param.dt.width != 0) { + if (is_blank_ident(e->token)) { + param.name = alloc_cstring(temporary_allocator(), e->token.string); + } + array_add(¶ms, param); + } + } + + auto results = array_make<TB_PrototypeParam>(heap_allocator(), 0, pt->result_count); + // if (pt->results) for (Entity *e : pt->params->Tuple.variables) { + // // TODO(bill): + // } + + + return tb_prototype_create(m->mod, TB_CDECL, params.count, params.data, results.count, results.data, pt->c_vararg); +} + +gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool ignore_body=false) { + GB_ASSERT(entity != nullptr); + GB_ASSERT(entity->kind == Entity_Procedure); + if (!entity->Procedure.is_foreign) { + if ((entity->flags & EntityFlag_ProcBodyChecked) == 0) { + GB_PANIC("%.*s :: %s (was parapoly: %d %d)", LIT(entity->token.string), type_to_string(entity->type), is_type_polymorphic(entity->type, true), is_type_polymorphic(entity->type, false)); + } + } + + String link_name = cg_get_entity_name(m, entity); + + cgProcedure *p = nullptr; + { + StringHashKey key = string_hash_string(link_name); + cgValue *found = string_map_get(&m->members, key); + if (found) { + cg_add_entity(m, entity, *found); + p = string_map_must_get(&m->procedures, key); + if (!ignore_body && p->func != nullptr) { + return nullptr; + } + } + } + + if (p == nullptr) { + p = gb_alloc_item(permanent_allocator(), cgProcedure); + } + + p->module = m; + p->entity = entity; + p->name = link_name; + + DeclInfo *decl = entity->decl_info; + + ast_node(pl, ProcLit, decl->proc_lit); + Type *pt = base_type(entity->type); + GB_ASSERT(pt->kind == Type_Proc); + + p->type = entity->type; + p->type_expr = decl->type_expr; + p->body = pl->body; + p->inlining = pl->inlining; + p->is_foreign = entity->Procedure.is_foreign; + p->is_export = entity->Procedure.is_export; + p->is_entry_point = false; + + gbAllocator a = heap_allocator(); + p->children.allocator = a; + // p->defer_stmts.allocator = a; + // p->blocks.allocator = a; + // p->branch_blocks.allocator = a; + p->context_stack.allocator = a; + p->scope_stack.allocator = a; + // map_init(&p->tuple_fix_map, 0); + + TB_Linkage linkage = TB_LINKAGE_PRIVATE; + if (p->is_export) { + linkage = TB_LINKAGE_PUBLIC; + } else if (p->is_foreign || ignore_body) { + if (ignore_body) { + linkage = TB_LINKAGE_PUBLIC; + } + p->symbol = cast(TB_Symbol *)tb_extern_create(m->mod, link_name.len, cast(char const *)link_name.text, TB_EXTERNAL_SO_LOCAL); + } + + if (p->symbol == nullptr) { + p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage, TB_COMDAT_NONE); + tb_function_set_prototype(p->func, cg_procedure_type_as_prototype(m, p->type), tb_default_arena()); + p->symbol = cast(TB_Symbol *)p->func; + } + + cgValue proc_value = cg_value(p->symbol, p->type); + cg_add_entity(m, entity, proc_value); + cg_add_member(m, p->name, proc_value); + cg_add_procedure_value(m, p); + + + return p; +} + +gb_internal cgProcedure *cg_procedure_create_dummy(cgModule *m, String const &link_name, Type *type) { + auto *prev_found = string_map_get(&m->members, link_name); + GB_ASSERT_MSG(prev_found == nullptr, "failed to create dummy procedure for: %.*s", LIT(link_name)); + + cgProcedure *p = gb_alloc_item(permanent_allocator(), cgProcedure); + + p->module = m; + p->name = link_name; + + p->type = type; + p->type_expr = nullptr; + p->body = nullptr; + p->tags = 0; + p->inlining = ProcInlining_none; + p->is_foreign = false; + p->is_export = false; + p->is_entry_point = false; + + gbAllocator a = heap_allocator(); + p->children.allocator = a; + // p->defer_stmts.allocator = a; + // p->blocks.allocator = a; + // p->branch_blocks.allocator = a; + p->scope_stack.allocator = a; + p->context_stack.allocator = a; + // map_init(&p->tuple_fix_map, 0); + + + TB_Linkage linkage = TB_LINKAGE_PRIVATE; + + p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage, TB_COMDAT_NONE); + tb_function_set_prototype(p->func, cg_procedure_type_as_prototype(m, p->type), tb_default_arena()); + p->symbol = cast(TB_Symbol *)p->func; + + cgValue proc_value = cg_value(p->symbol, p->type); + cg_add_member(m, p->name, proc_value); + cg_add_procedure_value(m, p); + + return p; +} + +gb_internal void cg_procedure_begin(cgProcedure *p) { + if (p == nullptr || p->func == nullptr) { + return; + } +} + +gb_internal void cg_procedure_end(cgProcedure *p) { + if (p == nullptr || p->func == nullptr) { + return; + } + tb_inst_ret(p->func, 0, nullptr); + if (p->name == "main") { + TB_Arena *arena = tb_default_arena(); + defer (arena->free(arena)); + TB_FuncOpt *opt = tb_funcopt_enter(p->func, arena); + defer (tb_funcopt_exit(opt)); + tb_funcopt_print(opt); + } + tb_module_compile_function(p->module->mod, p->func, TB_ISEL_FAST); +} + +gb_internal void cg_procedure_generate(cgProcedure *p) { + if (p->body == nullptr) { + return; + } + cg_procedure_begin(p); + defer (cg_procedure_end(p)); + + if (p->name != "bug.main" && + p->name != "main") { + return; + } + cg_build_stmt(p, p->body); +} + + + gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e) { GB_ASSERT(is_type_proc(e->type)); e = strip_entity_wrapping(e); |