mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Support #soa array iteration in a for in loop for -llvm-api backend only
This commit is contained in:
+12
-1
@@ -1661,6 +1661,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
|
|||||||
auto entities = array_make<Entity *>(temporary_allocator(), 0, 2);
|
auto entities = array_make<Entity *>(temporary_allocator(), 0, 2);
|
||||||
bool is_map = false;
|
bool is_map = false;
|
||||||
bool use_by_reference_for_value = false;
|
bool use_by_reference_for_value = false;
|
||||||
|
bool is_soa = false;
|
||||||
|
|
||||||
Ast *expr = unparen_expr(rs->expr);
|
Ast *expr = unparen_expr(rs->expr);
|
||||||
|
|
||||||
@@ -1775,7 +1776,12 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
|
|||||||
|
|
||||||
case Type_Struct:
|
case Type_Struct:
|
||||||
if (t->Struct.soa_kind != StructSoa_None) {
|
if (t->Struct.soa_kind != StructSoa_None) {
|
||||||
error(operand.expr, "#soa structures do not yet support for in loop iteration");
|
is_soa = true;
|
||||||
|
array_add(&vals, t->Struct.soa_elem);
|
||||||
|
array_add(&vals, t_int);
|
||||||
|
if (!build_context.use_llvm_api) {
|
||||||
|
error(operand.expr, "#soa structures do not yet support for in loop iteration");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1836,6 +1842,11 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
|
|||||||
entity->flags &= ~EntityFlag_Value;
|
entity->flags &= ~EntityFlag_Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_soa) {
|
||||||
|
if (i == 0) {
|
||||||
|
entity->flags |= EntityFlag_SoaPtrField;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
add_entity_definition(&ctx->checker->info, name, entity);
|
add_entity_definition(&ctx->checker->info, name, entity);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+101
-7
@@ -416,7 +416,9 @@ void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) {
|
|||||||
Type *t = base_type(type_deref(addr.addr.type));
|
Type *t = base_type(type_deref(addr.addr.type));
|
||||||
GB_ASSERT(t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None);
|
GB_ASSERT(t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None);
|
||||||
lbValue len = lb_soa_struct_len(p, addr.addr);
|
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;
|
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);
|
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);
|
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 dst = lb_emit_struct_ep(p, res.addr, cast(i32)i);
|
||||||
lbValue src_ptr = lb_emit_struct_ep(p, addr.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);
|
lbValue src = lb_emit_load(p, src_ptr);
|
||||||
|
src = lb_emit_ptr_offset(p, src, addr.soa.index);
|
||||||
src = lb_emit_load(p, src);
|
src = lb_emit_load(p, src);
|
||||||
lb_emit_store(p, dst, 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;
|
break;
|
||||||
}
|
}
|
||||||
|
case Type_Struct: {
|
||||||
|
GB_ASSERT(is_type_soa_struct(expr_type));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
GB_PANIC("Cannot do range_indexed of %s", type_to_string(expr_type));
|
GB_PANIC("Cannot do range_indexed of %s", type_to_string(expr_type));
|
||||||
break;
|
break;
|
||||||
@@ -3884,7 +3891,87 @@ void lb_build_range_tuple(lbProcedure *p, Ast *expr, Type *val0_type, Type *val1
|
|||||||
if (done_) *done_ = done;
|
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) {
|
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);
|
lb_open_scope(p, scope);
|
||||||
|
|
||||||
Type *val0_type = nullptr;
|
Type *val0_type = nullptr;
|
||||||
@@ -3909,11 +3996,10 @@ void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *scope) {
|
|||||||
lbValue key = {};
|
lbValue key = {};
|
||||||
lbBlock *loop = nullptr;
|
lbBlock *loop = nullptr;
|
||||||
lbBlock *done = nullptr;
|
lbBlock *done = nullptr;
|
||||||
Ast *expr = unparen_expr(rs->expr);
|
|
||||||
bool is_map = false;
|
bool is_map = false;
|
||||||
|
|
||||||
TypeAndValue tav = type_and_value_of_expr(expr);
|
TypeAndValue tav = type_and_value_of_expr(expr);
|
||||||
|
|
||||||
|
|
||||||
if (is_ast_range(expr)) {
|
if (is_ast_range(expr)) {
|
||||||
lb_build_range_interval(p, &expr->BinaryExpr, val0_type, &val, &key, &loop, &done);
|
lb_build_range_interval(p, &expr->BinaryExpr, val0_type, &val, &key, &loop, &done);
|
||||||
} else if (tav.mode == Addressing_Type) {
|
} else if (tav.mode == Addressing_Type) {
|
||||||
@@ -10622,6 +10708,11 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
|||||||
return {};
|
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) {
|
lbValue lb_get_using_variable(lbProcedure *p, Entity *e) {
|
||||||
GB_ASSERT(e->kind == Entity_Variable && e->flags & EntityFlag_Using);
|
GB_ASSERT(e->kind == Entity_Variable && e->flags & EntityFlag_Using);
|
||||||
String name = e->token.string;
|
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) {
|
} else if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) {
|
||||||
// NOTE(bill): Calculate the using variable every time
|
// NOTE(bill): Calculate the using variable every time
|
||||||
v = lb_get_using_variable(p, e);
|
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) {
|
if (v.value == nullptr) {
|
||||||
@@ -10901,7 +10994,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
|||||||
GB_ASSERT(is_type_soa_struct(t));
|
GB_ASSERT(is_type_soa_struct(t));
|
||||||
|
|
||||||
// TODO(bill): Bounds check
|
// 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);
|
lbValue len = lb_soa_struct_len(p, addr.addr);
|
||||||
lb_emit_bounds_check(p, ast_token(addr.soa.index_expr), addr.soa.index, len);
|
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) {
|
if (t->Struct.soa_kind == StructSoa_Fixed) {
|
||||||
item = lb_emit_array_ep(p, arr, index);
|
item = lb_emit_array_ep(p, arr, index);
|
||||||
} else {
|
} 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) {
|
if (sub_sel.index.count > 0) {
|
||||||
item = lb_emit_deep_field_gep(p, item, sub_sel);
|
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->types, a);
|
||||||
map_init(&m->llvm_types, a);
|
map_init(&m->llvm_types, a);
|
||||||
map_init(&m->values, a);
|
map_init(&m->values, a);
|
||||||
|
map_init(&m->soa_values, a);
|
||||||
string_map_init(&m->members, a);
|
string_map_init(&m->members, a);
|
||||||
map_init(&m->procedure_values, a);
|
map_init(&m->procedure_values, a);
|
||||||
string_map_init(&m->procedures, a);
|
string_map_init(&m->procedures, a);
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ struct lbModule {
|
|||||||
i32 internal_type_level;
|
i32 internal_type_level;
|
||||||
|
|
||||||
Map<lbValue> values; // Key: Entity *
|
Map<lbValue> values; // Key: Entity *
|
||||||
|
Map<lbAddr> soa_values; // Key: Entity *
|
||||||
StringMap<lbValue> members;
|
StringMap<lbValue> members;
|
||||||
StringMap<lbProcedure *> procedures;
|
StringMap<lbProcedure *> procedures;
|
||||||
Map<Entity *> procedure_values; // Key: LLVMValueRef
|
Map<Entity *> procedure_values; // Key: LLVMValueRef
|
||||||
|
|||||||
Reference in New Issue
Block a user