diff options
| author | gingerBill <bill@gingerbill.org> | 2023-08-07 15:04:03 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2023-08-07 15:04:03 +0100 |
| commit | 55c9fb7c5c416ff0b94d0a9a531c41662a4eeb54 (patch) | |
| tree | 3147103c25b86ac4c6bb1f4dccfe1a595ad669f3 /src/tilde_stmt.cpp | |
| parent | 8201a9ce6ea1d2a89d51f891305d27f5196dc6c9 (diff) | |
Tilde: Begin work on #soa
Diffstat (limited to 'src/tilde_stmt.cpp')
| -rw-r--r-- | src/tilde_stmt.cpp | 123 |
1 files changed, 121 insertions, 2 deletions
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; } } |