Browse Source

Prepare SOA Struct code for slices and dynamic arrays *to be implemented*

gingerBill 5 years ago
parent
commit
44e0e96612
9 changed files with 112 additions and 37 deletions
  1. 2 2
      core/fmt/fmt.odin
  2. 19 3
      core/reflect/types.odin
  3. 8 0
      core/runtime/core.odin
  4. 26 7
      core/runtime/internal.odin
  5. 10 5
      src/check_expr.cpp
  6. 2 2
      src/check_type.cpp
  7. 9 2
      src/checker.cpp
  8. 16 9
      src/ir.cpp
  9. 20 7
      src/types.cpp

+ 2 - 2
core/fmt/fmt.odin

@@ -1086,7 +1086,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 				return;
 			};
 
-			is_soa := b.soa_base_type != nil;
+			is_soa := b.soa_kind != .None;
 
 			strings.write_string(fi.buf, info.name);
 			strings.write_byte(fi.buf, is_soa ? '[' : '{');
@@ -1329,7 +1329,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 			return;
 		}
 
-		is_soa := info.soa_base_type != nil;
+		is_soa := info.soa_kind != .None;
 
 		strings.write_byte(fi.buf, is_soa ? '[' : '{');
 		defer strings.write_byte(fi.buf, is_soa ? ']' : '}');

+ 19 - 3
core/reflect/types.odin

@@ -162,6 +162,11 @@ are_types_identical :: proc(a, b: ^rt.Type_Info) -> bool {
 		y, ok := b.variant.(rt.Type_Info_Opaque);
 		if !ok do return false;
 		return x.elem == y.elem;
+
+	case rt.Type_Info_Simd_Vector:
+		y, ok := b.variant.(rt.Type_Info_Simd_Vector);
+		if !ok do return false;
+		return x.count == y.count && x.elem == y.elem;
 	}
 
 	return false;
@@ -394,13 +399,24 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
 		write_type(buf, info.value);
 
 	case rt.Type_Info_Struct:
-		if info.soa_base_type != nil {
+		#complete switch info.soa_kind {
+		case .None: // Ignore
+		case .Fixed:
 			write_string(buf, "#soa[");
 			write_i64(buf, i64(info.soa_len));
 			write_byte(buf, ']');
 			write_type(buf, info.soa_base_type);
-			break;
-		}	
+			return;
+		case .Slice:
+			write_string(buf, "#soa[]");
+			write_type(buf, info.soa_base_type);
+			return;
+		case .Dynamic:
+			write_string(buf, "#soa[dynamic]");
+			write_type(buf, info.soa_base_type);
+			return;
+		}
+
 		write_string(buf, "struct ");
 		if info.is_packed    do write_string(buf, "#packed ");
 		if info.is_raw_union do write_string(buf, "#raw_union ");

+ 8 - 0
core/runtime/core.odin

@@ -47,6 +47,13 @@ Platform_Endianness :: enum u8 {
 	Big      = 2,
 }
 
+Type_Info_Struct_Soa_Kind :: enum u8 {
+	None    = 0,
+	Fixed   = 1,
+	Slice   = 2,
+	Dynamic = 3,
+}
+
 // Variant Types
 Type_Info_Named      :: struct {name: string, base: ^Type_Info};
 Type_Info_Integer    :: struct {signed: bool, endianness: Platform_Endianness};
@@ -88,6 +95,7 @@ Type_Info_Struct :: struct {
 	is_raw_union: bool,
 	custom_align: bool,
 	// These are only set iff this structure is an SOA structure
+	soa_kind:      Type_Info_Struct_Soa_Kind,
 	soa_base_type: ^Type_Info,
 	soa_len:       int,
 };

+ 26 - 7
core/runtime/internal.odin

