aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/llvm_backend.cpp')
-rw-r--r--src/llvm_backend.cpp108
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);