diff options
Diffstat (limited to 'src/llvm_backend.cpp')
| -rw-r--r-- | src/llvm_backend.cpp | 108 |
1 files changed, 101 insertions, 7 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index d09c55b79..e05773767 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -416,7 +416,9 @@ void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) { Type *t = base_type(type_deref(addr.addr.type)); GB_ASSERT(t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None); lbValue len = lb_soa_struct_len(p, addr.addr); - lb_emit_bounds_check(p, ast_token(addr.soa.index_expr), index, len); + if (addr.soa.index_expr != nullptr) { + lb_emit_bounds_check(p, ast_token(addr.soa.index_expr), index, len); + } } isize field_count = 0; @@ -640,7 +642,7 @@ lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) { lbAddr res = lb_add_local_generated(p, elem, true); - if (!lb_is_const(addr.soa.index) || t->Struct.soa_kind != StructSoa_Fixed) { + if (addr.soa.index_expr != nullptr && (!lb_is_const(addr.soa.index) || t->Struct.soa_kind != StructSoa_Fixed)) { lb_emit_bounds_check(p, ast_token(addr.soa.index_expr), addr.soa.index, len); } @@ -671,8 +673,8 @@ lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) { lbValue dst = lb_emit_struct_ep(p, res.addr, cast(i32)i); lbValue src_ptr = lb_emit_struct_ep(p, addr.addr, cast(i32)i); - src_ptr = lb_emit_ptr_offset(p, src_ptr, addr.soa.index); lbValue src = lb_emit_load(p, src_ptr); + src = lb_emit_ptr_offset(p, src, addr.soa.index); src = lb_emit_load(p, src); lb_emit_store(p, dst, src); } @@ -3673,6 +3675,11 @@ void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValu break; } + case Type_Struct: { + GB_ASSERT(is_type_soa_struct(expr_type)); + break; + } + default: GB_PANIC("Cannot do range_indexed of %s", type_to_string(expr_type)); break; @@ -3884,7 +3891,87 @@ void lb_build_range_tuple(lbProcedure *p, Ast *expr, Type *val0_type, Type *val1 if (done_) *done_ = done; } +void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs, Scope *scope) { + Ast *expr = unparen_expr(rs->expr); + TypeAndValue tav = type_and_value_of_expr(expr); + + lbBlock *loop = nullptr; + lbBlock *body = nullptr; + lbBlock *done = nullptr; + + lb_open_scope(p, scope); + + + Type *val_types[2] = {}; + if (rs->vals.count > 0 && rs->vals[0] != nullptr && !is_blank_ident(rs->vals[0])) { + val_types[0] = type_of_expr(rs->vals[0]); + } + if (rs->vals.count > 1 && rs->vals[1] != nullptr && !is_blank_ident(rs->vals[1])) { + val_types[1] = type_of_expr(rs->vals[1]); + } + + + + lbAddr array = lb_build_addr(p, expr); + if (is_type_pointer(type_deref(lb_addr_type(array)))) { + array = lb_addr(lb_addr_load(p, array)); + } + lbValue count = lb_soa_struct_len(p, lb_addr_load(p, array)); + + + lbAddr index = lb_add_local_generated(p, t_int, false); + lb_addr_store(p, index, lb_const_int(p->module, t_int, cast(u64)-1)); + + loop = lb_create_block(p, "for.soa.loop"); + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + lbValue incr = lb_emit_arith(p, Token_Add, lb_addr_load(p, index), lb_const_int(p->module, t_int, 1), t_int); + lb_addr_store(p, index, incr); + + body = lb_create_block(p, "for.soa.body"); + done = lb_create_block(p, "for.soa.done"); + + lbValue cond = lb_emit_comp(p, Token_Lt, incr, count); + lb_emit_if(p, cond, body, done); + lb_start_block(p, body); + + + if (val_types[0]) { + Entity *e = entity_of_node(rs->vals[0]); + if (e != nullptr) { + lbAddr soa_val = lb_addr_soa_variable(array.addr, lb_addr_load(p, index), nullptr); + map_set(&p->module->soa_values, hash_entity(e), soa_val); + } + } + if (val_types[1]) { + lb_store_range_stmt_val(p, rs->vals[1], lb_addr_load(p, index)); + } + + + lb_push_target_list(p, rs->label, done, loop, nullptr); + + lb_build_stmt(p, rs->body); + + lb_close_scope(p, lbDeferExit_Default, nullptr); + lb_pop_target_list(p); + lb_emit_jump(p, loop); + lb_start_block(p, done); + +} + void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *scope) { + Ast *expr = unparen_expr(rs->expr); + + Type *expr_type = type_of_expr(expr); + if (expr_type != nullptr) { + Type *et = base_type(type_deref(expr_type)); + if (is_type_soa_struct(et)) { + lb_build_range_stmt_struct_soa(p, rs, scope); + return; + } + } + lb_open_scope(p, scope); Type *val0_type = nullptr; @@ -3909,11 +3996,10 @@ void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *scope) { lbValue key = {}; lbBlock *loop = nullptr; lbBlock *done = nullptr; - Ast *expr = unparen_expr(rs->expr); bool is_map = false; - TypeAndValue tav = type_and_value_of_expr(expr); + if (is_ast_range(expr)) { lb_build_range_interval(p, &expr->BinaryExpr, val0_type, &val, &key, &loop, &done); } else if (tav.mode == Addressing_Type) { @@ -10622,6 +10708,11 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) { return {}; } +lbAddr lb_get_soa_variable_addr(lbProcedure *p, Entity *e) { + lbAddr *found = map_get(&p->module->soa_values, hash_entity(e)); + GB_ASSERT(found != nullptr); + return *found; +} lbValue lb_get_using_variable(lbProcedure *p, Entity *e) { GB_ASSERT(e->kind == Entity_Variable && e->flags & EntityFlag_Using); String name = e->token.string; @@ -10661,6 +10752,8 @@ lbAddr lb_build_addr_from_entity(lbProcedure *p, Entity *e, Ast *expr) { } else if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) { // NOTE(bill): Calculate the using variable every time v = lb_get_using_variable(p, e); + } else if (e->flags & EntityFlag_SoaPtrField) { + return lb_get_soa_variable_addr(p, e); } if (v.value == nullptr) { @@ -10901,7 +10994,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { GB_ASSERT(is_type_soa_struct(t)); // TODO(bill): Bounds check - if (!lb_is_const(addr.soa.index) || t->Struct.soa_kind != StructSoa_Fixed) { + if (addr.soa.index_expr != nullptr && (!lb_is_const(addr.soa.index) || t->Struct.soa_kind != StructSoa_Fixed)) { lbValue len = lb_soa_struct_len(p, addr.addr); lb_emit_bounds_check(p, ast_token(addr.soa.index_expr), addr.soa.index, len); } @@ -10911,7 +11004,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { if (t->Struct.soa_kind == StructSoa_Fixed) { item = lb_emit_array_ep(p, arr, index); } else { - item = lb_emit_load(p, lb_emit_ptr_offset(p, arr, index)); + item = lb_emit_ptr_offset(p, lb_emit_load(p, arr), index); } if (sub_sel.index.count > 0) { item = lb_emit_deep_field_gep(p, item, sub_sel); @@ -12005,6 +12098,7 @@ void lb_init_module(lbModule *m, Checker *c) { map_init(&m->types, a); map_init(&m->llvm_types, a); map_init(&m->values, a); + map_init(&m->soa_values, a); string_map_init(&m->members, a); map_init(&m->procedure_values, a); string_map_init(&m->procedures, a); |