@@ -137,7 +137,7 @@ print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
 			os.write_string(fd, "()");
 		} else {
 			t := info.params.variant.(Type_Info_Tuple);
-			os.write_string(fd, "(");
+			os.write_byte(fd, '(');
 			for t, i in t.types {
 				if i > 0 do os.write_string(fd, ", ");
 				print_type(fd, t);
@@ -150,7 +150,7 @@ print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
 		}
 	case Type_Info_Tuple:
 		count := len(info.names);
-		if count != 1 do os.write_string(fd, "(");
+		if count != 1 do os.write_byte(fd, '(');
 		for name, i in info.names {
 			if i > 0 do os.write_string(fd, ", ");
 
@@ -165,9 +165,9 @@ print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
 		if count != 1 do os.write_string(fd, ")");
 
 	case Type_Info_Array:
-		os.write_string(fd, "[");
+		os.write_byte(fd, '[');
 		print_u64(fd, u64(info.count));
-		os.write_string(fd, "]");
+		os.write_byte(fd, ']');
 		print_type(fd, info.elem);
 	case Type_Info_Dynamic_Array:
 		os.write_string(fd, "[dynamic]");
@@ -183,13 +183,24 @@ print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
 		print_type(fd, info.value);
 
 	case Type_Info_Struct:
-		if info.soa_base_type != nil {
+		#complete switch info.soa_kind {
+		case .None: // Ignore
+		case .Fixed:
 			os.write_string(fd, "#soa[");
 			print_u64(fd, u64(info.soa_len));
 			os.write_byte(fd, ']');
 			print_type(fd, info.soa_base_type);
-			break;
+			return;
+		case .Slice:
+			os.write_string(fd, "#soa[]");
+			print_type(fd, info.soa_base_type);
+			return;
+		case .Dynamic:
+			os.write_string(fd, "#soa[dynamic]");
+			print_type(fd, info.soa_base_type);
+			return;
 		}
+
 		os.write_string(fd, "struct ");
 		if info.is_packed    do os.write_string(fd, "#packed ");
 		if info.is_raw_union do os.write_string(fd, "#raw_union ");
@@ -208,7 +219,15 @@ print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
 		os.write_byte(fd, '}');
 
 	case Type_Info_Union:
-		os.write_string(fd, "union {");
+		os.write_string(fd, "union ");
+		if info.custom_align {
+			os.write_string(fd, "#align ");
+			print_u64(fd, u64(ti.align));
+		}
+		if info.no_nil {
+			os.write_string(fd, "#no_nil ");
+		}
+		os.write_byte(fd, '{');
 		for variant, i in info.variants {
 			if i > 0 do os.write_string(fd, ", ");
 			print_type(fd, variant);

+ 10 - 5
src/check_expr.cpp

@@ -3631,10 +3631,13 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 			type  = t_untyped_integer;
 		} else if (is_type_struct(op_type)) {
 			Type *bt = base_type(op_type);
-			if (bt->Struct.is_soa) {
+			if (bt->Struct.soa_kind == StructSoa_Fixed) {
 				mode  = Addressing_Constant;
 				value = exact_value_i64(bt->Struct.soa_count);
 				type  = t_untyped_integer;
+			} else if ((bt->Struct.soa_kind == StructSoa_Slice && id == BuiltinProc_len) ||
+			           bt->Struct.soa_kind == StructSoa_Dynamic) {
+				mode = Addressing_Value;
 			}
 		}
 
@@ -4801,7 +4804,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 			soa_struct->Struct.fields = array_make<Entity *>(heap_allocator(), old_array->Array.count);
 			soa_struct->Struct.tags = array_make<String>(heap_allocator(), old_array->Array.count);
 			soa_struct->Struct.node = operand->expr;
-			soa_struct->Struct.is_soa = true;
+			soa_struct->Struct.soa_kind = StructSoa_Fixed;
 			soa_struct->Struct.soa_elem = elem;
 			soa_struct->Struct.soa_count = count;
 
@@ -4834,7 +4837,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 			soa_struct->Struct.fields = array_make<Entity *>(heap_allocator(), old_struct->Struct.fields.count);
 			soa_struct->Struct.tags = array_make<String>(heap_allocator(), old_struct->Struct.tags.count);
 			soa_struct->Struct.node = operand->expr;
-			soa_struct->Struct.is_soa = true;
+			soa_struct->Struct.soa_kind = StructSoa_Fixed;
 			soa_struct->Struct.soa_elem = elem;
 			soa_struct->Struct.soa_count = count;
 
@@ -6778,8 +6781,10 @@ bool check_set_index_data(Operand *o, Type *t, bool indirection, i64 *max_count)
 		}
 		return true;
 	case Type_Struct:
-		if (t->Struct.is_soa) {
-			*max_count = t->Struct.soa_count;
+		if (t->Struct.soa_kind != StructSoa_None) {
+			if (t->Struct.soa_kind == StructSoa_Fixed) {
+				*max_count = t->Struct.soa_count;
+			}
 			o->type = t->Struct.soa_elem;
 			if (o->mode == Addressing_SoaVariable || o->mode == Addressing_Variable) {
 				o->mode = Addressing_SoaVariable;

+ 2 - 2
src/check_type.cpp

@@ -2907,7 +2907,7 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
 						soa_struct->Struct.fields = array_make<Entity *>(heap_allocator(), old_array->Array.count);
 						soa_struct->Struct.tags = array_make<String>(heap_allocator(), old_array->Array.count);
 						soa_struct->Struct.node = e;
-						soa_struct->Struct.is_soa = true;
+						soa_struct->Struct.soa_kind = StructSoa_Fixed;
 						soa_struct->Struct.soa_elem = elem;
 						soa_struct->Struct.soa_count = count;
 
@@ -2940,7 +2940,7 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
 						soa_struct->Struct.fields = array_make<Entity *>(heap_allocator(), old_struct->Struct.fields.count);
 						soa_struct->Struct.tags = array_make<String>(heap_allocator(), old_struct->Struct.tags.count);
 						soa_struct->Struct.node = e;
-						soa_struct->Struct.is_soa = true;
+						soa_struct->Struct.soa_kind = StructSoa_Fixed;
 						soa_struct->Struct.soa_elem = elem;
 						soa_struct->Struct.soa_count = count;
 

+ 9 - 2
src/checker.cpp

@@ -1342,10 +1342,17 @@ void add_type_info_type(CheckerContext *c, Type *t) {
 		if (bt->Struct.scope != nullptr) {
 			for_array(i, bt->Struct.scope->elements.entries) {
 				Entity *e = bt->Struct.scope->elements.entries[i].value;
-				if (bt->Struct.is_soa) {
+				switch (bt->Struct.soa_kind) {
+				case StructSoa_Dynamic:
+					add_type_info_type(c, t_allocator);
+					/*fallthrough*/
+				case StructSoa_Slice:
+				case StructSoa_Fixed:
 					add_type_info_type(c, alloc_type_pointer(e->type));
-				} else {
+					break;
+				default:
 					add_type_info_type(c, e->type);
+					break;
 				}
 			}
 		}

+ 16 - 9
src/ir.cpp

@@ -3564,13 +3564,13 @@ void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) {
 	} else if (addr.kind == irAddr_SoaVariable) {
 		Type *t = type_deref(ir_type(addr.addr));
 		t = base_type(t);
-		GB_ASSERT(t->kind == Type_Struct && t->Struct.is_soa);
+		GB_ASSERT(t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None);
 		value = ir_emit_conv(proc, value, t->Struct.soa_elem);
 
 		irValue *index = addr.soa.index;
 		if (index->kind != irValue_Constant) {
 			Type *t = base_type(type_deref(ir_type(addr.addr)));
-			GB_ASSERT(t->kind == Type_Struct && t->Struct.is_soa);
+			GB_ASSERT(t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None);
 			i64 count = t->Struct.soa_count;
 			irValue *len = ir_const_int(count);
 			ir_emit_bounds_check(proc, ast_token(addr.soa.index_expr), index, len);
@@ -3695,8 +3695,8 @@ irValue *ir_addr_load(irProcedure *proc, irAddr const &addr) {
 	} else if (addr.kind == irAddr_SoaVariable) {
 		Type *t = type_deref(ir_type(addr.addr));
 		t = base_type(t);
-		GB_ASSERT(t->kind == Type_Struct && t->Struct.is_soa);
-		Type *elem = t->Struct.soa_elem;;
+		GB_ASSERT(t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None);
+		Type *elem = t->Struct.soa_elem;
 		i32 count = cast(i32)t->Struct.soa_count;
 
 		irValue *res = ir_add_local_generated(proc, elem, true);
@@ -7559,7 +7559,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 
 					if (addr.soa.index->kind != irValue_Constant) {
 						Type *t = base_type(type_deref(ir_type(addr.addr)));
-						GB_ASSERT(t->kind == Type_Struct && t->Struct.is_soa);
+						GB_ASSERT(t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None);
 						i64 count = t->Struct.soa_count;
 						irValue *len = ir_const_int(count);
 						ir_emit_bounds_check(proc, ast_token(addr.soa.index_expr), addr.soa.index, len);
@@ -7626,7 +7626,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 
 		bool deref = is_type_pointer(t);
 		t = base_type(type_deref(t));
-		if (t->kind == Type_Struct && t->Struct.is_soa) {
+		if (t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None) {
 			// SOA STRUCTURES!!!!
 			Type *elem = t->Struct.soa_elem;
 
@@ -10873,11 +10873,18 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
 				ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 6), is_raw_union);
 				ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 7), is_custom_align);
 
-				if (t->Struct.is_soa) {
+				if (t->Struct.soa_kind != StructSoa_None) {
+					irValue *kind = ir_emit_struct_ep(proc, tag, 8);
+					Type *kind_type = type_deref(ir_type(kind));
+
+					irValue *soa_kind = ir_value_constant(kind_type, exact_value_i64(t->Struct.soa_kind));
 					irValue *soa_type = ir_type_info(proc, t->Struct.soa_elem);
 					irValue *soa_len = ir_const_int(t->Struct.soa_count);
-					ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 8), soa_type);
-					ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 9), soa_len);
+
+
+					ir_emit_store(proc, kind, soa_kind);
+					ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 9), soa_type);
+					ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 10), soa_len);
 				}
 			}
 

