diff options
| author | gingerBill <bill@gingerbill.org> | 2023-07-14 11:58:18 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2023-07-14 11:58:18 +0100 |
| commit | 7cd2d14b6410a17783020cea390f2be9534fa432 (patch) | |
| tree | 27cc6c71036a2c7e9f907a9f99038c7938a7a89b /src/tilde_backend.cpp | |
| parent | fc5abfd68b3b4fb079fe61d72ad2b10cf24df455 (diff) | |
Very start of working on Tilde Backend for Odin
Diffstat (limited to 'src/tilde_backend.cpp')
| -rw-r--r-- | src/tilde_backend.cpp | 785 |
1 files changed, 750 insertions, 35 deletions
diff --git a/src/tilde_backend.cpp b/src/tilde_backend.cpp index 63466e132..abaf0b825 100644 --- a/src/tilde_backend.cpp +++ b/src/tilde_backend.cpp @@ -1,23 +1,716 @@ -#if defined(GB_SYSTEM_WINDOWS) - #pragma warning(push) - #pragma warning(disable: 4200) - #pragma warning(disable: 4201) - #define restrict gb_restrict -#endif +#include "tilde_backend.hpp" -#include "tilde/tb.h" +gb_internal cgValue cg_value(TB_Global *g, Type *type) { + return cg_value((TB_Symbol *)g, type); +} +gb_internal cgValue cg_value(TB_External *e, Type *type) { + return cg_value((TB_Symbol *)e, type); +} +gb_internal cgValue cg_value(TB_Function *f, Type *type) { + return cg_value((TB_Symbol *)f, type); +} +gb_internal cgValue cg_value(TB_Symbol *s, Type *type) { + cgValue v = {}; + v.kind = cgValue_Symbol; + v.type = type; + v.symbol = s; + return v; +} +gb_internal cgValue cg_value(TB_Node *node, Type *type) { + cgValue v = {}; + v.kind = cgValue_Value; + v.type = type; + v.node = node; + return v; +} +gb_internal cgValue cg_lvalue_addr(TB_Node *node, Type *type) { + GB_ASSERT(node->dt.type == TB_PTR); + cgValue v = {}; + v.kind = cgValue_Addr; + v.type = type; + v.node = node; + return v; +} -#if defined(GB_SYSTEM_WINDOWS) - #pragma warning(pop) -#endif +gb_internal cgAddr cg_addr(cgValue const &value) { + cgAddr addr = {}; + addr.kind = cgAddr_Default; + addr.addr = value; + if (addr.addr.kind == cgValue_Addr) { + GB_ASSERT(addr.addr.node != nullptr); + addr.addr.kind = cgValue_Value; + addr.addr.type = alloc_type_pointer(addr.addr.type); + } + return addr; +} + + +gb_internal void cg_add_entity(cgModule *m, Entity *e, cgValue const &val) { + if (e) { + rw_mutex_lock(&m->values_mutex); + map_set(&m->values, e, val); + rw_mutex_unlock(&m->values_mutex); + } +} + +gb_internal void cg_add_member(cgModule *m, String const &name, cgValue const &val) { + if (name.len > 0) { + rw_mutex_lock(&m->values_mutex); + string_map_set(&m->members, name, val); + rw_mutex_unlock(&m->values_mutex); + } +} + +gb_internal void cg_add_procedure_value(cgModule *m, cgProcedure *p) { + rw_mutex_lock(&m->values_mutex); + if (p->entity != nullptr) { + map_set(&m->procedure_values, p->func, p->entity); + } + string_map_set(&m->procedures, p->name, p); + rw_mutex_unlock(&m->values_mutex); + +} + +gb_internal isize cg_type_info_index(CheckerInfo *info, Type *type, bool err_on_not_found=true) { + auto *set = &info->minimum_dependency_type_info_set; + isize index = type_info_index(info, type, err_on_not_found); + if (index >= 0) { + auto *found = map_get(set, index); + if (found) { + GB_ASSERT(*found >= 0); + return *found + 1; + } + } + if (err_on_not_found) { + GB_PANIC("NOT FOUND lb_type_info_index %s @ index %td", type_to_string(type), index); + } + return -1; +} + +gb_internal void cg_create_global_variables(cgModule *m) { + if (build_context.no_rtti) { + return; + } + + CheckerInfo *info = m->info; + { // Add type info data + isize max_type_info_count = info->minimum_dependency_type_info_set.count+1; + // gb_printf_err("max_type_info_count: %td\n", max_type_info_count); + Type *t = alloc_type_array(t_type_info, max_type_info_count); + + TB_Global *g = tb_global_create(m->mod, CG_TYPE_INFO_DATA_NAME, nullptr, TB_LINKAGE_PRIVATE); + tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, max_type_info_count); + + cgValue value = cg_value(g, alloc_type_pointer(t)); + cg_global_type_info_data_entity = alloc_entity_variable(nullptr, make_token_ident(CG_TYPE_INFO_DATA_NAME), t, EntityState_Resolved); + cg_add_entity(m, cg_global_type_info_data_entity, value); + } + + { // Type info member buffer + // NOTE(bill): Removes need for heap allocation by making it global memory + isize count = 0; + + for (Type *t : m->info->type_info_types) { + isize index = cg_type_info_index(m->info, t, false); + if (index < 0) { + continue; + } + + switch (t->kind) { + case Type_Union: + count += t->Union.variants.count; + break; + case Type_Struct: + count += t->Struct.fields.count; + break; + case Type_Tuple: + count += t->Tuple.variables.count; + break; + } + } + + if (count > 0) { + { + char const *name = CG_TYPE_INFO_TYPES_NAME; + Type *t = alloc_type_array(t_type_info_ptr, count); + TB_Global *g = tb_global_create(m->mod, name, nullptr, TB_LINKAGE_PRIVATE); + tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count); + cg_global_type_info_member_types = cg_addr(cg_value(g, alloc_type_pointer(t))); + + } + { + char const *name = CG_TYPE_INFO_NAMES_NAME; + Type *t = alloc_type_array(t_string, count); + TB_Global *g = tb_global_create(m->mod, name, nullptr, TB_LINKAGE_PRIVATE); + tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count); + cg_global_type_info_member_names = cg_addr(cg_value(g, alloc_type_pointer(t))); + } + { + char const *name = CG_TYPE_INFO_OFFSETS_NAME; + Type *t = alloc_type_array(t_uintptr, count); + TB_Global *g = tb_global_create(m->mod, name, nullptr, TB_LINKAGE_PRIVATE); + tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count); + cg_global_type_info_member_offsets = cg_addr(cg_value(g, alloc_type_pointer(t))); + } + + { + char const *name = CG_TYPE_INFO_USINGS_NAME; + Type *t = alloc_type_array(t_bool, count); + TB_Global *g = tb_global_create(m->mod, name, nullptr, TB_LINKAGE_PRIVATE); + tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count); + cg_global_type_info_member_usings = cg_addr(cg_value(g, alloc_type_pointer(t))); + } + + { + char const *name = CG_TYPE_INFO_TAGS_NAME; + Type *t = alloc_type_array(t_string, count); + TB_Global *g = tb_global_create(m->mod, name, nullptr, TB_LINKAGE_PRIVATE); + tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count); + cg_global_type_info_member_tags = cg_addr(cg_value(g, alloc_type_pointer(t))); + } + } + } +} + +cgModule *cg_module_create(Checker *c) { + cgModule *m = gb_alloc_item(permanent_allocator(), cgModule); + + m->checker = c; + m->info = &c->info; -bool tb_generate_code(Checker *c) { TB_FeatureSet feature_set = {}; bool is_jit = false; - TB_Module *m = tb_module_create(TB_ARCH_X86_64, TB_SYSTEM_WINDOWS, &feature_set, is_jit); - defer (tb_module_destroy(m)); - tb_module_set_tls_index(m, "_tls_index"); + m->mod = tb_module_create(TB_ARCH_X86_64, TB_SYSTEM_WINDOWS, &feature_set, is_jit); + tb_module_set_tls_index(m->mod, "_tls_index"); + + map_init(&m->values); + array_init(&m->procedures_to_generate, heap_allocator()); + + return m; +} + +void cg_module_destroy(cgModule *m) { + map_destroy(&m->values); + array_free(&m->procedures_to_generate); + + tb_module_destroy(m->mod); +} + +gb_internal String cg_set_nested_type_name_ir_mangled_name(Entity *e, cgProcedure *p) { + // NOTE(bill, 2020-03-08): A polymorphic procedure may take a nested type declaration + // and as a result, the declaration does not have time to determine what it should be + + GB_ASSERT(e != nullptr && e->kind == Entity_TypeName); + if (e->TypeName.ir_mangled_name.len != 0) { + return e->TypeName.ir_mangled_name; + } + GB_ASSERT((e->scope->flags & ScopeFlag_File) == 0); + + if (p == nullptr) { + Entity *proc = nullptr; + if (e->parent_proc_decl != nullptr) { + proc = e->parent_proc_decl->entity; + } else { + Scope *scope = e->scope; + while (scope != nullptr && (scope->flags & ScopeFlag_Proc) == 0) { + scope = scope->parent; + } + GB_ASSERT(scope != nullptr); + GB_ASSERT(scope->flags & ScopeFlag_Proc); + proc = scope->procedure_entity; + } + GB_ASSERT(proc->kind == Entity_Procedure); + if (proc->cg_procedure != nullptr) { + p = proc->cg_procedure; + } + } + + // NOTE(bill): Generate a new name + // parent_proc.name-guid + String ts_name = e->token.string; + + if (p != nullptr) { + isize name_len = p->name.len + 1 + ts_name.len + 1 + 10 + 1; + char *name_text = gb_alloc_array(permanent_allocator(), char, name_len); + u32 guid = 1+p->module->nested_type_name_guid.fetch_add(1); + name_len = gb_snprintf(name_text, name_len, "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s-%u", LIT(p->name), LIT(ts_name), guid); + + String name = make_string(cast(u8 *)name_text, name_len-1); + e->TypeName.ir_mangled_name = name; + return name; + } else { + // NOTE(bill): a nested type be required before its parameter procedure exists. Just give it a temp name for now + isize name_len = 9 + 1 + ts_name.len + 1 + 10 + 1; + char *name_text = gb_alloc_array(permanent_allocator(), char, name_len); + static std::atomic<u32> guid; + name_len = gb_snprintf(name_text, name_len, "_internal" ABI_PKG_NAME_SEPARATOR "%.*s-%u", LIT(ts_name), 1+guid.fetch_add(1)); + + String name = make_string(cast(u8 *)name_text, name_len-1); + e->TypeName.ir_mangled_name = name; + return name; + } +} + +gb_internal String cg_mangle_name(cgModule *m, Entity *e) { + String name = e->token.string; + + AstPackage *pkg = e->pkg; + GB_ASSERT_MSG(pkg != nullptr, "Missing package for '%.*s'", LIT(name)); + String pkgn = pkg->name; + GB_ASSERT(!rune_is_digit(pkgn[0])); + if (pkgn == "llvm") { + GB_PANIC("llvm. entities are not allowed with the tilde backend"); + } + + isize max_len = pkgn.len + 1 + name.len + 1; + bool require_suffix_id = is_type_polymorphic(e->type, true); + + if ((e->scope->flags & (ScopeFlag_File | ScopeFlag_Pkg)) == 0) { + require_suffix_id = true; + } else if (is_blank_ident(e->token)) { + require_suffix_id = true; + }if (e->flags & EntityFlag_NotExported) { + require_suffix_id = true; + } + + if (require_suffix_id) { + max_len += 21; + } + + char *new_name = gb_alloc_array(permanent_allocator(), char, max_len); + isize new_name_len = gb_snprintf( + new_name, max_len, + "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s", LIT(pkgn), LIT(name) + ); + if (require_suffix_id) { + char *str = new_name + new_name_len-1; + isize len = max_len-new_name_len; + isize extra = gb_snprintf(str, len, "-%llu", cast(unsigned long long)e->id); + new_name_len += extra-1; + } + + String mangled_name = make_string((u8 const *)new_name, new_name_len-1); + return mangled_name; +} + +String cg_get_entity_name(cgModule *m, Entity *e) { + if (e != nullptr && e->kind == Entity_TypeName && e->TypeName.ir_mangled_name.len != 0) { + return e->TypeName.ir_mangled_name; + } + GB_ASSERT(e != nullptr); + + if (e->pkg == nullptr) { + return e->token.string; + } + + if (e->kind == Entity_TypeName && (e->scope->flags & ScopeFlag_File) == 0) { + return cg_set_nested_type_name_ir_mangled_name(e, nullptr); + } + + String name = {}; + + bool no_name_mangle = false; + + if (e->kind == Entity_Variable) { + bool is_foreign = e->Variable.is_foreign; + bool is_export = e->Variable.is_export; + no_name_mangle = e->Variable.link_name.len > 0 || is_foreign || is_export; + if (e->Variable.link_name.len > 0) { + return e->Variable.link_name; + } + } else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) { + return e->Procedure.link_name; + } else if (e->kind == Entity_Procedure && e->Procedure.is_export) { + no_name_mangle = true; + } + + if (!no_name_mangle) { + name = cg_mangle_name(m, e); + } + if (name.len == 0) { + name = e->token.string; + } + + if (e->kind == Entity_TypeName) { + e->TypeName.ir_mangled_name = name; + } else if (e->kind == Entity_Procedure) { + e->Procedure.link_name = name; + } + + return name; +} + + +struct cgGlobalVariable { + cgValue var; + cgValue init; + DeclInfo *decl; + bool is_initialized; +}; + + +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; + } + + } + + if (param.dt.width != 0) { + if (is_blank_ident(e->token)) { + param.name = alloc_cstring(temporary_allocator(), e->token.string); + } + array_add(¶ms, param); + } + } + + return tb_prototype_create(m->mod, TB_CDECL, params.count, params.data, 0, nullptr, false); +} + +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); + + char const *link_name_c = alloc_cstring(temporary_allocator(), link_name); + + 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_c, TB_EXTERNAL_SO_LOCAL); + } + + if (p->symbol == nullptr) { + p->func = tb_function_create(m->mod, link_name_c, 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->context_stack.allocator = a; + // map_init(&p->tuple_fix_map, 0); + + + + char const *link_name_c = alloc_cstring(temporary_allocator(), link_name); + + TB_Linkage linkage = TB_LINKAGE_PRIVATE; + + p->func = tb_function_create(m->mod, link_name_c, 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_printf_err("cg_procedure_begin %.*s\n", LIT(p->name)); +} + +gb_internal void cg_procedure_end(cgProcedure *p) { + if (p == nullptr || p->func == nullptr) { + return; + } + gb_printf_err("cg_procedure_end %.*s\n", LIT(p->name)); + tb_inst_ret(p->func, 0, nullptr); + tb_module_compile_function(p->module->mod, p->func, TB_ISEL_FAST); +} + +gb_internal void cg_procedure_build_body(cgProcedure *p) { + if (p->body == nullptr) { + return; + } + + // TODO(bill): +} + + +gb_internal bool cg_generate_code(Checker *c) { + TIME_SECTION("Tilde Module Initializtion"); + + CheckerInfo *info = &c->info; + gb_unused(info); + + cgModule *m = cg_module_create(c); + defer (cg_module_destroy(m)); + + TIME_SECTION("Tilde Global Variables"); + + cg_create_global_variables(m); + + // isize global_variable_max_count = 0; + // bool already_has_entry_point = false; + + // for (Entity *e : info->entities) { + // String name = e->token.string; + + // if (e->kind == Entity_Variable) { + // global_variable_max_count++; + // } else if (e->kind == Entity_Procedure) { + // if ((e->scope->flags&ScopeFlag_Init) && name == "main") { + // GB_ASSERT(e == info->entry_point); + // } + // if (build_context.command_kind == Command_test && + // (e->Procedure.is_export || e->Procedure.link_name.len > 0)) { + // String link_name = e->Procedure.link_name; + // if (e->pkg->kind == Package_Runtime) { + // if (link_name == "main" || + // link_name == "DllMain" || + // link_name == "WinMain" || + // link_name == "wWinMain" || + // link_name == "mainCRTStartup" || + // link_name == "_start") { + // already_has_entry_point = true; + // } + // } + // } + // } + // } + // auto global_variables = array_make<cgGlobalVariable>(permanent_allocator(), 0, global_variable_max_count); + + if (true) { + Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin); + cgProcedure *p = cg_procedure_create_dummy(m, str_lit(CG_STARTUP_RUNTIME_PROC_NAME), proc_type); + p->is_startup = true; + + cg_procedure_begin(p); + cg_procedure_end(p); + } + + if (true) { + Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin); + cgProcedure *p = cg_procedure_create_dummy(m, str_lit(CG_CLEANUP_RUNTIME_PROC_NAME), proc_type); + p->is_startup = true; + + cg_procedure_begin(p); + cg_procedure_end(p); + } + + auto *min_dep_set = &info->minimum_dependency_set; + + for (Entity *e : info->entities) { + String name = e->token.string; + Scope * scope = e->scope; + + if ((scope->flags & ScopeFlag_File) == 0) { + continue; + } + + Scope *package_scope = scope->parent; + GB_ASSERT(package_scope->flags & ScopeFlag_Pkg); + + if (e->kind != Entity_Procedure) { + continue; + } + + if (!ptr_set_exists(min_dep_set, e)) { + // NOTE(bill): Nothing depends upon it so doesn't need to be built + continue; + } + if (cgProcedure *p = cg_procedure_create(m, e)) { + array_add(&m->procedures_to_generate, p); + } + } + + + for (isize i = 0; i < m->procedures_to_generate.count; i++) { + cgProcedure *p = m->procedures_to_generate[i]; + cg_procedure_begin(p); + if (p->name == "main") { + cg_procedure_build_body(p); + } + cg_procedure_end(p); + } + + + + //////////////////////////////////////////////////////////////////////////////////// + TB_Arena *arena = tb_default_arena(); @@ -25,36 +718,36 @@ bool tb_generate_code(Checker *c) { { TB_Global *str_data = nullptr; { - str_data = tb_global_create(m, "csb$1", nullptr, TB_LINKAGE_PRIVATE); - tb_global_set_storage(m, tb_module_get_rdata(m), str_data, 8, 1, 1); - void *region = tb_global_add_region(m, str_data, 0, 8); + str_data = tb_global_create(m->mod, "csb$1", nullptr, TB_LINKAGE_PRIVATE); + tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), str_data, 8, 1, 1); + void *region = tb_global_add_region(m->mod, str_data, 0, 8); memcpy(region, "Hellope\x00", 8); } - str = tb_global_create(m, "global$str", nullptr, TB_LINKAGE_PRIVATE); - tb_global_set_storage(m, tb_module_get_rdata(m), str, 16, 8, 2); - tb_global_add_symbol_reloc(m, str, 0, cast(TB_Symbol *)str_data); - void *len = tb_global_add_region(m, str, 8, 8); + str = tb_global_create(m->mod, "global$str", nullptr, TB_LINKAGE_PRIVATE); + tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), str, 16, 8, 2); + tb_global_add_symbol_reloc(m->mod, str, 0, cast(TB_Symbol *)str_data); + void *len = tb_global_add_region(m->mod, str, 8, 8); *cast(i64 *)len = 7; } { TB_PrototypeParam printf_ret = {TB_TYPE_I32}; TB_PrototypeParam printf_params = {TB_TYPE_PTR}; - TB_FunctionPrototype *printf_proto = tb_prototype_create(m, TB_STDCALL, 1, &printf_params, 1, &printf_ret, true); - TB_External *printf_proc = tb_extern_create(m, "printf", TB_EXTERNAL_SO_LOCAL); + TB_FunctionPrototype *printf_proto = tb_prototype_create(m->mod, TB_STDCALL, 1, &printf_params, 1, &printf_ret, true); + TB_External *printf_proc = tb_extern_create(m->mod, "printf", TB_EXTERNAL_SO_LOCAL); TB_PrototypeParam main_ret = {TB_TYPE_I32}; - TB_FunctionPrototype *main_proto = tb_prototype_create(m, TB_STDCALL, 0, nullptr, 1, &main_ret, false); - TB_Function * p = tb_function_create(m, "main", TB_LINKAGE_PUBLIC, TB_COMDAT_NONE); + TB_FunctionPrototype *main_proto = tb_prototype_create(m->mod, TB_STDCALL, 0, nullptr, 1, &main_ret, false); + TB_Function * p = tb_function_create(m->mod, "main", TB_LINKAGE_PUBLIC, TB_COMDAT_NONE); tb_function_set_prototype(p, main_proto, arena); - auto str_ptr = tb_inst_get_symbol_address(p, cast(TB_Symbol *)str); + auto str_ptr = tb_inst_get_symbol_address(p, cast(TB_Symbol *)str); auto str_data_ptr_ptr = tb_inst_member_access(p, str_ptr, 0); - auto str_data_ptr = tb_inst_load(p, TB_TYPE_PTR, str_data_ptr_ptr, 1, false); - auto str_len_ptr = tb_inst_member_access(p, str_ptr, 8); - auto str_len = tb_inst_load(p, TB_TYPE_I64, str_len_ptr, 8, false); + auto str_data_ptr = tb_inst_load(p, TB_TYPE_PTR, str_data_ptr_ptr, 1, false); + auto str_len_ptr = tb_inst_member_access(p, str_ptr, 8); + auto str_len = tb_inst_load(p, TB_TYPE_I64, str_len_ptr, 8, false); TB_Node *params[4] = {}; @@ -64,17 +757,39 @@ bool tb_generate_code(Checker *c) { params[3] = tb_inst_cstring(p, "World"); TB_MultiOutput output = tb_inst_call(p, printf_proto, tb_inst_get_symbol_address(p, cast(TB_Symbol *)printf_proc), gb_count_of(params), params); gb_unused(output); + TB_Node *printf_return_value = output.single; + + TB_Node *zero = tb_inst_uint(p, TB_TYPE_I32, 0); + TB_Node *one = tb_inst_uint(p, TB_TYPE_I32, 1); + + TB_Node *prev_case = tb_inst_get_control(p); + + TB_Node *true_case = tb_inst_region(p); + TB_Node *false_case = tb_inst_region(p); + + TB_Node *cond = tb_inst_cmp_igt(p, printf_return_value, zero, true); + tb_inst_if(p, cond, true_case, false_case); - TB_Node *value = tb_inst_uint(p, TB_TYPE_I32, 0); - tb_inst_ret(p, 1, &value); + tb_inst_set_control(p, true_case); + tb_inst_ret(p, 1, &zero); - tb_module_compile_function(m, p, TB_ISEL_FAST); + tb_inst_set_control(p, false_case); + tb_inst_ret(p, 1, &one); - TB_ExportBuffer export_buffer = tb_module_object_export(m, TB_DEBUGFMT_NONE); + tb_inst_set_control(p, prev_case); + + + tb_module_compile_function(m->mod, p, TB_ISEL_FAST); + + tb_function_print(p, tb_default_print_callback, stdout); + + TB_ExportBuffer export_buffer = tb_module_object_export(m->mod, TB_DEBUGFMT_NONE); defer (tb_export_buffer_free(export_buffer)); char const *path = "W:/Odin/tilde_main.obj"; GB_ASSERT(tb_export_buffer_to_file(export_buffer, path)); } - return false; -}
\ No newline at end of file + return true; +} + +#undef ABI_PKG_NAME_SEPARATOR |