aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-05-29 23:24:03 +0100
committergingerBill <bill@gingerbill.org>2023-05-29 23:24:03 +0100
commitf07453d0aee436ba8c0f81cedfde5db3a7bbe1b4 (patch)
tree4314776543e88f46c040e8bb7296571bbd37e683 /src
parent97490c6445cb3ba85f470e64e6ed6d24394c421a (diff)
Support `#reverse` on `#soa` arrays
Diffstat (limited to 'src')
-rw-r--r--src/check_stmt.cpp4
-rw-r--r--src/llvm_backend_stmt.cpp41
2 files changed, 32 insertions, 13 deletions
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index c64de40c7..73aaa1c37 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -1596,10 +1596,6 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
if (is_ptr) use_by_reference_for_value = true;
array_add(&vals, t->Struct.soa_elem);
array_add(&vals, t_int);
-
- if (is_reverse) {
- error(node, "#reverse for is not yet supported for #soa types");
- }
}
break;
}
diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp
index 60468c7f0..da7fdaead 100644
--- a/src/llvm_backend_stmt.cpp
+++ b/src/llvm_backend_stmt.cpp
@@ -730,6 +730,8 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs
lbBlock *body = nullptr;
lbBlock *done = nullptr;
+ bool is_reverse = rs->reverse;
+
lb_open_scope(p, scope);
@@ -751,19 +753,40 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs
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 = {};
+ lbValue cond = {};
- 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);
+ if (!is_reverse) {
+ 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);
+
+ 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");
+ 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);
+ cond = lb_emit_comp(p, Token_Lt, incr, count);
+ } else {
+ // NOTE(bill): REVERSED LOGIC
+ lb_addr_store(p, index, count);
+
+ loop = lb_create_block(p, "for.soa.loop");
+ lb_emit_jump(p, loop);
+ lb_start_block(p, loop);
+
+ incr = lb_emit_arith(p, Token_Sub, 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");
+
+ cond = lb_emit_comp(p, Token_GtEq, incr, lb_const_int(p->module, t_int, 0));
+ }
lb_emit_if(p, cond, body, done);
lb_start_block(p, body);