mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 07:08:48 +00:00
Merge raw_union into struct as a memory layout tag #raw_union
This commit is contained in:
+29
-30
@@ -130,18 +130,16 @@ get_hash :: proc(s: string) -> u32 {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Vector :: struct(N: int, T: type) {
|
Vector :: struct(N: int, T: type) #raw_union {
|
||||||
using _: raw_union {
|
using e: [N]T;
|
||||||
using e: [N]T;
|
when 0 < N && N <= 4 {
|
||||||
when 0 < N && N <= 4 {
|
using v: struct {
|
||||||
using v: struct {
|
when N >= 1 do x: T;
|
||||||
when N >= 1 do x: T;
|
when N >= 2 do y: T;
|
||||||
when N >= 2 do y: T;
|
when N >= 3 do z: T;
|
||||||
when N >= 3 do z: T;
|
when N >= 4 do w: T;
|
||||||
when N >= 4 do w: T;
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
} };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 :: Vector(3, f32);
|
Vector3 :: Vector(3, f32);
|
||||||
@@ -161,17 +159,17 @@ foo3 :: proc(a: type/Vector(3, $T)) { fmt.println("foo3", a{}); }
|
|||||||
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
Foo :: struct {
|
// Foo :: struct {
|
||||||
a := 123;
|
// a := 123;
|
||||||
b := true;
|
// b := true;
|
||||||
}
|
// }
|
||||||
v1 := Foo{};
|
// v1 := Foo{};
|
||||||
fmt.println(v1);
|
// fmt.println(v1);
|
||||||
|
|
||||||
foo1(Vector(3, f32));
|
// foo1(Vector(3, f32));
|
||||||
foo1(Vector3);
|
// foo1(Vector3);
|
||||||
foo3(Vector(3, f32));
|
// foo3(Vector(3, f32));
|
||||||
foo3(Vector3);
|
// foo3(Vector3);
|
||||||
|
|
||||||
|
|
||||||
a, b: Vector3;
|
a, b: Vector3;
|
||||||
@@ -184,17 +182,18 @@ main :: proc() {
|
|||||||
b.z = 5;
|
b.z = 5;
|
||||||
|
|
||||||
v := add(a, b);
|
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..36 do put(&table, "Hellope", i);
|
||||||
for i in 0..42 do put(&table, "World!", i);
|
// for i in 0..42 do put(&table, "World!", i);
|
||||||
|
|
||||||
|
|
||||||
found, _ := find(&table, "Hellope");
|
// found, _ := find(&table, "Hellope");
|
||||||
fmt.printf("found is %v\n", found);
|
// fmt.printf("found is %v\n", found);
|
||||||
|
|
||||||
found, _ = find(&table, "World!");
|
// found, _ = find(&table, "World!");
|
||||||
fmt.printf("found is %v\n", found);
|
// fmt.printf("found is %v\n", found);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -38,7 +38,7 @@ CallingConvention :: enum {
|
|||||||
// The compiler relies upon this _exact_ order
|
// The compiler relies upon this _exact_ order
|
||||||
TypeInfo :: struct #ordered {
|
TypeInfo :: struct #ordered {
|
||||||
// Core Types
|
// Core Types
|
||||||
EnumValue :: raw_union {
|
EnumValue :: struct #raw_union {
|
||||||
f: f64;
|
f: f64;
|
||||||
i: i128;
|
i: i128;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ __multi3 :: proc(a, b: u128) -> u128 #cc_c #link_name "__multi3" {
|
|||||||
|
|
||||||
|
|
||||||
when ODIN_ENDIAN == "bit" {
|
when ODIN_ENDIAN == "bit" {
|
||||||
TWords :: raw_union {
|
TWords :: struct #raw_union {
|
||||||
all: u128;
|
all: u128;
|
||||||
using _: struct {lo, hi: u64;};
|
using _: struct {lo, hi: u64;};
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
TWords :: raw_union {
|
TWords :: struct #raw_union {
|
||||||
all: u128;
|
all: u128;
|
||||||
using _: struct {hi, lo: u64;};
|
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" {
|
__f16_to_f32 :: proc(f: f16) -> f32 #cc_c #no_inline #link_name "__gnu_h2f_ieee" {
|
||||||
when true {
|
when true {
|
||||||
// Source: https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
|
// 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, was_infnan: FP32;
|
||||||
magic.u = (254-15) << 23;
|
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" {
|
__f32_to_f16 :: proc(f_: f32) -> f16 #cc_c #no_inline #link_name "__gnu_f2h_ieee" {
|
||||||
when false {
|
when false {
|
||||||
// Source: https://gist.github.com/rygorous/2156668
|
// Source: https://gist.github.com/rygorous/2156668
|
||||||
FP16 :: raw_union {u: u16, f: f16};
|
FP16 :: struct #raw_union {u: u16, f: f16};
|
||||||
FP32 :: raw_union {u: u32, f: f32};
|
FP32 :: struct #raw_union {u: u32, f: f32};
|
||||||
|
|
||||||
f32infty, f16infty, magic: FP32;
|
f32infty, f16infty, magic: FP32;
|
||||||
f32infty.u = 255<<23;
|
f32infty.u = 255<<23;
|
||||||
|
|||||||
+64
-55
@@ -1055,6 +1055,8 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera
|
|||||||
GB_ASSERT(is_type_struct(struct_type));
|
GB_ASSERT(is_type_struct(struct_type));
|
||||||
ast_node(st, StructType, node);
|
ast_node(st, StructType, node);
|
||||||
|
|
||||||
|
String context = str_lit("struct");
|
||||||
|
|
||||||
isize min_field_count = 0;
|
isize min_field_count = 0;
|
||||||
for_array(field_index, st->fields) {
|
for_array(field_index, st->fields) {
|
||||||
AstNode *field = st->fields[field_index];
|
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);
|
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;
|
Type *polymorphic_params = nullptr;
|
||||||
bool is_polymorphic = false;
|
bool is_polymorphic = false;
|
||||||
bool can_check_fields = true;
|
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 = {};
|
Array<Entity *> fields = {};
|
||||||
|
|
||||||
if (!is_polymorphic) {
|
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;
|
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;
|
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) {
|
Entity **reordered_fields = gb_alloc_array(c->allocator, Entity *, fields.count);
|
||||||
struct_type->failure = false;
|
for (isize i = 0; i < fields.count; i++) {
|
||||||
struct_type->Record.are_offsets_set = false;
|
reordered_fields[i] = struct_type->Record.fields_in_src_order[i];
|
||||||
struct_type->Record.offsets = nullptr;
|
}
|
||||||
// NOTE(bill): Reorder fields for reduced size/performance
|
|
||||||
|
|
||||||
Entity **reordered_fields = gb_alloc_array(c->allocator, Entity *, fields.count);
|
// NOTE(bill): Hacky thing
|
||||||
for (isize i = 0; i < fields.count; i++) {
|
// TODO(bill): Probably make an inline sorting procedure rather than use global variables
|
||||||
reordered_fields[i] = struct_type->Record.fields_in_src_order[i];
|
__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
|
type_set_offsets(c->allocator, struct_type);
|
||||||
// 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);
|
|
||||||
|
|
||||||
|
|
||||||
if (st->align != nullptr) {
|
if (st->align != nullptr) {
|
||||||
if (st->is_packed) {
|
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;
|
union_type->Union.variant_count = variants.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
|
// void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
|
||||||
GB_ASSERT(node->kind == AstNode_RawUnionType);
|
// GB_ASSERT(node->kind == AstNode_RawUnionType);
|
||||||
GB_ASSERT(is_type_raw_union(union_type));
|
// GB_ASSERT(is_type_raw_union(union_type));
|
||||||
ast_node(ut, RawUnionType, node);
|
// ast_node(ut, RawUnionType, node);
|
||||||
|
|
||||||
isize min_field_count = 0;
|
// isize min_field_count = 0;
|
||||||
for_array(i, ut->fields) {
|
// for_array(i, ut->fields) {
|
||||||
AstNode *field = ut->fields[i];
|
// AstNode *field = ut->fields[i];
|
||||||
switch (field->kind) {
|
// switch (field->kind) {
|
||||||
case_ast_node(f, ValueDecl, field);
|
// case_ast_node(f, ValueDecl, field);
|
||||||
min_field_count += f->names.count;
|
// min_field_count += f->names.count;
|
||||||
case_end;
|
// 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.scope = c->context.scope;
|
||||||
union_type->Record.fields = fields.data;
|
// union_type->Record.fields = fields.data;
|
||||||
union_type->Record.field_count = fields.count;
|
// union_type->Record.field_count = fields.count;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *node) {
|
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;
|
return true;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(rut, RawUnionType, e);
|
/* case_ast_node(rut, RawUnionType, e);
|
||||||
*type = make_type_raw_union(c->allocator);
|
*type = make_type_raw_union(c->allocator);
|
||||||
set_base_type(named_type, *type);
|
set_base_type(named_type, *type);
|
||||||
check_open_scope(c, e);
|
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;
|
(*type)->Record.node = e;
|
||||||
return true;
|
return true;
|
||||||
case_end;
|
case_end;
|
||||||
|
*/
|
||||||
case_ast_node(et, EnumType, e);
|
case_ast_node(et, EnumType, e);
|
||||||
*type = make_type_enum(c->allocator);
|
*type = make_type_enum(c->allocator);
|
||||||
set_base_type(named_type, *type);
|
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 *original_type = operand->type;
|
||||||
Type *struct_type = base_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;
|
TypeRecord *st = &struct_type->Record;
|
||||||
GB_ASSERT(st->is_polymorphic);
|
GB_ASSERT(st->is_polymorphic);
|
||||||
|
|
||||||
@@ -7738,7 +7746,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
|||||||
valid = false;
|
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);
|
Entity *found = find_using_index_expr(t);
|
||||||
if (found != nullptr) {
|
if (found != nullptr) {
|
||||||
valid = check_set_index_data(o, found->type, is_type_pointer(found->type), &max_count);
|
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_VectorType:
|
||||||
case AstNode_StructType:
|
case AstNode_StructType:
|
||||||
case AstNode_UnionType:
|
case AstNode_UnionType:
|
||||||
case AstNode_RawUnionType:
|
// case AstNode_RawUnionType:
|
||||||
case AstNode_EnumType:
|
case AstNode_EnumType:
|
||||||
case AstNode_MapType:
|
case AstNode_MapType:
|
||||||
o->mode = Addressing_Type;
|
o->mode = Addressing_Type;
|
||||||
@@ -8351,19 +8359,20 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
|
|
||||||
case_ast_node(st, StructType, node);
|
case_ast_node(st, StructType, node);
|
||||||
str = gb_string_appendc(str, "struct ");
|
str = gb_string_appendc(str, "struct ");
|
||||||
if (st->is_packed) str = gb_string_appendc(str, "#packed ");
|
if (st->is_packed) str = gb_string_appendc(str, "#packed ");
|
||||||
if (st->is_ordered) str = gb_string_appendc(str, "#ordered ");
|
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 = gb_string_appendc(str, "{");
|
||||||
str = write_record_fields_to_string(str, st->fields);
|
str = write_record_fields_to_string(str, st->fields);
|
||||||
str = gb_string_appendc(str, "}");
|
str = gb_string_appendc(str, "}");
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(st, RawUnionType, node);
|
// case_ast_node(st, RawUnionType, node);
|
||||||
str = gb_string_appendc(str, "raw_union ");
|
// str = gb_string_appendc(str, "raw_union ");
|
||||||
str = gb_string_appendc(str, "{");
|
// str = gb_string_appendc(str, "{");
|
||||||
str = write_record_fields_to_string(str, st->fields);
|
// str = write_record_fields_to_string(str, st->fields);
|
||||||
str = gb_string_appendc(str, "}");
|
// str = gb_string_appendc(str, "}");
|
||||||
case_end;
|
// case_end;
|
||||||
|
|
||||||
case_ast_node(st, UnionType, node);
|
case_ast_node(st, UnionType, node);
|
||||||
str = gb_string_appendc(str, "union ");
|
str = gb_string_appendc(str, "union ");
|
||||||
|
|||||||
@@ -472,7 +472,6 @@ void check_open_scope(Checker *c, AstNode *node) {
|
|||||||
case AstNode_StructType:
|
case AstNode_StructType:
|
||||||
case AstNode_EnumType:
|
case AstNode_EnumType:
|
||||||
case AstNode_UnionType:
|
case AstNode_UnionType:
|
||||||
case AstNode_RawUnionType:
|
|
||||||
scope->is_record = true;
|
scope->is_record = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-36
@@ -662,7 +662,7 @@ bool ir_type_has_default_values(Type *t) {
|
|||||||
return ir_type_has_default_values(t->Array.elem);
|
return ir_type_has_default_values(t->Array.elem);
|
||||||
|
|
||||||
case Type_Record:
|
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++) {
|
for (isize i = 0; i < t->Record.field_count; i++) {
|
||||||
Entity *f = t->Record.fields_in_src_order[i];
|
Entity *f = t->Record.fields_in_src_order[i];
|
||||||
if (f->kind != Entity_Variable) continue;
|
if (f->kind != Entity_Variable) continue;
|
||||||
@@ -7355,12 +7355,7 @@ void ir_init_module(irModule *m, Checker *c) {
|
|||||||
count += t->Union.variant_count;
|
count += t->Union.variant_count;
|
||||||
break;
|
break;
|
||||||
case Type_Record:
|
case Type_Record:
|
||||||
switch (t->Record.kind) {
|
count += t->Record.field_count;
|
||||||
case TypeRecord_Struct:
|
|
||||||
case TypeRecord_RawUnion:
|
|
||||||
count += t->Record.field_count;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case Type_Tuple:
|
case Type_Tuple:
|
||||||
count += t->Tuple.variable_count;
|
count += t->Tuple.variable_count;
|
||||||
@@ -8193,8 +8188,32 @@ void ir_gen_tree(irGen *s) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
switch (t->Record.kind) {
|
if (t->Record.is_raw_union) {
|
||||||
case TypeRecord_Struct: {
|
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"));
|
ir_emit_comment(proc, str_lit("TypeInfoStruct"));
|
||||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_struct_ptr);
|
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, 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, 2), memory_offsets, count, count);
|
||||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 3), memory_usings, 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;
|
} break;
|
||||||
case Type_Map: {
|
case Type_Map: {
|
||||||
|
|||||||
+8
-9
@@ -300,8 +300,14 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
|||||||
} return;
|
} return;
|
||||||
|
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
switch (t->Record.kind) {
|
if (t->Record.is_raw_union) {
|
||||||
case TypeRecord_Struct:
|
// 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) {
|
if (t->Record.is_packed) {
|
||||||
ir_fprintf(f, "<");
|
ir_fprintf(f, "<");
|
||||||
}
|
}
|
||||||
@@ -323,13 +329,6 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
|||||||
ir_fprintf(f, ">");
|
ir_fprintf(f, ">");
|
||||||
}
|
}
|
||||||
return;
|
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;
|
} break;
|
||||||
|
|
||||||
|
|||||||
+21
-39
@@ -423,17 +423,13 @@ AST_NODE_KIND(_TypeBegin, "", i32) \
|
|||||||
AstNode * polymorphic_params; \
|
AstNode * polymorphic_params; \
|
||||||
bool is_packed; \
|
bool is_packed; \
|
||||||
bool is_ordered; \
|
bool is_ordered; \
|
||||||
|
bool is_raw_union; \
|
||||||
AstNode * align; \
|
AstNode * align; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(UnionType, "union type", struct { \
|
AST_NODE_KIND(UnionType, "union type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Array<AstNode *> variants; \
|
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 { \
|
AST_NODE_KIND(EnumType, "enum type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode * base_type; \
|
AstNode * base_type; \
|
||||||
@@ -599,7 +595,6 @@ Token ast_node_token(AstNode *node) {
|
|||||||
case AstNode_VectorType: return node->VectorType.token;
|
case AstNode_VectorType: return node->VectorType.token;
|
||||||
case AstNode_StructType: return node->StructType.token;
|
case AstNode_StructType: return node->StructType.token;
|
||||||
case AstNode_UnionType: return node->UnionType.token;
|
case AstNode_UnionType: return node->UnionType.token;
|
||||||
case AstNode_RawUnionType: return node->RawUnionType.token;
|
|
||||||
case AstNode_EnumType: return node->EnumType.token;
|
case AstNode_EnumType: return node->EnumType.token;
|
||||||
case AstNode_BitFieldType: return node->BitFieldType.token;
|
case AstNode_BitFieldType: return node->BitFieldType.token;
|
||||||
case AstNode_MapType: return node->MapType.token;
|
case AstNode_MapType: return node->MapType.token;
|
||||||
@@ -868,9 +863,6 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
|
|||||||
case AstNode_UnionType:
|
case AstNode_UnionType:
|
||||||
n->UnionType.variants = clone_ast_node_array(a, n->UnionType.variants);
|
n->UnionType.variants = clone_ast_node_array(a, n->UnionType.variants);
|
||||||
break;
|
break;
|
||||||
case AstNode_RawUnionType:
|
|
||||||
n->RawUnionType.fields = clone_ast_node_array(a, n->RawUnionType.fields);
|
|
||||||
break;
|
|
||||||
case AstNode_EnumType:
|
case AstNode_EnumType:
|
||||||
n->EnumType.base_type = clone_ast_node(a, n->EnumType.base_type);
|
n->EnumType.base_type = clone_ast_node(a, n->EnumType.base_type);
|
||||||
n->EnumType.fields = clone_ast_node_array(a, n->EnumType.fields);
|
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 *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);
|
AstNode *result = make_ast_node(f, AstNode_StructType);
|
||||||
result->StructType.token = token;
|
result->StructType.token = token;
|
||||||
result->StructType.fields = fields;
|
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.polymorphic_params = polymorphic_params;
|
||||||
result->StructType.is_packed = is_packed;
|
result->StructType.is_packed = is_packed;
|
||||||
result->StructType.is_ordered = is_ordered;
|
result->StructType.is_ordered = is_ordered;
|
||||||
|
result->StructType.is_raw_union = is_raw_union;
|
||||||
result->StructType.align = align;
|
result->StructType.align = align;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1471,14 +1465,6 @@ AstNode *ast_union_type(AstFile *f, Token token, Array<AstNode *> variants) {
|
|||||||
return result;
|
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 *ast_enum_type(AstFile *f, Token token, AstNode *base_type, Array<AstNode *> fields) {
|
||||||
AstNode *result = make_ast_node(f, AstNode_EnumType);
|
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_StructType:
|
||||||
case AstNode_UnionType:
|
case AstNode_UnionType:
|
||||||
case AstNode_RawUnionType:
|
|
||||||
case AstNode_EnumType:
|
case AstNode_EnumType:
|
||||||
case AstNode_BitFieldType:
|
case AstNode_BitFieldType:
|
||||||
return true;
|
return true;
|
||||||
@@ -2424,8 +2409,9 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
case Token_struct: {
|
case Token_struct: {
|
||||||
Token token = expect_token(f, Token_struct);
|
Token token = expect_token(f, Token_struct);
|
||||||
AstNode *polymorphic_params = nullptr;
|
AstNode *polymorphic_params = nullptr;
|
||||||
bool is_packed = false;
|
bool is_packed = false;
|
||||||
bool is_ordered = false;
|
bool is_ordered = false;
|
||||||
|
bool is_raw_union = false;
|
||||||
AstNode *align = nullptr;
|
AstNode *align = nullptr;
|
||||||
|
|
||||||
if (allow_token(f, Token_OpenParen)) {
|
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));
|
syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
|
||||||
}
|
}
|
||||||
align = parse_expr(f, true);
|
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 {
|
} else {
|
||||||
syntax_error(tag, "Invalid struct tag `#%.*s`", LIT(tag.string));
|
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) {
|
if (is_packed && is_ordered) {
|
||||||
syntax_error(token, "`#ordered` is not needed with `#packed` which implies ordering");
|
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");
|
Token open = expect_token_after(f, Token_OpenBrace, "struct");
|
||||||
|
|
||||||
@@ -2481,7 +2480,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
decls = fields->FieldList.list;
|
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;
|
} break;
|
||||||
|
|
||||||
case Token_union: {
|
case Token_union: {
|
||||||
@@ -2510,23 +2509,6 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
return ast_union_type(f, token, variants);
|
return ast_union_type(f, token, variants);
|
||||||
} break;
|
} 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: {
|
case Token_enum: {
|
||||||
Token token = expect_token(f, Token_enum);
|
Token token = expect_token(f, Token_enum);
|
||||||
AstNode *base_type = nullptr;
|
AstNode *base_type = nullptr;
|
||||||
|
|||||||
+1
-1
@@ -652,7 +652,7 @@ bool can_ssa_type(Type *t) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
case Type_Record:
|
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) {
|
if (t->Record.field_count > SSA_MAX_STRUCT_FIELD_COUNT) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -107,7 +107,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
|||||||
TOKEN_KIND(Token_macro, "macro"), \
|
TOKEN_KIND(Token_macro, "macro"), \
|
||||||
TOKEN_KIND(Token_struct, "struct"), \
|
TOKEN_KIND(Token_struct, "struct"), \
|
||||||
TOKEN_KIND(Token_union, "union"), \
|
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_enum, "enum"), \
|
||||||
TOKEN_KIND(Token_bit_field, "bit_field"), \
|
TOKEN_KIND(Token_bit_field, "bit_field"), \
|
||||||
TOKEN_KIND(Token_vector, "vector"), \
|
TOKEN_KIND(Token_vector, "vector"), \
|
||||||
|
|||||||
+84
-116
@@ -68,17 +68,7 @@ struct BasicType {
|
|||||||
String name;
|
String name;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TypeRecordKind {
|
|
||||||
TypeRecord_Invalid,
|
|
||||||
|
|
||||||
TypeRecord_Struct,
|
|
||||||
TypeRecord_RawUnion,
|
|
||||||
|
|
||||||
TypeRecord_Count,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TypeRecord {
|
struct TypeRecord {
|
||||||
TypeRecordKind kind;
|
|
||||||
|
|
||||||
// All record types
|
// All record types
|
||||||
// Theses are arrays
|
// Theses are arrays
|
||||||
@@ -94,6 +84,7 @@ struct TypeRecord {
|
|||||||
bool are_offsets_being_processed;
|
bool are_offsets_being_processed;
|
||||||
bool is_packed;
|
bool is_packed;
|
||||||
bool is_ordered;
|
bool is_ordered;
|
||||||
|
bool is_raw_union;
|
||||||
bool is_polymorphic;
|
bool is_polymorphic;
|
||||||
bool is_poly_specialized;
|
bool is_poly_specialized;
|
||||||
Type * polymorphic_params; // Type_Tuple
|
Type * polymorphic_params; // Type_Tuple
|
||||||
@@ -523,7 +514,6 @@ Type *make_type_slice(gbAllocator a, Type *elem) {
|
|||||||
|
|
||||||
Type *make_type_struct(gbAllocator a) {
|
Type *make_type_struct(gbAllocator a) {
|
||||||
Type *t = alloc_type(a, Type_Record);
|
Type *t = alloc_type(a, Type_Record);
|
||||||
t->Record.kind = TypeRecord_Struct;
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,12 +522,6 @@ Type *make_type_union(gbAllocator a) {
|
|||||||
return t;
|
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 *make_type_enum(gbAllocator a) {
|
||||||
Type *t = alloc_type(a, Type_Enum);
|
Type *t = alloc_type(a, Type_Enum);
|
||||||
return t;
|
return t;
|
||||||
@@ -847,7 +831,7 @@ Type *base_complex_elem_type(Type *t) {
|
|||||||
|
|
||||||
bool is_type_struct(Type *t) {
|
bool is_type_struct(Type *t) {
|
||||||
t = base_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) {
|
bool is_type_union(Type *t) {
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
@@ -856,7 +840,7 @@ bool is_type_union(Type *t) {
|
|||||||
|
|
||||||
bool is_type_raw_union(Type *t) {
|
bool is_type_raw_union(Type *t) {
|
||||||
t = base_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) {
|
bool is_type_enum(Type *t) {
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
@@ -932,8 +916,7 @@ bool is_type_indexable(Type *t) {
|
|||||||
|
|
||||||
bool is_type_polymorphic_struct(Type *t) {
|
bool is_type_polymorphic_struct(Type *t) {
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
if (t->kind == Type_Record &&
|
if (t->kind == Type_Record) {
|
||||||
t->Record.kind == TypeRecord_Struct) {
|
|
||||||
return t->Record.is_polymorphic;
|
return t->Record.is_polymorphic;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -941,8 +924,7 @@ bool is_type_polymorphic_struct(Type *t) {
|
|||||||
|
|
||||||
bool is_type_polymorphic_struct_specialized(Type *t) {
|
bool is_type_polymorphic_struct_specialized(Type *t) {
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
if (t->kind == Type_Record &&
|
if (t->kind == Type_Record) {
|
||||||
t->Record.kind == TypeRecord_Struct) {
|
|
||||||
return t->Record.is_polymorphic && t->Record.is_poly_specialized;
|
return t->Record.is_polymorphic && t->Record.is_poly_specialized;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -1158,34 +1140,28 @@ bool are_types_identical(Type *x, Type *y) {
|
|||||||
|
|
||||||
case Type_Record:
|
case Type_Record:
|
||||||
if (y->kind == Type_Record) {
|
if (y->kind == Type_Record) {
|
||||||
if (x->Record.kind == y->Record.kind) {
|
if (x->Record.is_raw_union == y->Record.is_raw_union &&
|
||||||
switch (x->Record.kind) {
|
x->Record.field_count == y->Record.field_count &&
|
||||||
case TypeRecord_Struct:
|
x->Record.is_packed == y->Record.is_packed &&
|
||||||
case TypeRecord_RawUnion:
|
x->Record.is_ordered == y->Record.is_ordered &&
|
||||||
if (x->Record.field_count == y->Record.field_count &&
|
x->Record.custom_align == y->Record.custom_align) {
|
||||||
x->Record.is_packed == y->Record.is_packed &&
|
// TODO(bill); Fix the custom alignment rule
|
||||||
x->Record.is_ordered == y->Record.is_ordered &&
|
for (isize i = 0; i < x->Record.field_count; i++) {
|
||||||
x->Record.custom_align == y->Record.custom_align) {
|
Entity *xf = x->Record.fields[i];
|
||||||
// TODO(bill); Fix the custom alignment rule
|
Entity *yf = y->Record.fields[i];
|
||||||
for (isize i = 0; i < x->Record.field_count; i++) {
|
if (!are_types_identical(xf->type, yf->type)) {
|
||||||
Entity *xf = x->Record.fields[i];
|
return false;
|
||||||
Entity *yf = y->Record.fields[i];
|
}
|
||||||
if (!are_types_identical(xf->type, yf->type)) {
|
if (xf->token.string != yf->token.string) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (xf->token.string != yf->token.string) {
|
bool xf_is_using = (xf->flags&EntityFlag_Using) != 0;
|
||||||
return false;
|
bool yf_is_using = (yf->flags&EntityFlag_Using) != 0;
|
||||||
}
|
if (xf_is_using ^ yf_is_using) {
|
||||||
bool xf_is_using = (xf->flags&EntityFlag_Using) != 0;
|
return false;
|
||||||
bool yf_is_using = (yf->flags&EntityFlag_Using) != 0;
|
|
||||||
if (xf_is_using ^ yf_is_using) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1310,7 +1286,7 @@ bool is_type_cte_safe(Type *type) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
if (type->Record.kind != TypeRecord_Struct) {
|
if (type->Record.is_raw_union) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (isize i = 0; i < type->Record.field_count; i++) {
|
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);
|
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") {
|
if (field_name == "__tag") {
|
||||||
Entity *e = type->Union.union__tag;
|
Entity *e = type->Union.union__tag;
|
||||||
GB_ASSERT(e != nullptr);
|
GB_ASSERT(e != nullptr);
|
||||||
@@ -1868,8 +1844,22 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
switch (t->Record.kind) {
|
if (t->Record.is_raw_union) {
|
||||||
case TypeRecord_Struct:
|
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) {
|
if (t->Record.custom_align > 0) {
|
||||||
return gb_clamp(t->Record.custom_align, 1, build_context.max_align);
|
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;
|
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;
|
} 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);
|
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 *offsets = gb_alloc_array(allocator, i64, field_count);
|
||||||
i64 curr_offset = 0;
|
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++) {
|
for (isize i = 0; i < field_count; i++) {
|
||||||
i64 size = type_size_of(allocator, fields[i]->type);
|
i64 size = type_size_of(allocator, fields[i]->type);
|
||||||
offsets[i] = curr_offset;
|
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) {
|
bool type_set_offsets(gbAllocator allocator, Type *t) {
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
if (is_type_struct(t)) {
|
if (t->kind == Type_Record) {
|
||||||
if (!t->Record.are_offsets_set) {
|
if (!t->Record.are_offsets_set) {
|
||||||
t->Record.are_offsets_being_processed = true;
|
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;
|
t->Record.are_offsets_set = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (is_type_tuple(t)) {
|
} else if (is_type_tuple(t)) {
|
||||||
if (!t->Tuple.are_offsets_set) {
|
if (!t->Tuple.are_offsets_set) {
|
||||||
t->Record.are_offsets_being_processed = true;
|
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;
|
t->Tuple.are_offsets_set = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2114,9 +2091,22 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
|
|
||||||
|
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
switch (t->Record.kind) {
|
if (t->Record.is_raw_union) {
|
||||||
|
i64 count = t->Record.field_count;
|
||||||
case TypeRecord_Struct: {
|
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;
|
i64 count = t->Record.field_count;
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2132,24 +2122,6 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
type_set_offsets(allocator, t);
|
type_set_offsets(allocator, t);
|
||||||
i64 size = t->Record.offsets[count-1] + type_size_of_internal(allocator, t->Record.fields[count-1]->type, path);
|
i64 size = t->Record.offsets[count-1] + type_size_of_internal(allocator, t->Record.fields[count-1]->type, path);
|
||||||
return align_formula(size, align);
|
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;
|
} 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) {
|
i64 type_offset_of(gbAllocator allocator, Type *t, i32 index) {
|
||||||
t = base_type(t);
|
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);
|
type_set_offsets(allocator, t);
|
||||||
if (gb_is_between(index, 0, t->Record.field_count-1)) {
|
if (gb_is_between(index, 0, t->Record.field_count-1)) {
|
||||||
return t->Record.offsets[index];
|
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];
|
isize index = sel.index[i];
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
offset += type_offset_of(allocator, t, index);
|
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;
|
t = t->Record.fields[index]->type;
|
||||||
} else {
|
} else {
|
||||||
// NOTE(bill): No need to worry about custom types, just need the alignment
|
// 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;
|
break;
|
||||||
|
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
switch (type->Record.kind) {
|
if (type->Record.is_raw_union) {
|
||||||
case TypeRecord_Struct:
|
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");
|
str = gb_string_appendc(str, "struct");
|
||||||
if (type->Record.is_packed) {
|
if (type->Record.is_packed) {
|
||||||
str = gb_string_appendc(str, " #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 = write_type_to_string(str, f->type);
|
||||||
}
|
}
|
||||||
str = gb_string_appendc(str, "}");
|
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;
|
} break;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user