Browse Source

Tilde: Begin work on #soa

gingerBill 2 years ago
parent
commit
55c9fb7c5c
6 changed files with 160 additions and 15 deletions
  1. 8 0
      src/tilde.cpp
  2. 1 0
      src/tilde.hpp
  3. 20 0
      src/tilde_builtin.cpp
  4. 8 12
      src/tilde_expr.cpp
  5. 2 1
      src/tilde_proc.cpp
  6. 121 2
      src/tilde_stmt.cpp

+ 8 - 0
src/tilde.cpp

@@ -201,6 +201,14 @@ gb_internal cgAddr cg_addr_map(cgValue addr, cgValue map_key, Type *map_type, Ty
 	return v;
 }
 
+gb_internal cgAddr cg_addr_soa_variable(cgValue addr, cgValue index, Ast *index_expr) {
+	cgAddr v = {cgAddr_SoaVariable, addr};
+	v.soa.index = index;
+	v.soa.index_expr = index_expr;
+	return v;
+}
+
+
 
 gb_internal void cg_set_debug_pos_from_node(cgProcedure *p, Ast *node) {
 	if (node) {

+ 1 - 0
src/tilde.hpp

@@ -202,6 +202,7 @@ struct cgProcedure {
 	bool   return_by_ptr;
 
 	PtrMap<Entity *, cgAddr> variable_map;
+	PtrMap<Entity *, cgAddr> soa_values_map;
 };
 
 

+ 20 - 0
src/tilde_builtin.cpp

@@ -43,6 +43,26 @@ gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value) {
 		}
 	case Type_Struct:
 		GB_ASSERT(is_type_soa_struct(t));
+		{
+			if (t->Struct.soa_kind == StructSoa_Fixed) {
+				return cg_const_int(p, t_int, t->Struct.soa_count);
+			}
+
+			GB_ASSERT(t->Struct.soa_kind == StructSoa_Slice ||
+			          t->Struct.soa_kind == StructSoa_Dynamic);
+
+			isize n = 0;
+			Type *elem = base_type(t->Struct.soa_elem);
+			if (elem->kind == Type_Struct) {
+				n = cast(isize)elem->Struct.fields.count;
+			} else if (elem->kind == Type_Array) {
+				n = cast(isize)elem->Array.count;
+			} else {
+				GB_PANIC("Unreachable");
+			}
+
+			return cg_emit_struct_ev(p, value, n);
+		}
 		break;
 	}
 

+ 8 - 12
src/tilde_expr.cpp

@@ -147,8 +147,7 @@ gb_internal cgAddr cg_build_addr_from_entity(cgProcedure *p, Entity *e, Ast *exp
 		// NOTE(bill): Calculate the using variable every time
 		v = cg_get_using_variable(p, e);
 	} else if (e->flags & EntityFlag_SoaPtrField) {
-		GB_PANIC("TODO(bill): cg_get_soa_variable_addr");
-		// return cg_get_soa_variable_addr(p, e);
+		return map_must_get(&p->soa_values_map, e);
 	}
 
 
