diff options
| author | gingerBill <bill@gingerbill.org> | 2023-07-15 14:26:47 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2023-07-15 14:26:47 +0100 |
| commit | ee8372145d62bf90c0fe43c78b96a02b6247321e (patch) | |
| tree | 4670870ddce1230883d2c3daa50f0bfcf7fb2e4b /src | |
| parent | ccb736411bc61a0ccde6835cbbf1876a2616e3e1 (diff) | |
Begin working on proper expressions
Diffstat (limited to 'src')
| -rw-r--r-- | src/tilde/tb.lib | bin | 4120106 -> 4112646 bytes | |||
| -rw-r--r-- | src/tilde_backend.cpp | 178 | ||||
| -rw-r--r-- | src/tilde_backend.hpp | 11 | ||||
| -rw-r--r-- | src/tilde_const.cpp | 97 | ||||
| -rw-r--r-- | src/tilde_expr.cpp | 265 | ||||
| -rw-r--r-- | src/tilde_proc.cpp | 84 | ||||
| -rw-r--r-- | src/tilde_stmt.cpp | 75 |
7 files changed, 630 insertions, 80 deletions
diff --git a/src/tilde/tb.lib b/src/tilde/tb.lib Binary files differindex a6ac5cbff..bad51e7e6 100644 --- a/src/tilde/tb.lib +++ b/src/tilde/tb.lib diff --git a/src/tilde_backend.cpp b/src/tilde_backend.cpp index 97f92e3db..dfe39c385 100644 --- a/src/tilde_backend.cpp +++ b/src/tilde_backend.cpp @@ -33,7 +33,7 @@ gb_internal TB_DataType cg_data_type(Type *t) { case Basic_typeid: return TB_TYPE_INTN(cast(u16)(8*sz)); - case Basic_f16: return TB_TYPE_I16; + case Basic_f16: return TB_TYPE_F16; case Basic_f32: return TB_TYPE_F32; case Basic_f64: return TB_TYPE_F64; @@ -60,11 +60,11 @@ gb_internal TB_DataType cg_data_type(Type *t) { case Basic_u128be: return TB_TYPE_INTN(cast(u16)(8*sz)); - case Basic_f16le: return TB_TYPE_I16; + case Basic_f16le: return TB_TYPE_F16; case Basic_f32le: return TB_TYPE_F32; case Basic_f64le: return TB_TYPE_F64; - case Basic_f16be: return TB_TYPE_I16; + case Basic_f16be: return TB_TYPE_F16; case Basic_f32be: return TB_TYPE_F32; case Basic_f64be: return TB_TYPE_F64; } @@ -173,9 +173,128 @@ gb_internal isize cg_type_info_index(CheckerInfo *info, Type *type, bool err_on_ return -1; } -gb_internal void cg_create_global_variables(cgModule *m) { +struct cgGlobalVariable { + cgValue var; + cgValue init; + DeclInfo *decl; + bool is_initialized; +}; + +// Returns already_has_entry_point +gb_internal bool cg_global_variables_create(cgModule *m) { + isize global_variable_max_count = 0; + bool already_has_entry_point = false; + + for (Entity *e : m->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 == m->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); + + auto *min_dep_set = &m->info->minimum_dependency_set; + + for (DeclInfo *d : m->info->variable_init_order) { + Entity *e = d->entity; + + if ((e->scope->flags & ScopeFlag_File) == 0) { + continue; + } + + if (!ptr_set_exists(min_dep_set, e)) { + continue; + } + + DeclInfo *decl = decl_info_of_entity(e); + if (decl == nullptr) { + continue; + } + GB_ASSERT(e->kind == Entity_Variable); + + bool is_foreign = e->Variable.is_foreign; + bool is_export = e->Variable.is_export; + + String name = cg_get_entity_name(m, e); + + TB_Linkage linkage = TB_LINKAGE_PRIVATE; + + if (is_foreign) { + linkage = TB_LINKAGE_PUBLIC; + // lb_add_foreign_library_path(m, e->Variable.foreign_library); + // lb_set_wasm_import_attributes(g.value, e, name); + } else if (is_export) { + linkage = TB_LINKAGE_PUBLIC; + } + // lb_set_linkage_from_entity_flags(m, g.value, e->flags); + + TB_DebugType *debug_type = cg_debug_type(m, e->type); + TB_Global *global = tb_global_create(m->mod, name.len, cast(char const *)name.text, debug_type, linkage); + cgValue g = cg_value(global, alloc_type_pointer(e->type)); + + TB_ModuleSection *section = tb_module_get_data(m->mod); + + if (e->Variable.thread_local_model != "") { + section = tb_module_get_tls(m->mod); + } + if (e->Variable.link_section.len > 0) { + // TODO(bill): custom module sections + // LLVMSetSection(g.value, alloc_cstring(permanent_allocator(), e->Variable.link_section)); + } + + size_t max_objects = 0; + tb_global_set_storage(m->mod, section, global, type_size_of(e->type), type_align_of(e->type), max_objects); + + cgGlobalVariable var = {}; + var.var = g; + var.decl = decl; + + if (decl->init_expr != nullptr) { + // TypeAndValue tav = type_and_value_of_expr(decl->init_expr); + // if (!is_type_any(e->type) && !is_type_union(e->type)) { + // if (tav.mode != Addressing_Invalid) { + // if (tav.value.kind != ExactValue_Invalid) { + // ExactValue v = tav.value; + // lbValue init = lb_const_value(m, tav.type, v); + // LLVMSetInitializer(g.value, init.value); + // var.is_initialized = true; + // } + // } + // } + // if (!var.is_initialized && is_type_untyped_nil(tav.type)) { + // var.is_initialized = true; + // } + } + + array_add(&global_variables, var); + + cg_add_entity(m, e, g); + cg_add_member(m, name, g); + } + + + if (build_context.no_rtti) { - return; + return already_has_entry_point; } CheckerInfo *info = m->info; @@ -256,9 +375,11 @@ gb_internal void cg_create_global_variables(cgModule *m) { } } } + + return already_has_entry_point; } -cgModule *cg_module_create(Checker *c) { +gb_internal cgModule *cg_module_create(Checker *c) { cgModule *m = gb_alloc_item(permanent_allocator(), cgModule); m->checker = c; @@ -286,7 +407,7 @@ cgModule *cg_module_create(Checker *c) { return m; } -void cg_module_destroy(cgModule *m) { +gb_internal void cg_module_destroy(cgModule *m) { map_destroy(&m->values); array_free(&m->procedures_to_generate); map_destroy(&m->file_id_map); @@ -391,7 +512,7 @@ gb_internal String cg_mangle_name(cgModule *m, Entity *e) { return mangled_name; } -String cg_get_entity_name(cgModule *m, Entity *e) { +gb_internal 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; } @@ -438,14 +559,6 @@ String cg_get_entity_name(cgModule *m, Entity *e) { return name; } - -struct cgGlobalVariable { - cgValue var; - cgValue init; - DeclInfo *decl; - bool is_initialized; -}; - #include "tilde_const.cpp" #include "tilde_expr.cpp" #include "tilde_proc.cpp" @@ -463,37 +576,8 @@ gb_internal bool cg_generate_code(Checker *c) { 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); + bool already_has_entry_point = cg_global_variables_create(m); + gb_unused(already_has_entry_point); if (true) { Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin); diff --git a/src/tilde_backend.hpp b/src/tilde_backend.hpp index 1f7300d73..228afb6af 100644 --- a/src/tilde_backend.hpp +++ b/src/tilde_backend.hpp @@ -7,6 +7,7 @@ #include "tilde/tb.h" +#define TB_TYPE_F16 TB_DataType{ { TB_INT, 0, 16 } } #define TB_TYPE_I128 TB_DataType{ { TB_INT, 0, 128 } } #define TB_TYPE_INT TB_TYPE_INTN(cast(u16)build_context.int_size) #define TB_TYPE_INTPTR TB_TYPE_INTN(cast(u16)build_context.ptr_size) @@ -127,6 +128,7 @@ struct cgProcedure { Array<cgProcedure *> children; TB_Function *func; + TB_FunctionPrototype *proto; TB_Symbol *symbol; Entity * entity; @@ -151,9 +153,12 @@ struct cgProcedure { Scope *curr_scope; i32 scope_index; + bool in_multi_assignment; Array<Scope *> scope_stack; Array<cgContextData> context_stack; + + PtrMap<Entity *, cgAddr> variable_map; }; @@ -226,4 +231,8 @@ gb_internal cgValue cg_build_call_expr(cgProcedure *p, Ast *expr); gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e); -gb_internal TB_DebugType *cg_debug_type(cgModule *m, Type *type);
\ No newline at end of file +gb_internal TB_DebugType *cg_debug_type(cgModule *m, Type *type); + +gb_internal String cg_get_entity_name(cgModule *m, Entity *e); + +gb_internal cgValue cg_typeid(cgModule *m, Type *t);
\ No newline at end of file diff --git a/src/tilde_const.cpp b/src/tilde_const.cpp index 97fee838e..35c87641f 100644 --- a/src/tilde_const.cpp +++ b/src/tilde_const.cpp @@ -1,19 +1,31 @@ -gb_internal cgValue cg_const_nil(cgProcedure *p, Type *type) { +gb_internal bool cg_is_expr_constant_zero(Ast *expr) { + GB_ASSERT(expr != nullptr); + auto v = exact_value_to_integer(expr->tav.value); + if (v.kind == ExactValue_Integer) { + return big_int_cmp_zero(&v.value_integer) == 0; + } + return false; +} + +gb_internal cgValue cg_const_nil(cgModule *m, cgProcedure *p, Type *type) { Type *original_type = type; type = core_type(type); i64 size = type_size_of(type); i64 align = type_align_of(type); TB_DataType dt = cg_data_type(type); if (TB_IS_VOID_TYPE(dt)) { - TB_Module *m = p->module->mod; char name[32] = {}; - gb_snprintf(name, 31, "cnil$%u", 1+p->module->const_nil_guid.fetch_add(1)); - TB_Global *global = tb_global_create(m, -1, name, nullptr, TB_LINKAGE_PRIVATE); - tb_global_set_storage(m, tb_module_get_rdata(m), global, size, align, 0); + gb_snprintf(name, 31, "cnil$%u", 1+m->const_nil_guid.fetch_add(1)); + TB_Global *global = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE); + tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), global, size, align, 0); TB_Symbol *symbol = cast(TB_Symbol *)global; - TB_Node *node = tb_inst_get_symbol_address(p->func, symbol); - return cg_lvalue_addr(node, type); + if (p) { + TB_Node *node = tb_inst_get_symbol_address(p->func, symbol); + return cg_lvalue_addr(node, type); + } else { + GB_PANIC("TODO(bill): cg_const_nil"); + } } if (is_type_internally_pointer_like(type)) { @@ -34,24 +46,71 @@ gb_internal cgValue cg_const_nil(cgProcedure *p, Type *type) { return {}; } -gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, ExactValue const &value) { +gb_internal cgValue cg_const_nil(cgProcedure *p, Type *type) { + return cg_const_nil(p->module, p, type); +} + +gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, ExactValue const &value, bool allow_local = true) { TB_Node *node = nullptr; - if (value.kind == ExactValue_Invalid) { + bool is_local = allow_local && p != nullptr; + gb_unused(is_local); + + TB_DataType dt = cg_data_type(type); + + switch (value.kind) { + case ExactValue_Invalid: return cg_const_nil(p, type); + + case ExactValue_Typeid: + return cg_typeid(m, value.value_typeid); + + case ExactValue_Procedure: + { + Ast *expr = unparen_expr(value.value_procedure); + Entity *e = entity_of_node(expr); + if (e != nullptr) { + cgValue found = cg_find_procedure_value_from_entity(m, e); + GB_ASSERT(are_types_identical(type, found.type)); + return found; + } + GB_PANIC("TODO(bill): cg_const_value ExactValue_Procedure"); + } + break; } - if (value.kind == ExactValue_Procedure) { - Ast *expr = unparen_expr(value.value_procedure); - Entity *e = entity_of_node(expr); - if (e != nullptr) { - cgValue found = cg_find_procedure_value_from_entity(m, e); - GB_ASSERT(are_types_identical(type, found.type)); - return found; + GB_ASSERT(!TB_IS_VOID_TYPE(dt)); + + switch (value.kind) { + case ExactValue_Bool: + return cg_value(tb_inst_uint(p->func, dt, value.value_bool), type); + + case ExactValue_Integer: + GB_ASSERT(dt.raw != TB_TYPE_I128.raw); + if (is_type_unsigned(type)) { + u64 i = exact_value_to_u64(value); + return cg_value(tb_inst_uint(p->func, dt, i), type); + } else { + i64 i = exact_value_to_i64(value); + return cg_value(tb_inst_sint(p->func, dt, i), type); } + break; + case ExactValue_Float: + GB_ASSERT(dt.raw != TB_TYPE_F16.raw); + GB_ASSERT(!is_type_different_to_arch_endianness(type)); + { + f64 f = exact_value_to_f64(value); + if (type_size_of(type) == 8) { + return cg_value(tb_inst_float64(p->func, f), type); + } else { + return cg_value(tb_inst_float32(p->func, cast(f32)f), type); + } + } + break; } + GB_ASSERT(node != nullptr); return cg_value(node, type); } @@ -59,4 +118,8 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac gb_internal cgValue cg_const_value(cgProcedure *p, Type *type, ExactValue const &value) { GB_ASSERT(p != nullptr); return cg_const_value(p->module, p, type, value); -}
\ No newline at end of file +} + +gb_internal cgValue cg_const_int(cgProcedure *p, Type *type, i64 i) { + return cg_const_value(p, type, exact_value_i64(i)); +} diff --git a/src/tilde_expr.cpp b/src/tilde_expr.cpp index 22da43cbd..fc22e12d9 100644 --- a/src/tilde_expr.cpp +++ b/src/tilde_expr.cpp @@ -1,3 +1,11 @@ +gb_internal cgValue cg_flatten_value(cgProcedure *p, cgValue value) { + if (value.kind == cgValue_Symbol) { + GB_ASSERT(is_type_internally_pointer_like(value.type)); + value = cg_value(tb_inst_get_symbol_address(p->func, value.symbol), value.type); + } + return value; +} + gb_internal cgContextData *cg_push_context_onto_stack(cgProcedure *p, cgAddr ctx) { ctx.kind = cgAddr_Context; cgContextData *cd = array_add_and_get(&p->context_stack); @@ -43,7 +51,7 @@ gb_internal cgValue cg_find_value_from_entity(cgModule *m, Entity *e) { return *found; } - // GB_PANIC("\n\tError in: %s, missing value '%.*s'\n", token_pos_to_string(e->token.pos), LIT(e->token.string)); + GB_PANIC("\n\tError in: %s, missing value '%.*s'\n", token_pos_to_string(e->token.pos), LIT(e->token.string)); return {}; } @@ -57,6 +65,10 @@ gb_internal cgAddr cg_build_addr_from_entity(cgProcedure *p, Entity *e, Ast *exp return {}; } + cgAddr *local_found = map_get(&p->variable_map, e); + if (local_found) { + return *local_found; + } cgValue v = {}; @@ -78,7 +90,9 @@ gb_internal cgAddr cg_build_addr_from_entity(cgProcedure *p, Entity *e, Ast *exp if (v.node == nullptr) { - return cg_addr(cg_find_value_from_entity(m, e)); + cgValue v = cg_find_value_from_entity(m, e); + v = cg_flatten_value(p, v); + return cg_addr(v); } return cg_addr(v); @@ -90,6 +104,17 @@ gb_internal cgValue cg_typeid(cgModule *m, Type *t) { } +gb_internal cgValue cg_correct_endianness(cgProcedure *p, cgValue value) { + Type *src = core_type(value.type); + GB_ASSERT(is_type_integer(src) || is_type_float(src)); + if (is_type_different_to_arch_endianness(src)) { + GB_PANIC("TODO(bill): cg_correct_endianness"); + // Type *platform_src_type = integer_endian_type_to_platform_type(src); + // value = cg_emit_byte_swap(p, value, platform_src_type); + } + return value; +} + gb_internal cgValue cg_emit_conv(cgProcedure *p, cgValue value, Type *type) { // TODO(bill): cg_emit_conv return value; @@ -98,10 +123,7 @@ gb_internal cgValue cg_emit_conv(cgProcedure *p, cgValue value, Type *type) { gb_internal cgValue cg_emit_transmute(cgProcedure *p, cgValue value, Type *type) { GB_ASSERT(type_size_of(value.type) == type_size_of(type)); - if (value.kind == cgValue_Symbol) { - GB_ASSERT(is_type_pointer(value.type)); - value = cg_value(tb_inst_get_symbol_address(p->func, value.symbol), type); - } + value = cg_flatten_value(p, value); i64 src_align = type_align_of(value.type); i64 dst_align = type_align_of(type); @@ -133,6 +155,217 @@ gb_internal cgValue cg_emit_transmute(cgProcedure *p, cgValue value, Type *type) } +gb_internal cgAddr cg_build_addr_slice_expr(cgProcedure *p, Ast *expr) { + ast_node(se, SliceExpr, expr); + + cgValue low = cg_const_int(p, t_int, 0); + cgValue high = {}; + + if (se->low != nullptr) { + low = cg_correct_endianness(p, cg_build_expr(p, se->low)); + } + if (se->high != nullptr) { + high = cg_correct_endianness(p, cg_build_expr(p, se->high)); + } + + bool no_indices = se->low == nullptr && se->high == nullptr; + gb_unused(no_indices); + + cgAddr addr = cg_build_addr(p, se->expr); + cgValue base = cg_addr_load(p, addr); + Type *type = base_type(base.type); + + if (is_type_pointer(type)) { + type = base_type(type_deref(type)); + addr = cg_addr(base); + base = cg_addr_load(p, addr); + } + + switch (type->kind) { + case Type_Slice: { + // Type *slice_type = type; + // cgValue len = cg_slice_len(p, base); + // if (high.value == nullptr) high = len; + + // if (!no_indices) { + // cg_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); + // } + + // cgValue elem = cg_emit_ptr_offset(p, cg_slice_elem(p, base), low); + // cgValue new_len = cg_emit_arith(p, Token_Sub, high, low, t_int); + + // cgAddr slice = cg_add_local_generated(p, slice_type, false); + // cg_fill_slice(p, slice, elem, new_len); + // return slice; + GB_PANIC("cg_build_addr_slice_expr Type_Slice"); + break; + } + + case Type_RelativeSlice: + GB_PANIC("TODO(bill): Type_RelativeSlice should be handled above already on the cg_addr_load"); + break; + + case Type_DynamicArray: { + // Type *elem_type = type->DynamicArray.elem; + // Type *slice_type = alloc_type_slice(elem_type); + + // lbValue len = lb_dynamic_array_len(p, base); + // if (high.value == nullptr) high = len; + + // if (!no_indices) { + // lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); + // } + + // lbValue elem = lb_emit_ptr_offset(p, lb_dynamic_array_elem(p, base), low); + // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); + + // lbAddr slice = lb_add_local_generated(p, slice_type, false); + // lb_fill_slice(p, slice, elem, new_len); + // return slice; + GB_PANIC("cg_build_addr_slice_expr Type_DynamicArray"); + break; + } + + case Type_MultiPointer: { + // lbAddr res = lb_add_local_generated(p, type_of_expr(expr), false); + // if (se->high == nullptr) { + // lbValue offset = base; + // LLVMValueRef indices[1] = {low.value}; + // offset.value = LLVMBuildGEP2(p->builder, lb_type(p->module, offset.type->MultiPointer.elem), offset.value, indices, 1, ""); + // lb_addr_store(p, res, offset); + // } else { + // low = lb_emit_conv(p, low, t_int); + // high = lb_emit_conv(p, high, t_int); + + // lb_emit_multi_pointer_slice_bounds_check(p, se->open, low, high); + + // LLVMValueRef indices[1] = {low.value}; + // LLVMValueRef ptr = LLVMBuildGEP2(p->builder, lb_type(p->module, base.type->MultiPointer.elem), base.value, indices, 1, ""); + // LLVMValueRef len = LLVMBuildSub(p->builder, high.value, low.value, ""); + + // LLVMValueRef gep0 = lb_emit_struct_ep(p, res.addr, 0).value; + // LLVMValueRef gep1 = lb_emit_struct_ep(p, res.addr, 1).value; + // LLVMBuildStore(p->builder, ptr, gep0); + // LLVMBuildStore(p->builder, len, gep1); + // } + // return res; + GB_PANIC("cg_build_addr_slice_expr Type_MultiPointer"); + break; + } + + case Type_Array: { + // Type *slice_type = alloc_type_slice(type->Array.elem); + // lbValue len = lb_const_int(p->module, t_int, type->Array.count); + + // if (high.value == nullptr) high = len; + + // bool low_const = type_and_value_of_expr(se->low).mode == Addressing_Constant; + // bool high_const = type_and_value_of_expr(se->high).mode == Addressing_Constant; + + // if (!low_const || !high_const) { + // if (!no_indices) { + // lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); + // } + // } + // lbValue elem = lb_emit_ptr_offset(p, lb_array_elem(p, lb_addr_get_ptr(p, addr)), low); + // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); + + // lbAddr slice = lb_add_local_generated(p, slice_type, false); + // lb_fill_slice(p, slice, elem, new_len); + // return slice; + GB_PANIC("cg_build_addr_slice_expr Type_Array"); + break; + } + + case Type_Basic: { + // GB_ASSERT(type == t_string); + // lbValue len = lb_string_len(p, base); + // if (high.value == nullptr) high = len; + + // if (!no_indices) { + // lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); + // } + + // lbValue elem = lb_emit_ptr_offset(p, lb_string_elem(p, base), low); + // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); + + // lbAddr str = lb_add_local_generated(p, t_string, false); + // lb_fill_string(p, str, elem, new_len); + // return str; + GB_PANIC("cg_build_addr_slice_expr Type_Basic"); + break; + } + + + case Type_Struct: + // if (is_type_soa_struct(type)) { + // lbValue len = lb_soa_struct_len(p, lb_addr_get_ptr(p, addr)); + // if (high.value == nullptr) high = len; + + // if (!no_indices) { + // lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); + // } + // #if 1 + + // lbAddr dst = lb_add_local_generated(p, type_of_expr(expr), true); + // if (type->Struct.soa_kind == StructSoa_Fixed) { + // i32 field_count = cast(i32)type->Struct.fields.count; + // for (i32 i = 0; i < field_count; i++) { + // lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i); + // lbValue field_src = lb_emit_struct_ep(p, lb_addr_get_ptr(p, addr), i); + // field_src = lb_emit_array_ep(p, field_src, low); + // lb_emit_store(p, field_dst, field_src); + // } + + // lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count); + // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); + // lb_emit_store(p, len_dst, new_len); + // } else if (type->Struct.soa_kind == StructSoa_Slice) { + // if (no_indices) { + // lb_addr_store(p, dst, base); + // } else { + // i32 field_count = cast(i32)type->Struct.fields.count - 1; + // for (i32 i = 0; i < field_count; i++) { + // lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i); + // lbValue field_src = lb_emit_struct_ev(p, base, i); + // field_src = lb_emit_ptr_offset(p, field_src, low); + // lb_emit_store(p, field_dst, field_src); + // } + + + // lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count); + // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); + // lb_emit_store(p, len_dst, new_len); + // } + // } else if (type->Struct.soa_kind == StructSoa_Dynamic) { + // i32 field_count = cast(i32)type->Struct.fields.count - 3; + // for (i32 i = 0; i < field_count; i++) { + // lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i); + // lbValue field_src = lb_emit_struct_ev(p, base, i); + // field_src = lb_emit_ptr_offset(p, field_src, low); + // lb_emit_store(p, field_dst, field_src); + // } + + + // lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count); + // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); + // lb_emit_store(p, len_dst, new_len); + // } + + // return dst; + // #endif + // } + GB_PANIC("cg_build_addr_slice_expr Type_Struct"); + break; + + } + + GB_PANIC("Unknown slicable type"); + return {}; +} + + + gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr); gb_internal cgValue cg_build_expr(cgProcedure *p, Ast *expr) { @@ -252,6 +485,11 @@ gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) { return cg_value(cast(TB_Node *)nullptr, e->type); } GB_ASSERT(e->kind != Entity_ProcGroup); + + cgAddr *addr = map_get(&p->variable_map, e); + if (addr) { + return cg_addr_load(p, *addr); + } // return cg_find_ident(p, m, e, expr); GB_PANIC("TODO: cg_find_ident"); return {}; @@ -327,6 +565,17 @@ gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) { cgValue value = cg_build_expr(p, ac->expr); return cg_emit_conv(p, value, type); case_end; + + case_ast_node(se, SliceExpr, expr); + if (is_type_slice(type_of_expr(se->expr))) { + // NOTE(bill): Quick optimization + if (se->high == nullptr && + (se->low == nullptr || cg_is_expr_constant_zero(se->low))) { + return cg_build_expr(p, se->expr); + } + } + return cg_addr_load(p, cg_build_addr(p, expr)); + case_end; } GB_PANIC("TODO(bill): cg_build_expr_internal %.*s", LIT(ast_strings[expr->kind])); return {}; @@ -384,6 +633,10 @@ gb_internal cgAddr cg_build_addr_internal(cgProcedure *p, Ast *expr) { Entity *e = entity_of_node(expr); return cg_build_addr_from_entity(p, e, expr); case_end; + + case_ast_node(se, SliceExpr, expr); + return cg_build_addr_slice_expr(p, expr); + case_end; } TokenPos token_pos = ast_token(expr).pos; diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp index b60e797c3..99b70a6a8 100644 --- a/src/tilde_proc.cpp +++ b/src/tilde_proc.cpp @@ -113,7 +113,7 @@ gb_internal TB_FunctionPrototype *cg_procedure_type_as_prototype(cgModule *m, Ty } } - if (param.dt.width != 0) { + if (param.dt.raw != 0) { if (is_blank_ident(e->token)) { param.name = alloc_cstring(temporary_allocator(), e->token.string); } @@ -183,6 +183,7 @@ gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool i // p->branch_blocks.allocator = a; p->context_stack.allocator = a; p->scope_stack.allocator = a; + map_init(&p->variable_map); // map_init(&p->tuple_fix_map, 0); TB_Linkage linkage = TB_LINKAGE_PRIVATE; @@ -196,8 +197,10 @@ gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool i } if (p->symbol == nullptr) { + TB_Arena *arena = tb_default_arena(); 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->proto = cg_procedure_type_as_prototype(m, p->type); + tb_function_set_prototype(p->func, p->proto, arena); p->symbol = cast(TB_Symbol *)p->func; } @@ -235,13 +238,16 @@ gb_internal cgProcedure *cg_procedure_create_dummy(cgModule *m, String const &li // p->branch_blocks.allocator = a; p->scope_stack.allocator = a; p->context_stack.allocator = a; + map_init(&p->variable_map); // map_init(&p->tuple_fix_map, 0); TB_Linkage linkage = TB_LINKAGE_PRIVATE; + TB_Arena *arena = tb_default_arena(); 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->proto = cg_procedure_type_as_prototype(m, p->type); + tb_function_set_prototype(p->func, p->proto, arena); p->symbol = cast(TB_Symbol *)p->func; cgValue proc_value = cg_value(p->symbol, p->type); @@ -255,6 +261,78 @@ gb_internal void cg_procedure_begin(cgProcedure *p) { if (p == nullptr || p->func == nullptr) { return; } + + if (p->body == nullptr) { + return; + } + + GB_ASSERT(p->type->kind == Type_Proc); + TypeProc *pt = &p->type->Proc; + if (pt->params) { + int param_index = 0; + for (Entity *e : pt->params->Tuple.variables) { + if (e->kind != Entity_Variable) { + continue; + } + + if (param_index >= p->proto->param_count) { + break; + } + + TB_Node *ptr = tb_inst_param_addr(p->func, param_index); + cgValue local = cg_value(ptr, alloc_type_pointer(e->type)); + + if (e != nullptr && e->token.string.len > 0 && e->token.string != "_") { + // NOTE(bill): for debugging purposes only + String name = e->token.string; + TB_DebugType *debug_type = cg_debug_type(p->module, e->type); + tb_node_append_attrib(ptr, tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, debug_type)); + + } + cgAddr addr = cg_addr(local); + if (e) { + map_set(&p->variable_map, e, addr); + } + + // if (arg_type->kind == lbArg_Ignore) { + // continue; + // } else if (arg_type->kind == lbArg_Direct) { + // if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) { + // LLVMTypeRef param_type = lb_type(p->module, e->type); + // LLVMValueRef original_value = LLVMGetParam(p->value, param_offset+param_index); + // LLVMValueRef value = OdinLLVMBuildTransmute(p, original_value, param_type); + + // lbValue param = {}; + // param.value = value; + // param.type = e->type; + + // map_set(&p->direct_parameters, e, param); + + // lbValue ptr = lb_address_from_load_or_generate_local(p, param); + // GB_ASSERT(LLVMIsAAllocaInst(ptr.value)); + // lb_add_entity(p->module, e, ptr); + + // lbBlock *block = p->decl_block; + // if (original_value != value) { + // block = p->curr_block; + // } + // LLVMValueRef debug_storage_value = value; + // if (original_value != value && LLVMIsALoadInst(value)) { + // debug_storage_value = LLVMGetOperand(value, 0); + // } + // lb_add_debug_param_variable(p, debug_storage_value, e->type, e->token, param_index+1, block, arg_type->kind); + // } + // } else if (arg_type->kind == lbArg_Indirect) { + // if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) { + // lbValue ptr = {}; + // ptr.value = LLVMGetParam(p->value, param_offset+param_index); + // ptr.type = alloc_type_pointer(e->type); + // lb_add_entity(p->module, e, ptr); + // lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1, p->decl_block, arg_type->kind); + // } + // } + } + } } gb_internal void cg_procedure_end(cgProcedure *p) { diff --git a/src/tilde_stmt.cpp b/src/tilde_stmt.cpp index 7c3dfcef8..2952539ca 100644 --- a/src/tilde_stmt.cpp +++ b/src/tilde_stmt.cpp @@ -131,6 +131,9 @@ gb_internal cgValue cg_address_from_load(cgProcedure *p, cgValue value) { GB_PANIC("Symbol is an invalid use case for cg_address_from_load"); return {}; } + GB_PANIC("Invalid cgValue for cg_address_from_load"); + return {}; + } gb_internal bool cg_addr_is_empty(cgAddr const &addr) { @@ -174,7 +177,14 @@ gb_internal Type *cg_addr_type(cgAddr const &addr) { } gb_internal cgValue cg_addr_load(cgProcedure *p, cgAddr addr) { - GB_PANIC("TODO(bill): cg_addr_load"); + if (addr.addr.node == nullptr) { + return {}; + } + switch (addr.kind) { + case cgAddr_Default: + return cg_emit_load(p, addr.addr); + } + GB_PANIC("TODO(bill): cg_addr_load %p", addr.addr.node); return {}; } @@ -285,19 +295,23 @@ gb_internal cgAddr cg_add_local(cgProcedure *p, Type *type, Entity *e, bool zero if (e != nullptr && e->token.string.len > 0 && e->token.string != "_") { // NOTE(bill): for debugging purposes only - // String name = e->token.string; - // TB_DebugType *debug_type = cg_debug_type(p->module, type); - // tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, debug_type); + String name = e->token.string; + TB_DebugType *debug_type = cg_debug_type(p->module, type); + tb_node_append_attrib(local, tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, debug_type)); } if (zero_init) { bool is_volatile = false; - TB_Node *zero = tb_inst_uint(p->func, TB_TYPE_I8, 0); + TB_Node *zero = tb_inst_uint(p->func, TB_TYPE_I8, 0); TB_Node *count = tb_inst_uint(p->func, TB_TYPE_I32, cast(u64)size); tb_inst_memset(p->func, local, zero, count, alignment, is_volatile); } - return cg_addr(cg_value(local, alloc_type_pointer(type))); + cgAddr addr = cg_addr(cg_value(local, alloc_type_pointer(type))); + if (e) { + map_set(&p->variable_map, e, addr); + } + return addr; } @@ -313,10 +327,59 @@ gb_internal void cg_emit_defer_stmts(cgProcedure *p, cgDeferExitKind kind, TB_No // TODO(bill): cg_emit_defer_stmts } + +gb_internal isize cg_append_tuple_values(cgProcedure *p, Array<cgValue> *dst_values, cgValue src_value) { + isize init_count = dst_values->count; + Type *t = src_value.type; + if (t && t->kind == Type_Tuple) { + GB_PANIC("TODO(bill): tuple assignments"); + // cgTupleFix *tf = map_get(&p->tuple_fix_map, src_value.value); + // if (tf) { + // for (cgValue const &value : tf->values) { + // array_add(dst_values, value); + // } + // } else { + // for_array(i, t->Tuple.variables) { + // cgValue v = cg_emit_tuple_ev(p, src_value, cast(i32)i); + // array_add(dst_values, v); + // } + // } + } else { + array_add(dst_values, src_value); + } + return dst_values->count - init_count; +} gb_internal void cg_build_assignment(cgProcedure *p, Array<cgAddr> const &lvals, Slice<Ast *> const &values) { if (values.count == 0) { return; } + + auto inits = array_make<cgValue>(permanent_allocator(), 0, lvals.count); + + for (Ast *rhs : values) { + cgValue init = cg_build_expr(p, rhs); + cg_append_tuple_values(p, &inits, init); + } + + bool prev_in_assignment = p->in_multi_assignment; + + isize lval_count = 0; + for (cgAddr const &lval : lvals) { + if (!cg_addr_is_empty(lval)) { + // check if it is not a blank identifier + lval_count += 1; + } + } + p->in_multi_assignment = lval_count > 1; + + GB_ASSERT(lvals.count == inits.count); + for_array(i, inits) { + cgAddr lval = lvals[i]; + cgValue init = inits[i]; + cg_addr_store(p, lval, init); + } + + p->in_multi_assignment = prev_in_assignment; } gb_internal void cg_build_assign_stmt(cgProcedure *p, AstAssignStmt *as) { |