+ 20 - 7
src/types.cpp

@@ -110,6 +110,13 @@ struct BasicType {
 	String    name;
 };
 
+enum StructSoaKind {
+	StructSoa_None    = 0,
+	StructSoa_Fixed   = 1,
+	StructSoa_Slice   = 2,
+	StructSoa_Dynamic = 3,
+};
+
 struct TypeStruct {
 	Array<Entity *> fields;
 	Array<String>   tags;
@@ -129,9 +136,10 @@ struct TypeStruct {
 	bool is_raw_union;
 	bool is_polymorphic;
 	bool is_poly_specialized;
-	bool is_soa;
-	Type *soa_elem;
-	i64   soa_count;
+
+	StructSoaKind soa_kind;
+	Type *        soa_elem;
+	i64           soa_count;
 };
 
 struct TypeUnion {
@@ -1135,7 +1143,7 @@ bool is_type_union(Type *t) {
 }
 bool is_type_soa_struct(Type *t) {
 	t = base_type(t);
-	return t->kind == Type_Struct && t->Struct.is_soa;
+	return t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None;
 }
 
 bool is_type_raw_union(Type *t) {
@@ -2199,7 +2207,7 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
 			}
 		}
 
-		bool is_soa = type->Struct.is_soa;
+		bool is_soa = type->Struct.soa_kind != StructSoa_None;
 		bool is_soa_of_array = is_soa && is_type_array(type->Struct.soa_elem);
 
 		if (is_soa_of_array) {
@@ -3008,8 +3016,13 @@ gbString write_type_to_string(gbString str, Type *type) {
 		break;
 
 	case Type_Struct: {
-		if (type->Struct.soa_elem != nullptr) {
-			str = gb_string_append_fmt(str, "#soa[%d]", cast(int)type->Struct.soa_count);
+		if (type->Struct.soa_kind != StructSoa_None) {
+			switch (type->Struct.soa_kind) {
+			case StructSoa_Fixed:   str = gb_string_append_fmt(str, "#soa[%d]", cast(int)type->Struct.soa_count); break;
+			case StructSoa_Slice:   str = gb_string_appendc(str,    "#soa[]");                                    break;
+			case StructSoa_Dynamic: str = gb_string_appendc(str,    "#soa[dynamic]");                             break;
+			default: GB_PANIC("Unknown StructSoaKind"); break;
+			}
 			str = write_type_to_string(str, type->Struct.soa_elem);
 			break;
 		}