From 55c9fb7c5c416ff0b94d0a9a531c41662a4eeb54 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 7 Aug 2023 15:04:03 +0100 Subject: [PATCH] Tilde: Begin work on #soa --- src/tilde.cpp | 8 +++ src/tilde.hpp | 1 + src/tilde_builtin.cpp | 20 +++++++ src/tilde_expr.cpp | 20 +++---- src/tilde_proc.cpp | 3 +- src/tilde_stmt.cpp | 123 +++++++++++++++++++++++++++++++++++++++++- 6 files changed, 160 insertions(+), 15 deletions(-) diff --git a/src/tilde.cpp b/src/tilde.cpp index 5562d2d48..17a2a1ab3 100644 --- a/src/tilde.cpp +++ b/src/tilde.cpp @@ -201,6 +201,14 @@ gb_internal cgAddr cg_addr_map(cgValue addr, cgValue map_key, Type *map_type, Ty return v; } +gb_internal cgAddr cg_addr_soa_variable(cgValue addr, cgValue index, Ast *index_expr) { + cgAddr v = {cgAddr_SoaVariable, addr}; + v.soa.index = index; + v.soa.index_expr = index_expr; + return v; +} + + gb_internal void cg_set_debug_pos_from_node(cgProcedure *p, Ast *node) { if (node) { diff --git a/src/tilde.hpp b/src/tilde.hpp index f98b52512..76417a9cf 100644 --- a/src/tilde.hpp +++ b/src/tilde.hpp @@ -202,6 +202,7 @@ struct cgProcedure { bool return_by_ptr; PtrMap variable_map; + PtrMap soa_values_map; }; diff --git a/src/tilde_builtin.cpp b/src/tilde_builtin.cpp index d84506e09..012e2c1b9 100644 --- a/src/tilde_builtin.cpp +++ b/src/tilde_builtin.cpp @@ -43,6 +43,26 @@ gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value) { } case Type_Struct: GB_ASSERT(is_type_soa_struct(t)); + { + if (t->Struct.soa_kind == StructSoa_Fixed) { + return cg_const_int(p, t_int, t->Struct.soa_count); + } + + GB_ASSERT(t->Struct.soa_kind == StructSoa_Slice || + t->Struct.soa_kind == StructSoa_Dynamic); + + isize n = 0; + Type *elem = base_type(t->Struct.soa_elem); + if (elem->kind == Type_Struct) { + n = cast(isize)elem->Struct.fields.count; + } else if (elem->kind == Type_Array) { + n = cast(isize)elem->Array.count; + } else { + GB_PANIC("Unreachable"); + } + + return cg_emit_struct_ev(p, value, n); + } break; } diff --git a/src/tilde_expr.cpp b/src/tilde_expr.cpp index 6dadc5c67..ece8e0816 100644 --- a/src/tilde_expr.cpp +++ b/src/tilde_expr.cpp @@ -147,8 +147,7 @@ gb_internal cgAddr cg_build_addr_from_entity(cgProcedure *p, Entity *e, Ast *exp // NOTE(bill): Calculate the using variable every time v = cg_get_using_variable(p, e); } else if (e->flags & EntityFlag_SoaPtrField) { - GB_PANIC("TODO(bill): cg_get_soa_variable_addr"); - // return cg_get_soa_variable_addr(p, e); + return map_must_get(&p->soa_values_map, e); } @@ -3541,15 +3540,13 @@ gb_internal cgAddr cg_build_addr_index_expr(cgProcedure *p, Ast *expr) { bool deref = is_type_pointer(t); t = base_type(type_deref(t)); if (is_type_soa_struct(t)) { - GB_PANIC("TODO(bill): #soa"); - // // SOA STRUCTURES!!!! - // lbValue val = cg_build_addr_ptr(p, ie->expr); - // if (deref) { - // val = cg_emit_load(p, val); - // } + cgValue val = cg_build_addr_ptr(p, ie->expr); + if (deref) { + val = cg_emit_load(p, val); + } - // cgValue index = cg_build_expr(p, ie->index); - // return cg_addr_soa_variable(val, index, ie->index); + cgValue index = cg_build_expr(p, ie->index); + return cg_addr_soa_variable(val, index, ie->index); } if (ie->expr->tav.mode == Addressing_SoaVariable) { @@ -3788,8 +3785,7 @@ gb_internal cgAddr cg_build_addr_internal(cgProcedure *p, Ast *expr) { cgValue value = cg_build_expr(p, de->expr); cgValue ptr = cg_emit_struct_ev(p, value, 0); cgValue idx = cg_emit_struct_ev(p, value, 1); - GB_PANIC("TODO(bill): cg_addr_soa_variable"); - // return cg_addr_soa_variable(ptr, idx, nullptr); + return cg_addr_soa_variable(ptr, idx, nullptr); } cgValue addr = cg_build_expr(p, de->expr); return cg_addr(addr); diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp index 26d1ce409..a9a69e415 100644 --- a/src/tilde_proc.cpp +++ b/src/tilde_proc.cpp @@ -78,6 +78,7 @@ gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool i p->branch_regions.allocator = a; map_init(&p->variable_map); + map_init(&p->soa_values_map); TB_Linkage linkage = TB_LINKAGE_PRIVATE; if (p->is_export) { @@ -143,7 +144,7 @@ gb_internal cgProcedure *cg_procedure_create_dummy(cgModule *m, String const &li p->branch_regions.allocator = a; map_init(&p->variable_map); - + map_init(&p->soa_values_map); TB_Linkage linkage = TB_LINKAGE_PRIVATE; diff --git a/src/tilde_stmt.cpp b/src/tilde_stmt.cpp index 26faab442..e27275b04 100644 --- a/src/tilde_stmt.cpp +++ b/src/tilde_stmt.cpp @@ -1649,6 +1649,126 @@ gb_internal void cg_build_range_stmt_enum(cgProcedure *p, Type *enum_type, Type if (done_) *done_ = done; } +gb_internal void cg_build_range_stmt_struct_soa(cgProcedure *p, AstRangeStmt *rs, Scope *scope) { + Ast *expr = unparen_expr(rs->expr); + TypeAndValue tav = type_and_value_of_expr(expr); + + TB_Node *loop = nullptr; + TB_Node *body = nullptr; + TB_Node *done = nullptr; + + bool is_reverse = rs->reverse; + + cg_scope_open(p, scope); + + Ast *val0 = rs->vals.count > 0 ? cg_strip_and_prefix(rs->vals[0]) : nullptr; + Ast *val1 = rs->vals.count > 1 ? cg_strip_and_prefix(rs->vals[1]) : nullptr; + Type *val_types[2] = {}; + if (val0 != nullptr && !is_blank_ident(val0)) { + val_types[0] = type_of_expr(val0); + } + if (val1 != nullptr && !is_blank_ident(val1)) { + val_types[1] = type_of_expr(val1); + } + + cgAddr array = cg_build_addr(p, expr); + if (is_type_pointer(cg_addr_type(array))) { + array = cg_addr(cg_addr_load(p, array)); + } + cgValue count = cg_builtin_len(p, cg_addr_load(p, array)); + + + cgAddr index = cg_add_local(p, t_int, nullptr, false); + + if (!is_reverse) { + /* + for x, i in array { + ... + } + + i := -1 + for { + i += 1 + if !(i < len(array)) { + break + } + x := array[i] // but #soa-ified + ... + } + */ + + cg_addr_store(p, index, cg_const_int(p, t_int, cast(u64)-1)); + + loop = cg_control_region(p, "for_soa_loop"); + cg_emit_goto(p, loop); + tb_inst_set_control(p->func, loop); + + cgValue incr = cg_emit_arith(p, Token_Add, cg_addr_load(p, index), cg_const_int(p, t_int, 1), t_int); + cg_addr_store(p, index, incr); + + body = cg_control_region(p, "for_soa_body"); + done = cg_control_region(p, "for_soa_done"); + + cgValue cond = cg_emit_comp(p, Token_Lt, incr, count); + cg_emit_if(p, cond, body, done); + } else { + // NOTE(bill): REVERSED LOGIC + /* + #reverse for x, i in array { + ... + } + + i := len(array) + for { + i -= 1 + if i < 0 { + break + } + #no_bounds_check x := array[i] // but #soa-ified + ... + } + */ + cg_addr_store(p, index, count); + + loop = cg_control_region(p, "for_soa_loop"); + cg_emit_goto(p, loop); + tb_inst_set_control(p->func, loop); + + cgValue incr = cg_emit_arith(p, Token_Sub, cg_addr_load(p, index), cg_const_int(p, t_int, 1), t_int); + cg_addr_store(p, index, incr); + + body = cg_control_region(p, "for_soa_body"); + done = cg_control_region(p, "for_soa_done"); + + cgValue cond = cg_emit_comp(p, Token_Lt, incr, cg_const_int(p, t_int, 0)); + cg_emit_if(p, cond, done, body); + } + tb_inst_set_control(p->func, body); + + + if (val_types[0]) { + Entity *e = entity_of_node(val0); + if (e != nullptr) { + cgAddr soa_val = cg_addr_soa_variable(array.addr, cg_addr_load(p, index), nullptr); + map_set(&p->soa_values_map, e, soa_val); + } + } + if (val_types[1]) { + cg_range_stmt_store_val(p, val1, cg_addr_load(p, index)); + } + + + cg_push_target_list(p, rs->label, done, loop, nullptr); + + cg_build_stmt(p, rs->body); + + cg_scope_close(p, cgDeferExit_Default, nullptr); + cg_pop_target_list(p); + cg_emit_goto(p, loop); + tb_inst_set_control(p->func, done); + +} + gb_internal void cg_build_range_stmt(cgProcedure *p, Ast *node) { ast_node(rs, RangeStmt, node); @@ -1664,8 +1784,7 @@ gb_internal void cg_build_range_stmt(cgProcedure *p, Ast *node) { if (expr_type != nullptr) { Type *et = base_type(type_deref(expr_type)); if (is_type_soa_struct(et)) { - GB_PANIC("TODO(bill): #soa array range statements"); - // cg_build_range_stmt_struct_soa(p, rs, scope); + cg_build_range_stmt_struct_soa(p, rs, rs->scope); return; } }