diff --git a/code/demo.odin b/code/demo.odin index 9ecf20aef..903278399 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -130,18 +130,16 @@ get_hash :: proc(s: string) -> u32 { -Vector :: struct(N: int, T: type) { - using _: raw_union { - using e: [N]T; - when 0 < N && N <= 4 { - using v: struct { - when N >= 1 do x: T; - when N >= 2 do y: T; - when N >= 3 do z: T; - when N >= 4 do w: T; - }; - -} }; +Vector :: struct(N: int, T: type) #raw_union { + using e: [N]T; + when 0 < N && N <= 4 { + using v: struct { + when N >= 1 do x: T; + when N >= 2 do y: T; + when N >= 3 do z: T; + when N >= 4 do w: T; + }; + } } Vector3 :: Vector(3, f32); @@ -161,17 +159,17 @@ foo3 :: proc(a: type/Vector(3, $T)) { fmt.println("foo3", a{}); } main :: proc() { - Foo :: struct { - a := 123; - b := true; - } - v1 := Foo{}; - fmt.println(v1); + // Foo :: struct { + // a := 123; + // b := true; + // } + // v1 := Foo{}; + // fmt.println(v1); - foo1(Vector(3, f32)); - foo1(Vector3); - foo3(Vector(3, f32)); - foo3(Vector3); + // foo1(Vector(3, f32)); + // foo1(Vector3); + // foo3(Vector(3, f32)); + // foo3(Vector3); a, b: Vector3; @@ -184,17 +182,18 @@ main :: proc() { b.z = 5; v := add(a, b); - fmt.println(v.v); + fmt.println(size_of(Vector3)); + fmt.println(v.e, v.v); - table: Table(string, int); + // table: Table(string, int); - for i in 0..36 do put(&table, "Hellope", i); - for i in 0..42 do put(&table, "World!", i); + // for i in 0..36 do put(&table, "Hellope", i); + // for i in 0..42 do put(&table, "World!", i); - found, _ := find(&table, "Hellope"); - fmt.printf("found is %v\n", found); + // found, _ := find(&table, "Hellope"); + // fmt.printf("found is %v\n", found); - found, _ = find(&table, "World!"); - fmt.printf("found is %v\n", found); + // found, _ = find(&table, "World!"); + // fmt.printf("found is %v\n", found); } diff --git a/core/_preload.odin b/core/_preload.odin index c4c945d3d..4c4d8f2b9 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -38,7 +38,7 @@ CallingConvention :: enum { // The compiler relies upon this _exact_ order TypeInfo :: struct #ordered { // Core Types - EnumValue :: raw_union { + EnumValue :: struct #raw_union { f: f64; i: i128; } diff --git a/core/_soft_numbers.odin b/core/_soft_numbers.odin index 4e0da58ba..21673165f 100644 --- a/core/_soft_numbers.odin +++ b/core/_soft_numbers.odin @@ -6,12 +6,12 @@ __multi3 :: proc(a, b: u128) -> u128 #cc_c #link_name "__multi3" { when ODIN_ENDIAN == "bit" { - TWords :: raw_union { + TWords :: struct #raw_union { all: u128; using _: struct {lo, hi: u64;}; }; } else { - TWords :: raw_union { + TWords :: struct #raw_union { all: u128; using _: struct {hi, lo: u64;}; }; @@ -106,7 +106,7 @@ __u128_quo_mod :: proc(a, b: u128, rem: ^u128) -> (quo: u128) #cc_c #link_name " __f16_to_f32 :: proc(f: f16) -> f32 #cc_c #no_inline #link_name "__gnu_h2f_ieee" { when true { // Source: https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/ - FP32 :: raw_union {u: u32, f: f32}; + FP32 :: struct #raw_union {u: u32, f: f32}; magic, was_infnan: FP32; magic.u = (254-15) << 23; @@ -130,8 +130,8 @@ __f16_to_f32 :: proc(f: f16) -> f32 #cc_c #no_inline #link_name "__gnu_h2f_ieee" __f32_to_f16 :: proc(f_: f32) -> f16 #cc_c #no_inline #link_name "__gnu_f2h_ieee" { when false { // Source: https://gist.github.com/rygorous/2156668 - FP16 :: raw_union {u: u16, f: f16}; - FP32 :: raw_union {u: u32, f: f32}; + FP16 :: struct #raw_union {u: u16, f: f16}; + FP32 :: struct #raw_union {u: u32, f: f32}; f32infty, f16infty, magic: FP32; f32infty.u = 255<<23; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index cdbeba913..7a730629a 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1055,6 +1055,8 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Arrayfields) { AstNode *field = st->fields[field_index]; @@ -1066,6 +1068,11 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, ArrayRecord.names = make_names_field_for_record(c, c->context.scope); + if (st->is_raw_union) { + struct_type->Record.is_raw_union = true; + context = str_lit("struct #raw_union"); + } + Type *polymorphic_params = nullptr; bool is_polymorphic = false; bool can_check_fields = true; @@ -1218,7 +1225,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array fields = {}; if (!is_polymorphic) { - fields = check_fields(c, node, st->fields, min_field_count, str_lit("struct")); + fields = check_fields(c, node, st->fields, min_field_count, context); } struct_type->Record.scope = c->context.scope; @@ -1232,35 +1239,36 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, ArrayRecord.is_poly_specialized = is_poly_specialized; - type_set_offsets(c->allocator, struct_type); + if (!struct_type->Record.is_raw_union) { + type_set_offsets(c->allocator, struct_type); + if (!struct_type->failure && !st->is_packed && !st->is_ordered) { + struct_type->failure = false; + struct_type->Record.are_offsets_set = false; + struct_type->Record.offsets = nullptr; + // NOTE(bill): Reorder fields for reduced size/performance - if (!struct_type->failure && !st->is_packed && !st->is_ordered) { - struct_type->failure = false; - struct_type->Record.are_offsets_set = false; - struct_type->Record.offsets = nullptr; - // NOTE(bill): Reorder fields for reduced size/performance + Entity **reordered_fields = gb_alloc_array(c->allocator, Entity *, fields.count); + for (isize i = 0; i < fields.count; i++) { + reordered_fields[i] = struct_type->Record.fields_in_src_order[i]; + } - Entity **reordered_fields = gb_alloc_array(c->allocator, Entity *, fields.count); - for (isize i = 0; i < fields.count; i++) { - reordered_fields[i] = struct_type->Record.fields_in_src_order[i]; + // NOTE(bill): Hacky thing + // TODO(bill): Probably make an inline sorting procedure rather than use global variables + __checker_allocator = c->allocator; + // NOTE(bill): compound literal order must match source not layout + gb_sort_array(reordered_fields, fields.count, cmp_reorder_struct_fields); + + for (isize i = 0; i < fields.count; i++) { + reordered_fields[i]->Variable.field_index = i; + } + + struct_type->Record.fields = reordered_fields; } - // NOTE(bill): Hacky thing - // TODO(bill): Probably make an inline sorting procedure rather than use global variables - __checker_allocator = c->allocator; - // NOTE(bill): compound literal order must match source not layout - gb_sort_array(reordered_fields, fields.count, cmp_reorder_struct_fields); - - for (isize i = 0; i < fields.count; i++) { - reordered_fields[i]->Variable.field_index = i; - } - - struct_type->Record.fields = reordered_fields; + type_set_offsets(c->allocator, struct_type); } - type_set_offsets(c->allocator, struct_type); - if (st->align != nullptr) { if (st->is_packed) { @@ -1353,29 +1361,29 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n union_type->Union.variant_count = variants.count; } -void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) { - GB_ASSERT(node->kind == AstNode_RawUnionType); - GB_ASSERT(is_type_raw_union(union_type)); - ast_node(ut, RawUnionType, node); +// void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) { +// GB_ASSERT(node->kind == AstNode_RawUnionType); +// GB_ASSERT(is_type_raw_union(union_type)); +// ast_node(ut, RawUnionType, node); - isize min_field_count = 0; - for_array(i, ut->fields) { - AstNode *field = ut->fields[i]; - switch (field->kind) { - case_ast_node(f, ValueDecl, field); - min_field_count += f->names.count; - case_end; - } - } +// isize min_field_count = 0; +// for_array(i, ut->fields) { +// AstNode *field = ut->fields[i]; +// switch (field->kind) { +// case_ast_node(f, ValueDecl, field); +// min_field_count += f->names.count; +// case_end; +// } +// } - union_type->Record.names = make_names_field_for_record(c, c->context.scope); +// union_type->Record.names = make_names_field_for_record(c, c->context.scope); - auto fields = check_fields(c, node, ut->fields, min_field_count, str_lit("raw_union")); +// auto fields = check_fields(c, node, ut->fields, min_field_count, str_lit("raw_union")); - union_type->Record.scope = c->context.scope; - union_type->Record.fields = fields.data; - union_type->Record.field_count = fields.count; -} +// union_type->Record.scope = c->context.scope; +// union_type->Record.fields = fields.data; +// union_type->Record.field_count = fields.count; +// } void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *node) { @@ -3018,7 +3026,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) return true; case_end; - case_ast_node(rut, RawUnionType, e); +/* case_ast_node(rut, RawUnionType, e); *type = make_type_raw_union(c->allocator); set_base_type(named_type, *type); check_open_scope(c, e); @@ -3027,7 +3035,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) (*type)->Record.node = e; return true; case_end; - + */ case_ast_node(et, EnumType, e); *type = make_type_enum(c->allocator); set_base_type(named_type, *type); @@ -6482,7 +6490,7 @@ CallArgumentError check_polymorphic_struct_type(Checker *c, Operand *operand, As Type *original_type = operand->type; Type *struct_type = base_type(operand->type); - GB_ASSERT(is_type_struct(struct_type)); + GB_ASSERT(struct_type->kind == Type_Record); TypeRecord *st = &struct_type->Record; GB_ASSERT(st->is_polymorphic); @@ -7738,7 +7746,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t valid = false; } - if (!valid && (is_type_struct(t) || is_type_raw_union(t))) { + if (!valid && t->kind == Type_Record) { Entity *found = find_using_index_expr(t); if (found != nullptr) { valid = check_set_index_data(o, found->type, is_type_pointer(found->type), &max_count); @@ -7937,7 +7945,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t case AstNode_VectorType: case AstNode_StructType: case AstNode_UnionType: - case AstNode_RawUnionType: + // case AstNode_RawUnionType: case AstNode_EnumType: case AstNode_MapType: o->mode = Addressing_Type; @@ -8351,19 +8359,20 @@ gbString write_expr_to_string(gbString str, AstNode *node) { case_ast_node(st, StructType, node); str = gb_string_appendc(str, "struct "); - if (st->is_packed) str = gb_string_appendc(str, "#packed "); - if (st->is_ordered) str = gb_string_appendc(str, "#ordered "); + if (st->is_packed) str = gb_string_appendc(str, "#packed "); + if (st->is_ordered) str = gb_string_appendc(str, "#ordered "); + if (st->is_raw_union) str = gb_string_appendc(str, "#raw_union "); str = gb_string_appendc(str, "{"); str = write_record_fields_to_string(str, st->fields); str = gb_string_appendc(str, "}"); case_end; - case_ast_node(st, RawUnionType, node); - str = gb_string_appendc(str, "raw_union "); - str = gb_string_appendc(str, "{"); - str = write_record_fields_to_string(str, st->fields); - str = gb_string_appendc(str, "}"); - case_end; + // case_ast_node(st, RawUnionType, node); + // str = gb_string_appendc(str, "raw_union "); + // str = gb_string_appendc(str, "{"); + // str = write_record_fields_to_string(str, st->fields); + // str = gb_string_appendc(str, "}"); + // case_end; case_ast_node(st, UnionType, node); str = gb_string_appendc(str, "union "); diff --git a/src/checker.cpp b/src/checker.cpp index 1d566ef4b..c2694774d 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -472,7 +472,6 @@ void check_open_scope(Checker *c, AstNode *node) { case AstNode_StructType: case AstNode_EnumType: case AstNode_UnionType: - case AstNode_RawUnionType: scope->is_record = true; break; } diff --git a/src/ir.cpp b/src/ir.cpp index d49b53c7c..85eef66c4 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -662,7 +662,7 @@ bool ir_type_has_default_values(Type *t) { return ir_type_has_default_values(t->Array.elem); case Type_Record: - if (t->Record.kind == TypeRecord_Struct) { + if (!t->Record.is_raw_union) { for (isize i = 0; i < t->Record.field_count; i++) { Entity *f = t->Record.fields_in_src_order[i]; if (f->kind != Entity_Variable) continue; @@ -7355,12 +7355,7 @@ void ir_init_module(irModule *m, Checker *c) { count += t->Union.variant_count; break; case Type_Record: - switch (t->Record.kind) { - case TypeRecord_Struct: - case TypeRecord_RawUnion: - count += t->Record.field_count; - break; - } + count += t->Record.field_count; break; case Type_Tuple: count += t->Tuple.variable_count; @@ -8193,8 +8188,32 @@ void ir_gen_tree(irGen *s) { } break; case Type_Record: { - switch (t->Record.kind) { - case TypeRecord_Struct: { + if (t->Record.is_raw_union) { + ir_emit_comment(proc, str_lit("TypeInfoRawUnion")); + tag = ir_emit_conv(proc, variant_ptr, t_type_info_raw_union_ptr); + + irValue *memory_types = ir_type_info_member_types_offset(proc, t->Record.field_count); + irValue *memory_names = ir_type_info_member_names_offset(proc, t->Record.field_count); + irValue *memory_offsets = ir_type_info_member_offsets_offset(proc, t->Record.field_count); + + for (isize i = 0; i < t->Record.field_count; i++) { + Entity *f = t->Record.fields[i]; + irValue *index = ir_const_int(a, i); + irValue *type_info = ir_emit_ptr_offset(proc, memory_types, index); + // NOTE(bill): Offsets are always 0 + + ir_emit_store(proc, type_info, ir_type_info(proc, f->type)); + if (f->token.string.len > 0) { + irValue *name = ir_emit_ptr_offset(proc, memory_names, index); + ir_emit_store(proc, name, ir_const_string(a, f->token.string)); + } + } + + irValue *count = ir_const_int(a, t->Record.field_count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 0), memory_types, count, count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names, count, count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 2), memory_offsets, count, count); + } else { ir_emit_comment(proc, str_lit("TypeInfoStruct")); tag = ir_emit_conv(proc, variant_ptr, t_type_info_struct_ptr); @@ -8239,33 +8258,6 @@ void ir_gen_tree(irGen *s) { ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names, count, count); ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 2), memory_offsets, count, count); ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 3), memory_usings, count, count); - } break; - case TypeRecord_RawUnion: { - ir_emit_comment(proc, str_lit("TypeInfoRawUnion")); - tag = ir_emit_conv(proc, variant_ptr, t_type_info_raw_union_ptr); - - irValue *memory_types = ir_type_info_member_types_offset(proc, t->Record.field_count); - irValue *memory_names = ir_type_info_member_names_offset(proc, t->Record.field_count); - irValue *memory_offsets = ir_type_info_member_offsets_offset(proc, t->Record.field_count); - - for (isize i = 0; i < t->Record.field_count; i++) { - Entity *f = t->Record.fields[i]; - irValue *index = ir_const_int(a, i); - irValue *type_info = ir_emit_ptr_offset(proc, memory_types, index); - // NOTE(bill): Offsets are always 0 - - ir_emit_store(proc, type_info, ir_type_info(proc, f->type)); - if (f->token.string.len > 0) { - irValue *name = ir_emit_ptr_offset(proc, memory_names, index); - ir_emit_store(proc, name, ir_const_string(a, f->token.string)); - } - } - - irValue *count = ir_const_int(a, t->Record.field_count); - ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 0), memory_types, count, count); - ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names, count, count); - ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 2), memory_offsets, count, count); - } break; } } break; case Type_Map: { diff --git a/src/ir_print.cpp b/src/ir_print.cpp index e2b4fcb1a..e2d33054b 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -300,8 +300,14 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) { } return; case Type_Record: { - switch (t->Record.kind) { - case TypeRecord_Struct: + if (t->Record.is_raw_union) { + // NOTE(bill): The zero size array is used to fix the alignment used in a structure as + // LLVM takes the first element's alignment as the entire alignment (like C) + i64 size_of_union = type_size_of(heap_allocator(), t); + i64 align_of_union = type_align_of(heap_allocator(), t); + ir_fprintf(f, "{[0 x <%lld x i8>], [%lld x i8]}", align_of_union, size_of_union); + return; + } else { if (t->Record.is_packed) { ir_fprintf(f, "<"); } @@ -323,13 +329,6 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) { ir_fprintf(f, ">"); } return; - case TypeRecord_RawUnion: { - // NOTE(bill): The zero size array is used to fix the alignment used in a structure as - // LLVM takes the first element's alignment as the entire alignment (like C) - i64 size_of_union = type_size_of(heap_allocator(), t); - i64 align_of_union = type_align_of(heap_allocator(), t); - ir_fprintf(f, "{[0 x <%lld x i8>], [%lld x i8]}", align_of_union, size_of_union); - } return; } } break; diff --git a/src/parser.cpp b/src/parser.cpp index cd47bd173..c75fb3fc0 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -423,17 +423,13 @@ AST_NODE_KIND(_TypeBegin, "", i32) \ AstNode * polymorphic_params; \ bool is_packed; \ bool is_ordered; \ + bool is_raw_union; \ AstNode * align; \ }) \ AST_NODE_KIND(UnionType, "union type", struct { \ Token token; \ Array variants; \ }) \ - AST_NODE_KIND(RawUnionType, "raw union type", struct { \ - Token token; \ - Array fields; \ - isize field_count; \ - }) \ AST_NODE_KIND(EnumType, "enum type", struct { \ Token token; \ AstNode * base_type; \ @@ -599,7 +595,6 @@ Token ast_node_token(AstNode *node) { case AstNode_VectorType: return node->VectorType.token; case AstNode_StructType: return node->StructType.token; case AstNode_UnionType: return node->UnionType.token; - case AstNode_RawUnionType: return node->RawUnionType.token; case AstNode_EnumType: return node->EnumType.token; case AstNode_BitFieldType: return node->BitFieldType.token; case AstNode_MapType: return node->MapType.token; @@ -868,9 +863,6 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) { case AstNode_UnionType: n->UnionType.variants = clone_ast_node_array(a, n->UnionType.variants); break; - case AstNode_RawUnionType: - n->RawUnionType.fields = clone_ast_node_array(a, n->RawUnionType.fields); - break; case AstNode_EnumType: n->EnumType.base_type = clone_ast_node(a, n->EnumType.base_type); n->EnumType.fields = clone_ast_node_array(a, n->EnumType.fields); @@ -1451,7 +1443,8 @@ AstNode *ast_vector_type(AstFile *f, Token token, AstNode *count, AstNode *elem) } AstNode *ast_struct_type(AstFile *f, Token token, Array fields, isize field_count, - AstNode *polymorphic_params, bool is_packed, bool is_ordered, AstNode *align) { + AstNode *polymorphic_params, bool is_packed, bool is_ordered, bool is_raw_union, + AstNode *align) { AstNode *result = make_ast_node(f, AstNode_StructType); result->StructType.token = token; result->StructType.fields = fields; @@ -1459,6 +1452,7 @@ AstNode *ast_struct_type(AstFile *f, Token token, Array fields, isize result->StructType.polymorphic_params = polymorphic_params; result->StructType.is_packed = is_packed; result->StructType.is_ordered = is_ordered; + result->StructType.is_raw_union = is_raw_union; result->StructType.align = align; return result; } @@ -1471,14 +1465,6 @@ AstNode *ast_union_type(AstFile *f, Token token, Array variants) { return result; } -AstNode *ast_raw_union_type(AstFile *f, Token token, Array fields, isize field_count) { - AstNode *result = make_ast_node(f, AstNode_RawUnionType); - result->RawUnionType.token = token; - result->RawUnionType.fields = fields; - result->RawUnionType.field_count = field_count; - return result; -} - AstNode *ast_enum_type(AstFile *f, Token token, AstNode *base_type, Array fields) { AstNode *result = make_ast_node(f, AstNode_EnumType); @@ -1837,7 +1823,6 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) { case AstNode_StructType: case AstNode_UnionType: - case AstNode_RawUnionType: case AstNode_EnumType: case AstNode_BitFieldType: return true; @@ -2424,8 +2409,9 @@ AstNode *parse_operand(AstFile *f, bool lhs) { case Token_struct: { Token token = expect_token(f, Token_struct); AstNode *polymorphic_params = nullptr; - bool is_packed = false; - bool is_ordered = false; + bool is_packed = false; + bool is_ordered = false; + bool is_raw_union = false; AstNode *align = nullptr; if (allow_token(f, Token_OpenParen)) { @@ -2458,6 +2444,11 @@ AstNode *parse_operand(AstFile *f, bool lhs) { syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string)); } align = parse_expr(f, true); + } else if (tag.string == "raw_union") { + if (is_raw_union) { + syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string)); + } + is_raw_union = true; } else { syntax_error(tag, "Invalid struct tag `#%.*s`", LIT(tag.string)); } @@ -2468,6 +2459,14 @@ AstNode *parse_operand(AstFile *f, bool lhs) { if (is_packed && is_ordered) { syntax_error(token, "`#ordered` is not needed with `#packed` which implies ordering"); } + if (is_raw_union && is_packed) { + is_packed = false; + syntax_error(token, "`#raw_union` cannot also be `#packed`"); + } + if (is_raw_union && is_ordered) { + is_ordered = false; + syntax_error(token, "`#raw_union` cannot also be `#ordered`"); + } Token open = expect_token_after(f, Token_OpenBrace, "struct"); @@ -2481,7 +2480,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) { decls = fields->FieldList.list; } - return ast_struct_type(f, token, decls, name_count, polymorphic_params, is_packed, is_ordered, align); + return ast_struct_type(f, token, decls, name_count, polymorphic_params, is_packed, is_ordered, is_raw_union, align); } break; case Token_union: { @@ -2510,23 +2509,6 @@ AstNode *parse_operand(AstFile *f, bool lhs) { return ast_union_type(f, token, variants); } break; - case Token_raw_union: { - Token token = expect_token(f, Token_raw_union); - Token open = expect_token_after(f, Token_OpenBrace, "raw_union"); - - isize decl_count = 0; - AstNode *fields = parse_record_field_list(f, &decl_count); - Token close = expect_token(f, Token_CloseBrace); - - Array decls = {}; - if (fields != nullptr) { - GB_ASSERT(fields->kind == AstNode_FieldList); - decls = fields->FieldList.list; - } - - return ast_raw_union_type(f, token, decls, decl_count); - } break; - case Token_enum: { Token token = expect_token(f, Token_enum); AstNode *base_type = nullptr; diff --git a/src/ssa.cpp b/src/ssa.cpp index 03810e354..a1b5c3827 100644 --- a/src/ssa.cpp +++ b/src/ssa.cpp @@ -652,7 +652,7 @@ bool can_ssa_type(Type *t) { return false; case Type_Record: - if (t->Record.kind == TypeRecord_Struct) { + if (!t->Record.is_raw_union) { if (t->Record.field_count > SSA_MAX_STRUCT_FIELD_COUNT) { return false; } diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 53e71a3c3..1b4d290f3 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -107,7 +107,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ TOKEN_KIND(Token_macro, "macro"), \ TOKEN_KIND(Token_struct, "struct"), \ TOKEN_KIND(Token_union, "union"), \ - TOKEN_KIND(Token_raw_union, "raw_union"), \ + /* TOKEN_KIND(Token_raw_union, "raw_union"), */ \ TOKEN_KIND(Token_enum, "enum"), \ TOKEN_KIND(Token_bit_field, "bit_field"), \ TOKEN_KIND(Token_vector, "vector"), \ diff --git a/src/types.cpp b/src/types.cpp index 3c9d99728..3fe9029d8 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -68,17 +68,7 @@ struct BasicType { String name; }; -enum TypeRecordKind { - TypeRecord_Invalid, - - TypeRecord_Struct, - TypeRecord_RawUnion, - - TypeRecord_Count, -}; - struct TypeRecord { - TypeRecordKind kind; // All record types // Theses are arrays @@ -94,6 +84,7 @@ struct TypeRecord { bool are_offsets_being_processed; bool is_packed; bool is_ordered; + bool is_raw_union; bool is_polymorphic; bool is_poly_specialized; Type * polymorphic_params; // Type_Tuple @@ -523,7 +514,6 @@ Type *make_type_slice(gbAllocator a, Type *elem) { Type *make_type_struct(gbAllocator a) { Type *t = alloc_type(a, Type_Record); - t->Record.kind = TypeRecord_Struct; return t; } @@ -532,12 +522,6 @@ Type *make_type_union(gbAllocator a) { return t; } -Type *make_type_raw_union(gbAllocator a) { - Type *t = alloc_type(a, Type_Record); - t->Record.kind = TypeRecord_RawUnion; - return t; -} - Type *make_type_enum(gbAllocator a) { Type *t = alloc_type(a, Type_Enum); return t; @@ -847,7 +831,7 @@ Type *base_complex_elem_type(Type *t) { bool is_type_struct(Type *t) { t = base_type(t); - return (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct); + return (t->kind == Type_Record && !t->Record.is_raw_union); } bool is_type_union(Type *t) { t = base_type(t); @@ -856,7 +840,7 @@ bool is_type_union(Type *t) { bool is_type_raw_union(Type *t) { t = base_type(t); - return (t->kind == Type_Record && t->Record.kind == TypeRecord_RawUnion); + return (t->kind == Type_Record && t->Record.is_raw_union); } bool is_type_enum(Type *t) { t = base_type(t); @@ -932,8 +916,7 @@ bool is_type_indexable(Type *t) { bool is_type_polymorphic_struct(Type *t) { t = base_type(t); - if (t->kind == Type_Record && - t->Record.kind == TypeRecord_Struct) { + if (t->kind == Type_Record) { return t->Record.is_polymorphic; } return false; @@ -941,8 +924,7 @@ bool is_type_polymorphic_struct(Type *t) { bool is_type_polymorphic_struct_specialized(Type *t) { t = base_type(t); - if (t->kind == Type_Record && - t->Record.kind == TypeRecord_Struct) { + if (t->kind == Type_Record) { return t->Record.is_polymorphic && t->Record.is_poly_specialized; } return false; @@ -1158,34 +1140,28 @@ bool are_types_identical(Type *x, Type *y) { case Type_Record: if (y->kind == Type_Record) { - if (x->Record.kind == y->Record.kind) { - switch (x->Record.kind) { - case TypeRecord_Struct: - case TypeRecord_RawUnion: - if (x->Record.field_count == y->Record.field_count && - x->Record.is_packed == y->Record.is_packed && - x->Record.is_ordered == y->Record.is_ordered && - x->Record.custom_align == y->Record.custom_align) { - // TODO(bill); Fix the custom alignment rule - for (isize i = 0; i < x->Record.field_count; i++) { - Entity *xf = x->Record.fields[i]; - Entity *yf = y->Record.fields[i]; - if (!are_types_identical(xf->type, yf->type)) { - return false; - } - if (xf->token.string != yf->token.string) { - return false; - } - bool xf_is_using = (xf->flags&EntityFlag_Using) != 0; - bool yf_is_using = (yf->flags&EntityFlag_Using) != 0; - if (xf_is_using ^ yf_is_using) { - return false; - } - } - return true; + if (x->Record.is_raw_union == y->Record.is_raw_union && + x->Record.field_count == y->Record.field_count && + x->Record.is_packed == y->Record.is_packed && + x->Record.is_ordered == y->Record.is_ordered && + x->Record.custom_align == y->Record.custom_align) { + // TODO(bill); Fix the custom alignment rule + for (isize i = 0; i < x->Record.field_count; i++) { + Entity *xf = x->Record.fields[i]; + Entity *yf = y->Record.fields[i]; + if (!are_types_identical(xf->type, yf->type)) { + return false; + } + if (xf->token.string != yf->token.string) { + return false; + } + bool xf_is_using = (xf->flags&EntityFlag_Using) != 0; + bool yf_is_using = (yf->flags&EntityFlag_Using) != 0; + if (xf_is_using ^ yf_is_using) { + return false; } - break; } + return true; } } break; @@ -1310,7 +1286,7 @@ bool is_type_cte_safe(Type *type) { return false; case Type_Record: { - if (type->Record.kind != TypeRecord_Struct) { + if (type->Record.is_raw_union) { return false; } for (isize i = 0; i < type->Record.field_count; i++) { @@ -1619,7 +1595,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n return lookup_field_with_selection(a, specialized, field_name, is_type, sel); } - } else if (type->Record.kind == Type_Union) { + } else if (type->kind == Type_Union) { if (field_name == "__tag") { Entity *e = type->Union.union__tag; GB_ASSERT(e != nullptr); @@ -1868,8 +1844,22 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { } break; case Type_Record: { - switch (t->Record.kind) { - case TypeRecord_Struct: + if (t->Record.is_raw_union) { + i64 max = 1; + for (isize i = 0; i < t->Record.field_count; i++) { + Type *field_type = t->Record.fields[i]->type; + type_path_push(path, field_type); + if (path->failure) { + return FAILURE_ALIGNMENT; + } + i64 align = type_align_of_internal(allocator, field_type, path); + type_path_pop(path); + if (max < align) { + max = align; + } + } + return max; + } else { if (t->Record.custom_align > 0) { return gb_clamp(t->Record.custom_align, 1, build_context.max_align); } @@ -1892,23 +1882,6 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { } return max; } - break; - case TypeRecord_RawUnion: { - i64 max = 1; - for (isize i = 0; i < t->Record.field_count; i++) { - Type *field_type = t->Record.fields[i]->type; - type_path_push(path, field_type); - if (path->failure) { - return FAILURE_ALIGNMENT; - } - i64 align = type_align_of_internal(allocator, field_type, path); - type_path_pop(path); - if (max < align) { - max = align; - } - } - return max; - } break; } } break; @@ -1927,10 +1900,14 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { return gb_clamp(next_pow2(type_size_of_internal(allocator, t, path)), 1, build_context.word_size); } -i64 *type_set_offsets_of(gbAllocator allocator, Entity **fields, isize field_count, bool is_packed) { +i64 *type_set_offsets_of(gbAllocator allocator, Entity **fields, isize field_count, bool is_packed, bool is_raw_union) { i64 *offsets = gb_alloc_array(allocator, i64, field_count); i64 curr_offset = 0; - if (is_packed) { + if (is_raw_union) { + for (isize i = 0; i < field_count; i++) { + offsets[i] = 0; + } + } else if (is_packed) { for (isize i = 0; i < field_count; i++) { i64 size = type_size_of(allocator, fields[i]->type); offsets[i] = curr_offset; @@ -1950,17 +1927,17 @@ i64 *type_set_offsets_of(gbAllocator allocator, Entity **fields, isize field_cou bool type_set_offsets(gbAllocator allocator, Type *t) { t = base_type(t); - if (is_type_struct(t)) { + if (t->kind == Type_Record) { if (!t->Record.are_offsets_set) { t->Record.are_offsets_being_processed = true; - t->Record.offsets = type_set_offsets_of(allocator, t->Record.fields, t->Record.field_count, t->Record.is_packed); + t->Record.offsets = type_set_offsets_of(allocator, t->Record.fields, t->Record.field_count, t->Record.is_packed, t->Record.is_raw_union); t->Record.are_offsets_set = true; return true; } } else if (is_type_tuple(t)) { if (!t->Tuple.are_offsets_set) { t->Record.are_offsets_being_processed = true; - t->Tuple.offsets = type_set_offsets_of(allocator, t->Tuple.variables, t->Tuple.variable_count, false); + t->Tuple.offsets = type_set_offsets_of(allocator, t->Tuple.variables, t->Tuple.variable_count, false, false); t->Tuple.are_offsets_set = true; return true; } @@ -2114,9 +2091,22 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { case Type_Record: { - switch (t->Record.kind) { - - case TypeRecord_Struct: { + if (t->Record.is_raw_union) { + i64 count = t->Record.field_count; + i64 align = type_align_of_internal(allocator, t, path); + if (path->failure) { + return FAILURE_SIZE; + } + i64 max = 0; + for (isize i = 0; i < count; i++) { + i64 size = type_size_of_internal(allocator, t->Record.fields[i]->type, path); + if (max < size) { + max = size; + } + } + // TODO(bill): Is this how it should work? + return align_formula(max, align); + } else { i64 count = t->Record.field_count; if (count == 0) { return 0; @@ -2132,24 +2122,6 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { type_set_offsets(allocator, t); i64 size = t->Record.offsets[count-1] + type_size_of_internal(allocator, t->Record.fields[count-1]->type, path); return align_formula(size, align); - } break; - - case TypeRecord_RawUnion: { - i64 count = t->Record.field_count; - i64 align = type_align_of_internal(allocator, t, path); - if (path->failure) { - return FAILURE_SIZE; - } - i64 max = 0; - for (isize i = 0; i < count; i++) { - i64 size = type_size_of_internal(allocator, t->Record.fields[i]->type, path); - if (max < size) { - max = size; - } - } - // TODO(bill): Is this how it should work? - return align_formula(max, align); - } break; } } break; @@ -2172,7 +2144,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { i64 type_offset_of(gbAllocator allocator, Type *t, i32 index) { t = base_type(t); - if (t->kind == Type_Record && (t->Record.kind == TypeRecord_Struct)) { + if (t->kind == Type_Record && !t->Record.is_raw_union) { type_set_offsets(allocator, t); if (gb_is_between(index, 0, t->Record.field_count-1)) { return t->Record.offsets[index]; @@ -2221,7 +2193,7 @@ i64 type_offset_of_from_selection(gbAllocator allocator, Type *type, Selection s isize index = sel.index[i]; t = base_type(t); offset += type_offset_of(allocator, t, index); - if (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct) { + if (t->kind == Type_Record && !t->Record.is_raw_union) { t = t->Record.fields[index]->type; } else { // NOTE(bill): No need to worry about custom types, just need the alignment @@ -2339,8 +2311,20 @@ gbString write_type_to_string(gbString str, Type *type) { break; case Type_Record: { - switch (type->Record.kind) { - case TypeRecord_Struct: + if (type->Record.is_raw_union) { + str = gb_string_appendc(str, "raw_union{"); + for (isize i = 0; i < type->Record.field_count; i++) { + Entity *f = type->Record.fields[i]; + GB_ASSERT(f->kind == Entity_Variable); + if (i > 0) { + str = gb_string_appendc(str, ", "); + } + str = gb_string_append_length(str, f->token.string.text, f->token.string.len); + str = gb_string_appendc(str, ": "); + str = write_type_to_string(str, f->type); + } + str = gb_string_appendc(str, "}"); + } else { str = gb_string_appendc(str, "struct"); if (type->Record.is_packed) { str = gb_string_appendc(str, " #packed"); @@ -2360,22 +2344,6 @@ gbString write_type_to_string(gbString str, Type *type) { str = write_type_to_string(str, f->type); } str = gb_string_appendc(str, "}"); - break; - - case TypeRecord_RawUnion: - str = gb_string_appendc(str, "raw_union{"); - for (isize i = 0; i < type->Record.field_count; i++) { - Entity *f = type->Record.fields[i]; - GB_ASSERT(f->kind == Entity_Variable); - if (i > 0) { - str = gb_string_appendc(str, ", "); - } - str = gb_string_append_length(str, f->token.string.text, f->token.string.len); - str = gb_string_appendc(str, ": "); - str = write_type_to_string(str, f->type); - } - str = gb_string_appendc(str, "}"); - break; } } break;