@@ -3541,15 +3540,13 @@ gb_internal cgAddr cg_build_addr_index_expr(cgProcedure *p, Ast *expr) {
 	bool deref = is_type_pointer(t);
 	t = base_type(type_deref(t));
 	if (is_type_soa_struct(t)) {
-		GB_PANIC("TODO(bill): #soa");
-		// // SOA STRUCTURES!!!!
-		// lbValue val = cg_build_addr_ptr(p, ie->expr);
-		// if (deref) {
-		// 	val = cg_emit_load(p, val);
-		// }
+		cgValue val = cg_build_addr_ptr(p, ie->expr);
+		if (deref) {
+			val = cg_emit_load(p, val);
+		}
 
-		// cgValue index = cg_build_expr(p, ie->index);
-		// return cg_addr_soa_variable(val, index, ie->index);
+		cgValue index = cg_build_expr(p, ie->index);
+		return cg_addr_soa_variable(val, index, ie->index);
 	}
 
 	if (ie->expr->tav.mode == Addressing_SoaVariable) {
@@ -3788,8 +3785,7 @@ gb_internal cgAddr cg_build_addr_internal(cgProcedure *p, Ast *expr) {
 			cgValue value = cg_build_expr(p, de->expr);
 			cgValue ptr = cg_emit_struct_ev(p, value, 0);
 			cgValue idx = cg_emit_struct_ev(p, value, 1);
-			GB_PANIC("TODO(bill): cg_addr_soa_variable");
-			// return cg_addr_soa_variable(ptr, idx, nullptr);
+			return cg_addr_soa_variable(ptr, idx, nullptr);
 		}
 		cgValue addr = cg_build_expr(p, de->expr);
 		return cg_addr(addr);

+ 2 - 1
src/tilde_proc.cpp

@@ -78,6 +78,7 @@ gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool i
 	p->branch_regions.allocator = a;
 
 	map_init(&p->variable_map);
+	map_init(&p->soa_values_map);
 
 	TB_Linkage linkage = TB_LINKAGE_PRIVATE;
 	if (p->is_export) {
@@ -143,7 +144,7 @@ gb_internal cgProcedure *cg_procedure_create_dummy(cgModule *m, String const &li
 	p->branch_regions.allocator = a;
 
 	map_init(&p->variable_map);
-
+	map_init(&p->soa_values_map);
 
 	TB_Linkage linkage = TB_LINKAGE_PRIVATE;
 

+ 121 - 2
src/tilde_stmt.cpp

@@ -1649,6 +1649,126 @@ gb_internal void cg_build_range_stmt_enum(cgProcedure *p, Type *enum_type, Type
 	if (done_) *done_ = done;
 }
 
+gb_internal void cg_build_range_stmt_struct_soa(cgProcedure *p, AstRangeStmt *rs, Scope *scope) {
+	Ast *expr = unparen_expr(rs->expr);
+	TypeAndValue tav = type_and_value_of_expr(expr);
+
+	TB_Node *loop = nullptr;
+	TB_Node *body = nullptr;
+	TB_Node *done = nullptr;
+
+	bool is_reverse = rs->reverse;
+
+	cg_scope_open(p, scope);
+
+	Ast *val0 = rs->vals.count > 0 ? cg_strip_and_prefix(rs->vals[0]) : nullptr;
+	Ast *val1 = rs->vals.count > 1 ? cg_strip_and_prefix(rs->vals[1]) : nullptr;
+	Type *val_types[2] = {};
+	if (val0 != nullptr && !is_blank_ident(val0)) {
+		val_types[0] = type_of_expr(val0);
+	}
+	if (val1 != nullptr && !is_blank_ident(val1)) {
+		val_types[1] = type_of_expr(val1);
+	}
+
+	cgAddr array = cg_build_addr(p, expr);
+	if (is_type_pointer(cg_addr_type(array))) {
+		array = cg_addr(cg_addr_load(p, array));
+	}
+	cgValue count = cg_builtin_len(p, cg_addr_load(p, array));
+
+
+	cgAddr index = cg_add_local(p, t_int, nullptr, false);
+
+	if (!is_reverse) {
+		/*
+			for x, i in array {
+				...
+			}
+
+			i := -1
+			for {
+				i += 1
+				if !(i < len(array)) {
+					break
+				}
+				x := array[i] // but #soa-ified
+				...
+			}
+		*/
+
+		cg_addr_store(p, index, cg_const_int(p, t_int, cast(u64)-1));
+
+		loop = cg_control_region(p, "for_soa_loop");
+		cg_emit_goto(p, loop);
+		tb_inst_set_control(p->func, loop);
+
+		cgValue incr = cg_emit_arith(p, Token_Add, cg_addr_load(p, index), cg_const_int(p, t_int, 1), t_int);
+		cg_addr_store(p, index, incr);
+
+		body = cg_control_region(p, "for_soa_body");
+		done = cg_control_region(p, "for_soa_done");
+
+		cgValue cond = cg_emit_comp(p, Token_Lt, incr, count);
+		cg_emit_if(p, cond, body, done);
+	} else {
+		// NOTE(bill): REVERSED LOGIC
+		/*
+			#reverse for x, i in array {
+				...
+			}
+
+			i := len(array)
+			for {
+				i -= 1
+				if i < 0 {
+					break
+				}
+				#no_bounds_check x := array[i] // but #soa-ified
+				...
+			}
+		*/
+		cg_addr_store(p, index, count);
+
+		loop = cg_control_region(p, "for_soa_loop");
+		cg_emit_goto(p, loop);
+		tb_inst_set_control(p->func, loop);
+
+		cgValue incr = cg_emit_arith(p, Token_Sub, cg_addr_load(p, index), cg_const_int(p, t_int, 1), t_int);
+		cg_addr_store(p, index, incr);
+
+		body = cg_control_region(p, "for_soa_body");
+		done = cg_control_region(p, "for_soa_done");
+
+		cgValue cond = cg_emit_comp(p, Token_Lt, incr, cg_const_int(p, t_int, 0));
+		cg_emit_if(p, cond, done, body);
+	}
+	tb_inst_set_control(p->func, body);
+
+
+	if (val_types[0]) {
+		Entity *e = entity_of_node(val0);
+		if (e != nullptr) {
+			cgAddr soa_val = cg_addr_soa_variable(array.addr, cg_addr_load(p, index), nullptr);
+			map_set(&p->soa_values_map, e, soa_val);
+		}
+	}
+	if (val_types[1]) {
+		cg_range_stmt_store_val(p, val1, cg_addr_load(p, index));
+	}
+
+
+	cg_push_target_list(p, rs->label, done, loop, nullptr);
+
+	cg_build_stmt(p, rs->body);
+
+	cg_scope_close(p, cgDeferExit_Default, nullptr);
+	cg_pop_target_list(p);
+	cg_emit_goto(p, loop);
+	tb_inst_set_control(p->func, done);
+
+}
+
 
 gb_internal void cg_build_range_stmt(cgProcedure *p, Ast *node) {
 	ast_node(rs, RangeStmt, node);
@@ -1664,8 +1784,7 @@ gb_internal void cg_build_range_stmt(cgProcedure *p, Ast *node) {
 	if (expr_type != nullptr) {
 		Type *et = base_type(type_deref(expr_type));
 	 	if (is_type_soa_struct(et)) {
-	 		GB_PANIC("TODO(bill): #soa array range statements");
-			// cg_build_range_stmt_struct_soa(p, rs, scope);
+			cg_build_range_stmt_struct_soa(p, rs, rs->scope);
 			return;
 		}
 	}