aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-07-18 19:24:45 +0100
committerGinger Bill <bill@gingerbill.org>2017-07-18 19:24:45 +0100
commit59fb7b020a5e0bd2d23daab0f74e9cfa23420afc (patch)
tree435bd10ec767d4bdf56bfc3d232c0c9debea18d8
parent65f079ebc474f9decc7afb222630c04b4da32690 (diff)
Merge `raw_union` into `struct` as a memory layout tag `#raw_union`
-rw-r--r--code/demo.odin59
-rw-r--r--core/_preload.odin2
-rw-r--r--core/_soft_numbers.odin10
-rw-r--r--src/check_expr.cpp115
-rw-r--r--src/checker.cpp1
-rw-r--r--src/ir.cpp64
-rw-r--r--src/ir_print.cpp17
-rw-r--r--src/parser.cpp60
-rw-r--r--src/ssa.cpp2
-rw-r--r--src/tokenizer.cpp2
-rw-r--r--src/types.cpp194
11 files changed, 237 insertions, 289 deletions
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, Array<Opera
GB_ASSERT(is_type_struct(struct_type));
ast_node(st, StructType, node);
+ String context = str_lit("struct");
+
isize min_field_count = 0;
for_array(field_index, st->fields) {
AstNode *field = st->fields[field_index];
@@ -1066,6 +1068,11 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera
}
struct_type->Record.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<Opera
Array<Entity *> 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, Array<Opera
struct_type->Record.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);
- // 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;
+ }
- for (isize i = 0; i < fields.count; i++) {
- reordered_fields[i]->Variable.field_index = i;
+ struct_type->Record.fields = reordered_fields;
}
- 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<AstNode *> variants; \
}) \
- AST_NODE_KIND(RawUnionType, "raw union type", struct { \
- Token token; \
- Array<AstNode *> 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<AstNode *> 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<AstNode *> 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<AstNode *> variants) {
return result;
}
-AstNode *ast_raw_union_type(AstFile *f, Token token, Array<AstNode *> 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<AstNode *> 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<AstNode *> 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,16 +2311,8 @@ gbString write_type_to_string(gbString str, Type *type) {
break;
case Type_Record: {
- switch (type->Record.kind) {
- case TypeRecord_Struct:
- str = gb_string_appendc(str, "struct");
- if (type->Record.is_packed) {
- str = gb_string_appendc(str, " #packed");
- }
- if (type->Record.is_ordered) {
- str = gb_string_appendc(str, " #ordered");
- }
- str = gb_string_appendc(str, " {");
+ 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);
@@ -2360,10 +2324,15 @@ 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{");
+ } else {
+ str = gb_string_appendc(str, "struct");
+ if (type->Record.is_packed) {
+ str = gb_string_appendc(str, " #packed");
+ }
+ if (type->Record.is_ordered) {
+ str = gb_string_appendc(str, " #ordered");
+ }
+ str = gb_string_appendc(str, " {");
for (isize i = 0; i < type->Record.field_count; i++) {
Entity *f = type->Record.fields[i];
GB_ASSERT(f->kind == Entity_Variable);
@@ -2375,7 +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;
}
} break;