diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index f2d42774a..c7d63aea5 100644 --- a/core/fmt/fmt.odin +++ b/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 ? ']' : '}'); diff --git a/core/reflect/types.odin b/core/reflect/types.odin index 7a8503c82..25a723834 100644 --- a/core/reflect/types.odin +++ b/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 "); diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 30555956e..7fdadbaa1 100644 --- a/core/runtime/core.odin +++ b/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, }; diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index bfa620bd2..88c591a2c 100644 --- a/core/runtime/internal.odin +++ b/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); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 22f27939e..85ac17300 100644 --- a/src/check_expr.cpp +++ b/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(heap_allocator(), old_array->Array.count); soa_struct->Struct.tags = array_make(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(heap_allocator(), old_struct->Struct.fields.count); soa_struct->Struct.tags = array_make(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; diff --git a/src/check_type.cpp b/src/check_type.cpp index f62843e2b..aa5a32905 100644 --- a/src/check_type.cpp +++ b/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(heap_allocator(), old_array->Array.count); soa_struct->Struct.tags = array_make(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(heap_allocator(), old_struct->Struct.fields.count); soa_struct->Struct.tags = array_make(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; diff --git a/src/checker.cpp b/src/checker.cpp index 6b3b1b68f..c189b8e6f 100644 --- a/src/checker.cpp +++ b/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; } } } diff --git a/src/ir.cpp b/src/ir.cpp index 86e618187..3343021f4 100644 --- a/src/ir.cpp +++ b/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); } } diff --git a/src/types.cpp b/src/types.cpp index 06aa211ab..224ac8159 100644 --- a/src/types.cpp +++ b/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 fields; Array 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; }