Browse Source

Support `#reverse` on `#soa` arrays

gingerBill 2 years ago
parent
commit
f07453d0ae
2 changed files with 32 additions and 13 deletions
  1. 0 4
      src/check_stmt.cpp
  2. 32 9
      src/llvm_backend_stmt.cpp

+ 0 - 4
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;
 					if (is_ptr) use_by_reference_for_value = true;
 					array_add(&vals, t->Struct.soa_elem);
 					array_add(&vals, t->Struct.soa_elem);
 					array_add(&vals, t_int);
 					array_add(&vals, t_int);
-
-					if (is_reverse) {
-						error(node, "#reverse for is not yet supported for #soa types");
-					}
 				}
 				}
 				break;
 				break;
 			}
 			}

+ 32 - 9
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 *body = nullptr;
 	lbBlock *done = nullptr;
 	lbBlock *done = nullptr;
 
 
+	bool is_reverse = rs->reverse;
+
 	lb_open_scope(p, scope);
 	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);
 	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_emit_if(p, cond, body, done);
 	lb_start_block(p, body);
 	lb_start_block(p, body);