mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-25 23:14:59 -07:00
Compiler Internal Changes: TypeRecord_Union -> Type_Union
This commit is contained in:
@@ -53,11 +53,6 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
|
||||
if (is_type_bit_field_value(t)) {
|
||||
t = default_bit_field_value_type(t);
|
||||
}
|
||||
if (is_type_variant(t)) {
|
||||
Type *st = base_type(t);
|
||||
GB_ASSERT(st->Record.variant_parent != nullptr);
|
||||
t = st->Record.variant_parent;
|
||||
}
|
||||
GB_ASSERT(is_type_typed(t));
|
||||
e->type = t;
|
||||
}
|
||||
|
||||
+17
-21
@@ -499,8 +499,8 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
|
||||
#endif
|
||||
|
||||
if (is_type_union(dst)) {
|
||||
for (isize i = 0; i < dst->Record.variant_count; i++) {
|
||||
Type *vt = dst->Record.variants[i];
|
||||
for (isize i = 0; i < dst->Union.variant_count; i++) {
|
||||
Type *vt = dst->Union.variants[i];
|
||||
if (are_types_identical(vt, s)) {
|
||||
return 1;
|
||||
}
|
||||
@@ -990,12 +990,10 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n
|
||||
array_init(&variants, c->allocator, variant_count);
|
||||
array_add(&variants, t_invalid);
|
||||
|
||||
union_type->Record.scope = c->context.scope;
|
||||
union_type->Record.are_offsets_set = false;
|
||||
union_type->Record.is_ordered = true;
|
||||
union_type->Union.scope = c->context.scope;
|
||||
{
|
||||
Entity *__tag = make_entity_field(c->allocator, nullptr, make_token_ident(str_lit("__tag")), t_int, false, -1);
|
||||
union_type->Record.union__tag = __tag;
|
||||
union_type->Union.union__tag = __tag;
|
||||
}
|
||||
|
||||
for_array(i, ut->variants) {
|
||||
@@ -1016,11 +1014,8 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n
|
||||
}
|
||||
}
|
||||
|
||||
type_set_offsets(c->allocator, union_type);
|
||||
|
||||
|
||||
union_type->Record.variants = variants.data;
|
||||
union_type->Record.variant_count = variants.count;
|
||||
union_type->Union.variants = variants.data;
|
||||
union_type->Union.variant_count = variants.count;
|
||||
}
|
||||
|
||||
void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
|
||||
@@ -2549,7 +2544,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
|
||||
check_open_scope(c, e);
|
||||
check_union_type(c, named_type, *type, e);
|
||||
check_close_scope(c);
|
||||
(*type)->Record.node = e;
|
||||
(*type)->Union.node = e;
|
||||
return true;
|
||||
case_end;
|
||||
|
||||
@@ -6436,7 +6431,13 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
Type *t = base_type(type);
|
||||
switch (t->kind) {
|
||||
case Type_Record: {
|
||||
if (!is_type_struct(t) && !is_type_union(t)) {
|
||||
if (is_type_union(t)) {
|
||||
is_constant = false;
|
||||
}
|
||||
if (cl->elems.count == 0) {
|
||||
break; // NOTE(bill): No need to init
|
||||
}
|
||||
if (!is_type_struct(t)) {
|
||||
if (cl->elems.count != 0) {
|
||||
gbString type_str = type_to_string(type);
|
||||
error(node, "Illegal compound literal type `%s`", type_str);
|
||||
@@ -6444,12 +6445,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (is_type_union(t)) {
|
||||
is_constant = false;
|
||||
}
|
||||
if (cl->elems.count == 0) {
|
||||
break; // NOTE(bill): No need to init
|
||||
}
|
||||
|
||||
{ // Checker values
|
||||
isize field_count = t->Record.field_count;
|
||||
if (cl->elems[0]->kind == AstNode_FieldValue) {
|
||||
@@ -6817,8 +6813,8 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
|
||||
if (is_type_union(src)) {
|
||||
bool ok = false;
|
||||
for (isize i = 1; i < bsrc->Record.variant_count; i++) {
|
||||
Type *vt = bsrc->Record.variants[i];
|
||||
for (isize i = 1; i < bsrc->Union.variant_count; i++) {
|
||||
Type *vt = bsrc->Union.variants[i];
|
||||
if (are_types_identical(vt, dst)) {
|
||||
ok = true;
|
||||
break;
|
||||
|
||||
+2
-2
@@ -1473,8 +1473,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
if (match_type_kind == MatchType_Union) {
|
||||
GB_ASSERT(is_type_union(bt));
|
||||
bool tag_type_found = false;
|
||||
for (isize i = 0; i < bt->Record.variant_count; i++) {
|
||||
Type *vt = bt->Record.variants[i];
|
||||
for (isize i = 0; i < bt->Union.variant_count; i++) {
|
||||
Type *vt = bt->Union.variants[i];
|
||||
if (are_types_identical(vt, y.type)) {
|
||||
tag_type_found = true;
|
||||
break;
|
||||
|
||||
+11
-14
@@ -1152,20 +1152,17 @@ void add_type_info_type(Checker *c, Type *t) {
|
||||
add_type_info_type(c, bt->Enum.base_type);
|
||||
break;
|
||||
|
||||
case Type_Union:
|
||||
add_type_info_type(c, t_int);
|
||||
for (isize i = 0; i < bt->Union.variant_count; i++) {
|
||||
add_type_info_type(c, bt->Union.variants[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Record: {
|
||||
switch (bt->Record.kind) {
|
||||
case TypeRecord_Union:
|
||||
add_type_info_type(c, t_int);
|
||||
for (isize i = 0; i < bt->Record.variant_count; i++) {
|
||||
add_type_info_type(c, bt->Record.variants[i]);
|
||||
}
|
||||
/* fallthrough */
|
||||
default:
|
||||
for (isize i = 0; i < bt->Record.field_count; i++) {
|
||||
Entity *f = bt->Record.fields[i];
|
||||
add_type_info_type(c, f->type);
|
||||
}
|
||||
break;
|
||||
for (isize i = 0; i < bt->Record.field_count; i++) {
|
||||
Entity *f = bt->Record.fields[i];
|
||||
add_type_info_type(c, f->type);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1343,7 +1340,7 @@ void init_preload(Checker *c) {
|
||||
Entity *type_info_variant = record->fields_in_src_order[2];
|
||||
Type *tiv_type = type_info_variant->type;
|
||||
GB_ASSERT(is_type_union(tiv_type));
|
||||
TypeRecord *tiv = &tiv_type->Record;
|
||||
TypeUnion *tiv = &tiv_type->Union;
|
||||
|
||||
if (tiv->variant_count != 23) {
|
||||
compiler_error("Invalid `TypeInfo` layout");
|
||||
|
||||
+42
-76
@@ -2949,8 +2949,8 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
||||
}
|
||||
|
||||
if (is_type_union(dst)) {
|
||||
for (isize i = 1; i < dst->Record.variant_count; i++) {
|
||||
Type *vt = dst->Record.variants[i];
|
||||
for (isize i = 1; i < dst->Union.variant_count; i++) {
|
||||
Type *vt = dst->Union.variants[i];
|
||||
if (are_types_identical(vt, src_type)) {
|
||||
ir_emit_comment(proc, str_lit("union - child to parent"));
|
||||
gbAllocator a = proc->module->allocator;
|
||||
@@ -3290,8 +3290,8 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token
|
||||
|
||||
irValue *tag = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, value_));
|
||||
irValue *dst_tag = nullptr;
|
||||
for (isize i = 1; i < src->Record.variant_count; i++) {
|
||||
Type *vt = src->Record.variants[i];
|
||||
for (isize i = 1; i < src->Union.variant_count; i++) {
|
||||
Type *vt = src->Union.variants[i];
|
||||
if (are_types_identical(vt, dst)) {
|
||||
dst_tag = ir_const_int(a, i);
|
||||
break;
|
||||
@@ -6825,9 +6825,9 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
Type *bt = type_deref(case_type);
|
||||
irValue *index = nullptr;
|
||||
Type *ut = base_type(type_deref(parent_type));
|
||||
GB_ASSERT(ut->Record.kind == TypeRecord_Union);
|
||||
for (isize variant_index = 1; variant_index < ut->Record.variant_count; variant_index++) {
|
||||
Type *vt = ut->Record.variants[variant_index];
|
||||
GB_ASSERT(ut->kind == Type_Union);
|
||||
for (isize variant_index = 1; variant_index < ut->Union.variant_count; variant_index++) {
|
||||
Type *vt = ut->Union.variants[variant_index];
|
||||
if (are_types_identical(vt, bt)) {
|
||||
index = ir_const_int(allocator, variant_index);
|
||||
break;
|
||||
@@ -7232,16 +7232,15 @@ void ir_init_module(irModule *m, Checker *c) {
|
||||
Type *t = cast(Type *)entry->key.ptr;
|
||||
|
||||
switch (t->kind) {
|
||||
case Type_Union:
|
||||
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;
|
||||
case TypeRecord_Union:
|
||||
count += t->Record.field_count;
|
||||
count += t->Record.variant_count;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Type_Tuple:
|
||||
@@ -8044,6 +8043,36 @@ void ir_gen_tree(irGen *s) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Union: {
|
||||
ir_emit_comment(proc, str_lit("TypeInfoUnion"));
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_union_ptr);
|
||||
|
||||
{
|
||||
irValue *variant_names = ir_emit_struct_ep(proc, tag, 1);
|
||||
irValue *variant_types = ir_emit_struct_ep(proc, tag, 2);
|
||||
|
||||
isize variant_count = gb_max(0, t->Union.variant_count-1);
|
||||
irValue *memory_names = ir_type_info_member_names_offset(proc, variant_count);
|
||||
irValue *memory_types = ir_type_info_member_types_offset(proc, variant_count);
|
||||
|
||||
// NOTE(bill): Zeroth is nil so ignore it
|
||||
for (isize variant_index = 0; variant_index < variant_count; variant_index++) {
|
||||
Type *vt = t->Union.variants[variant_index+1]; // Skip zeroth
|
||||
irValue *tip = ir_get_type_info_ptr(proc, vt);
|
||||
|
||||
irValue *index = ir_const_int(a, variant_index);
|
||||
irValue *type_info = ir_emit_ptr_offset(proc, memory_types, index);
|
||||
ir_emit_store(proc, type_info, ir_type_info(proc, vt));
|
||||
}
|
||||
|
||||
irValue *count = ir_const_int(a, variant_count);
|
||||
ir_fill_slice(proc, variant_names, memory_names, count, count);
|
||||
ir_fill_slice(proc, variant_types, memory_types, count, count);
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
case Type_Record: {
|
||||
switch (t->Record.kind) {
|
||||
case TypeRecord_Struct: {
|
||||
@@ -8092,69 +8121,6 @@ void ir_gen_tree(irGen *s) {
|
||||
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_Union: {
|
||||
ir_emit_comment(proc, str_lit("TypeInfoUnion"));
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_union_ptr);
|
||||
|
||||
{
|
||||
irValue *common_fields = ir_emit_struct_ep(proc, tag, 0);
|
||||
|
||||
isize field_count = t->Record.field_count;
|
||||
irValue *memory_types = ir_type_info_member_types_offset(proc, field_count);
|
||||
irValue *memory_names = ir_type_info_member_names_offset(proc, field_count);
|
||||
irValue *memory_offsets = ir_type_info_member_offsets_offset(proc, field_count);
|
||||
|
||||
type_set_offsets(a, t); // NOTE(bill): Just incase the offsets have not been set yet
|
||||
for (isize field_index = 0; field_index < field_count; field_index++) {
|
||||
// TODO(bill): Order fields in source order not layout order
|
||||
Entity *f = t->Record.fields[field_index];
|
||||
irValue *tip = ir_get_type_info_ptr(proc, f->type);
|
||||
i64 foffset = t->Record.offsets[f->Variable.field_index];
|
||||
GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
|
||||
|
||||
irValue *index = ir_const_int(a, field_index);
|
||||
irValue *type_info = ir_emit_ptr_offset(proc, memory_types, index);
|
||||
irValue *offset = ir_emit_ptr_offset(proc, memory_offsets, index);
|
||||
|
||||
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));
|
||||
}
|
||||
ir_emit_store(proc, offset, ir_const_int(a, foffset));
|
||||
}
|
||||
|
||||
|
||||
irValue *count = ir_const_int(a, field_count);
|
||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 0), memory_types, count, count);
|
||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 1), memory_names, count, count);
|
||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 2), memory_offsets, count, count);
|
||||
}
|
||||
|
||||
{
|
||||
irValue *variant_names = ir_emit_struct_ep(proc, tag, 1);
|
||||
irValue *variant_types = ir_emit_struct_ep(proc, tag, 2);
|
||||
|
||||
isize variant_count = gb_max(0, t->Record.variant_count-1);
|
||||
irValue *memory_names = ir_type_info_member_names_offset(proc, variant_count);
|
||||
irValue *memory_types = ir_type_info_member_types_offset(proc, variant_count);
|
||||
|
||||
// NOTE(bill): Zeroth is nil so ignore it
|
||||
for (isize variant_index = 0; variant_index < variant_count; variant_index++) {
|
||||
Type *vt = t->Record.variants[variant_index+1]; // Skip zeroth
|
||||
irValue *tip = ir_get_type_info_ptr(proc, vt);
|
||||
|
||||
irValue *index = ir_const_int(a, variant_index);
|
||||
irValue *type_info = ir_emit_ptr_offset(proc, memory_types, index);
|
||||
ir_emit_store(proc, type_info, ir_type_info(proc, vt));
|
||||
}
|
||||
|
||||
irValue *count = ir_const_int(a, variant_count);
|
||||
ir_fill_slice(proc, variant_names, memory_names, count, count);
|
||||
ir_fill_slice(proc, variant_types, memory_types, 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);
|
||||
@@ -8250,8 +8216,8 @@ void ir_gen_tree(irGen *s) {
|
||||
Type *tiv = base_type(ti->Record.fields_in_src_order[2]->type);
|
||||
GB_ASSERT(is_type_union(tiv));
|
||||
bool found = false;
|
||||
for (isize i = 1; i < tiv->Record.variant_count; i++) {
|
||||
Type *vt = tiv->Record.variants[i];
|
||||
for (isize i = 1; i < tiv->Union.variant_count; i++) {
|
||||
Type *vt = tiv->Union.variants[i];
|
||||
if (are_types_identical(vt, tag_type)) {
|
||||
found = true;
|
||||
irValue *tag_val = ir_const_int(a, i);
|
||||
|
||||
+20
-23
@@ -285,6 +285,23 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
||||
ir_print_type(f, m, base_enum_type(t));
|
||||
return;
|
||||
|
||||
case Type_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 align = type_align_of(heap_allocator(), t);
|
||||
i64 total_size = type_size_of(heap_allocator(), t);
|
||||
#if 1
|
||||
i64 block_size = t->Union.variant_block_size;
|
||||
|
||||
ir_fprintf(f, "{[0 x <%lld x i8>], ", align);
|
||||
ir_fprintf(f, "[%lld x i8], ", block_size);
|
||||
ir_fprintf(f, "i%lld}", word_bits);
|
||||
#else
|
||||
i64 block_size = total_size - build_context.word_size;
|
||||
ir_fprintf(f, "{[0 x <%lld x i8>], [%lld x i8], i%lld}", align, block_size, word_bits);
|
||||
#endif
|
||||
} return;
|
||||
|
||||
case Type_Record: {
|
||||
switch (t->Record.kind) {
|
||||
case TypeRecord_Struct:
|
||||
@@ -309,26 +326,6 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
||||
ir_fprintf(f, ">");
|
||||
}
|
||||
return;
|
||||
case TypeRecord_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 align = type_align_of(heap_allocator(), t);
|
||||
i64 total_size = type_size_of(heap_allocator(), t);
|
||||
#if 1
|
||||
i64 block_size = t->Record.variant_block_size;
|
||||
|
||||
ir_fprintf(f, "{[0 x <%lld x i8>], ", align);
|
||||
for (isize i = 0; i < t->Record.field_count; i++) {
|
||||
ir_print_type(f, m, t->Record.fields[i]->type);
|
||||
ir_fprintf(f, ", ");
|
||||
}
|
||||
ir_fprintf(f, "[%lld x i8], ", block_size);
|
||||
ir_fprintf(f, "i%lld}", word_bits);
|
||||
#else
|
||||
i64 block_size = total_size - build_context.word_size;
|
||||
ir_fprintf(f, "{[0 x <%lld x i8>], [%lld x i8], i%lld}", align, block_size, word_bits);
|
||||
#endif
|
||||
} 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)
|
||||
@@ -974,7 +971,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
ir_fprintf(f, " 0, ");
|
||||
ir_print_type(f, m, t_i32);
|
||||
#if 1
|
||||
ir_fprintf(f, " %d", 2 + t->Record.field_count);
|
||||
ir_fprintf(f, " %d", 2);
|
||||
#else
|
||||
ir_fprintf(f, " %d", 2);
|
||||
#endif
|
||||
@@ -993,11 +990,11 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
ir_print_value(f, m, instr->UnionTagValue.address, et);
|
||||
ir_fprintf(f, ",");
|
||||
#if 1
|
||||
ir_fprintf(f, " %d", 2 + t->Record.field_count);
|
||||
ir_fprintf(f, " %d", 2);
|
||||
#else
|
||||
ir_fprintf(f, " %d", 2);
|
||||
#endif
|
||||
ir_fprintf(f, ", %d", 2 + t->Record.field_count);
|
||||
ir_fprintf(f, ", %d", 2);
|
||||
ir_fprintf(f, " ; UnionTagValue");
|
||||
ir_fprintf(f, "\n");
|
||||
} break;
|
||||
|
||||
+4
-3
@@ -648,10 +648,11 @@ bool can_ssa_type(Type *t) {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case Type_Union:
|
||||
return false;
|
||||
|
||||
case Type_Record:
|
||||
if (t->Record.kind == TypeRecord_Union) {
|
||||
return false;
|
||||
} else if (t->Record.kind == TypeRecord_Struct) {
|
||||
if (t->Record.kind == TypeRecord_Struct) {
|
||||
if (t->Record.field_count > SSA_MAX_STRUCT_FIELD_COUNT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+113
-149
@@ -73,7 +73,7 @@ enum TypeRecordKind {
|
||||
|
||||
TypeRecord_Struct,
|
||||
TypeRecord_RawUnion,
|
||||
TypeRecord_Union, // Tagged
|
||||
// TypeRecord_Union, // Tagged
|
||||
// TypeRecord_Enum,
|
||||
|
||||
TypeRecord_Count,
|
||||
@@ -93,13 +93,13 @@ struct TypeRecord {
|
||||
Scope * scope;
|
||||
|
||||
// Entity_TypeName - union
|
||||
Type ** variants;
|
||||
i32 variant_count;
|
||||
Entity * union__tag;
|
||||
i64 variant_block_size; // NOTE(bill): Internal use only
|
||||
// Type ** variants;
|
||||
// i32 variant_count;
|
||||
// Entity * union__tag;
|
||||
// i64 variant_block_size; // NOTE(bill): Internal use only
|
||||
|
||||
Type * variant_parent;
|
||||
i32 variant_index;
|
||||
// Type * variant_parent;
|
||||
// i32 variant_index;
|
||||
|
||||
i64 * offsets;
|
||||
bool are_offsets_set;
|
||||
@@ -137,6 +137,17 @@ struct TypeRecord {
|
||||
Entity * min_value; \
|
||||
Entity * max_value; \
|
||||
}) \
|
||||
TYPE_KIND(Union, struct { \
|
||||
Type ** variants; \
|
||||
i32 variant_count; \
|
||||
AstNode *node; \
|
||||
Scope * scope; \
|
||||
Entity * union__tag; \
|
||||
i64 variant_block_size; \
|
||||
Type * variant_parent; \
|
||||
i32 variant_index; \
|
||||
i64 custom_align; \
|
||||
}) \
|
||||
TYPE_KIND(Named, struct { \
|
||||
String name; \
|
||||
Type * base; \
|
||||
@@ -539,8 +550,7 @@ Type *make_type_struct(gbAllocator a) {
|
||||
}
|
||||
|
||||
Type *make_type_union(gbAllocator a) {
|
||||
Type *t = alloc_type(a, Type_Record);
|
||||
t->Record.kind = TypeRecord_Union;
|
||||
Type *t = alloc_type(a, Type_Union);
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -867,14 +877,7 @@ bool is_type_struct(Type *t) {
|
||||
}
|
||||
bool is_type_union(Type *t) {
|
||||
t = base_type(t);
|
||||
return (t->kind == Type_Record && t->Record.kind == TypeRecord_Union);
|
||||
}
|
||||
bool is_type_variant(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t->kind == Type_Record) {
|
||||
return t->Record.kind == TypeRecord_Struct && t->Record.variant_parent != nullptr;
|
||||
}
|
||||
return false;
|
||||
return t->kind == Type_Union;
|
||||
}
|
||||
|
||||
bool is_type_raw_union(Type *t) {
|
||||
@@ -1002,14 +1005,17 @@ bool is_type_polymorphic(Type *t) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case Type_Record:
|
||||
for (isize i = 0; i < t->Record.field_count; i++) {
|
||||
if (is_type_polymorphic(t->Record.fields[i]->type)) {
|
||||
break;
|
||||
case Type_Union:
|
||||
for (isize i = 1; i < t->Union.variant_count; i++) {
|
||||
if (is_type_polymorphic(t->Union.variants[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (isize i = 1; i < t->Record.variant_count; i++) {
|
||||
if (is_type_polymorphic(t->Record.variants[i])) {
|
||||
break;
|
||||
case Type_Record:
|
||||
for (isize i = 0; i < t->Record.field_count; i++) {
|
||||
if (is_type_polymorphic(t->Record.fields[i]->type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1052,11 +1058,9 @@ bool type_has_nil(Type *t) {
|
||||
case Type_DynamicArray:
|
||||
case Type_Map:
|
||||
return true;
|
||||
case Type_Union:
|
||||
return true;
|
||||
case Type_Record:
|
||||
switch (t->Record.kind) {
|
||||
case TypeRecord_Union:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
@@ -1140,15 +1144,28 @@ bool are_types_identical(Type *x, Type *y) {
|
||||
case Type_Enum:
|
||||
return x == y; // NOTE(bill): All enums are unique
|
||||
|
||||
case Type_Union:
|
||||
if (y->kind == Type_Union) {
|
||||
if (x->Union.variant_count == y->Union.variant_count &&
|
||||
x->Union.custom_align == y->Union.custom_align) {
|
||||
// NOTE(bill): zeroth variant is nullptr
|
||||
for (isize i = 1; i < x->Union.variant_count; i++) {
|
||||
if (!are_types_identical(x->Union.variants[i], y->Union.variants[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
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:
|
||||
case TypeRecord_Union:
|
||||
if (x->Record.field_count == y->Record.field_count &&
|
||||
x->Record.variant_count == y->Record.variant_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) {
|
||||
@@ -1168,12 +1185,6 @@ bool are_types_identical(Type *x, Type *y) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// NOTE(bill): zeroth variant is nullptr
|
||||
for (isize i = 1; i < x->Record.variant_count; i++) {
|
||||
if (!are_types_identical(x->Record.variants[i], y->Record.variants[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -1597,6 +1608,14 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
||||
}
|
||||
}
|
||||
|
||||
} else if (type->Record.kind == Type_Union) {
|
||||
if (field_name == "__tag") {
|
||||
Entity *e = type->Union.union__tag;
|
||||
GB_ASSERT(e != nullptr);
|
||||
selection_add_index(&sel, -1); // HACK(bill): Leaky memory
|
||||
sel.entity = e;
|
||||
return sel;
|
||||
}
|
||||
} else if (type->kind == Type_Record) {
|
||||
for (isize i = 0; i < type->Record.field_count; i++) {
|
||||
Entity *f = type->Record.fields[i];
|
||||
@@ -1625,15 +1644,6 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
||||
sel.index.count = prev_count;
|
||||
}
|
||||
}
|
||||
if (type->Record.kind == TypeRecord_Union) {
|
||||
if (field_name == "__tag") {
|
||||
Entity *e = type->Record.union__tag;
|
||||
GB_ASSERT(e != nullptr);
|
||||
selection_add_index(&sel, -1); // HACK(bill): Leaky memory
|
||||
sel.entity = e;
|
||||
return sel;
|
||||
}
|
||||
}
|
||||
} else if (type->kind == Type_BitField) {
|
||||
for (isize i = 0; i < type->BitField.field_count; i++) {
|
||||
Entity *f = type->BitField.fields[i];
|
||||
@@ -1828,6 +1838,24 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
||||
case Type_Enum:
|
||||
return type_align_of_internal(allocator, t->Enum.base_type, path);
|
||||
|
||||
case Type_Union: {
|
||||
i64 max = build_context.word_size;
|
||||
// NOTE(bill): field zero is null
|
||||
for (isize i = 1; i < t->Union.variant_count; i++) {
|
||||
Type *variant = t->Union.variants[i];
|
||||
type_path_push(path, variant);
|
||||
if (path->failure) {
|
||||
return FAILURE_ALIGNMENT;
|
||||
}
|
||||
i64 align = type_align_of_internal(allocator, variant, path);
|
||||
type_path_pop(path);
|
||||
if (max < align) {
|
||||
max = align;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
} break;
|
||||
|
||||
case Type_Record: {
|
||||
switch (t->Record.kind) {
|
||||
case TypeRecord_Struct:
|
||||
@@ -1854,35 +1882,6 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
||||
return max;
|
||||
}
|
||||
break;
|
||||
case TypeRecord_Union: {
|
||||
i64 max = 1;
|
||||
if (t->Record.field_count > 0) {
|
||||
Type *field_type = t->Record.fields[0]->type;
|
||||
type_path_push(path, field_type);
|
||||
i64 align = type_align_of_internal(allocator, field_type, path);
|
||||
if (path->failure) {
|
||||
return FAILURE_ALIGNMENT;
|
||||
}
|
||||
type_path_pop(path);
|
||||
if (max < align) {
|
||||
max = align;
|
||||
}
|
||||
}
|
||||
// NOTE(bill): field zero is null
|
||||
for (isize i = 1; i < t->Record.variant_count; i++) {
|
||||
Type *variant = t->Record.variants[i];
|
||||
type_path_push(path, variant);
|
||||
if (path->failure) {
|
||||
return FAILURE_ALIGNMENT;
|
||||
}
|
||||
i64 align = type_align_of_internal(allocator, variant, path);
|
||||
type_path_pop(path);
|
||||
if (max < align) {
|
||||
max = align;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
} break;
|
||||
case TypeRecord_RawUnion: {
|
||||
i64 max = 1;
|
||||
for (isize i = 0; i < t->Record.field_count; i++) {
|
||||
@@ -1947,14 +1946,7 @@ bool type_set_offsets(gbAllocator allocator, Type *t) {
|
||||
t->Record.are_offsets_set = true;
|
||||
return true;
|
||||
}
|
||||
} else if (is_type_union(t)) {
|
||||
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, false);
|
||||
t->Record.are_offsets_set = true;
|
||||
return true;
|
||||
}
|
||||
} else if (is_type_tuple(t)) {
|
||||
} 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);
|
||||
@@ -2080,6 +2072,36 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
||||
case Type_Enum:
|
||||
return type_size_of_internal(allocator, t->Enum.base_type, path);
|
||||
|
||||
case Type_Union: {
|
||||
i64 align = type_align_of_internal(allocator, t, path);
|
||||
if (path->failure) {
|
||||
return FAILURE_SIZE;
|
||||
}
|
||||
|
||||
i64 max = 0;
|
||||
isize variant_count = t->Union.variant_count;
|
||||
|
||||
i64 field_size = max;
|
||||
|
||||
for (isize i = 1; i < variant_count; i++) {
|
||||
Type *variant_type = t->Union.variants[i];
|
||||
i64 size = type_size_of_internal(allocator, variant_type, path);
|
||||
if (max < size) {
|
||||
max = size;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(bill): Align to int
|
||||
i64 size = align_formula(max, build_context.word_size);
|
||||
// NOTE(bill): Calculate the padding between the common fields and the tag
|
||||
t->Union.variant_block_size = size - field_size;
|
||||
|
||||
size += type_size_of(allocator, t_int);
|
||||
size = align_formula(size, align);
|
||||
return size;
|
||||
} break;
|
||||
|
||||
|
||||
case Type_Record: {
|
||||
switch (t->Record.kind) {
|
||||
|
||||
@@ -2101,52 +2123,6 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
||||
return align_formula(size, align);
|
||||
} break;
|
||||
|
||||
case TypeRecord_Union: {
|
||||
i64 align = type_align_of_internal(allocator, t, path);
|
||||
if (path->failure) {
|
||||
return FAILURE_SIZE;
|
||||
}
|
||||
|
||||
i64 max = 0;
|
||||
isize field_count = t->Record.field_count;
|
||||
isize variant_count = t->Record.variant_count;
|
||||
|
||||
// Check for recursive types
|
||||
for (isize i = 0; i < field_count; i++) {
|
||||
i64 size = type_size_of_internal(allocator, t->Record.fields[i]->type, path);
|
||||
if (path->failure) {
|
||||
return FAILURE_SIZE;
|
||||
}
|
||||
}
|
||||
// NOTE(bill): Zeroth field is invalid
|
||||
type_set_offsets(allocator, t);
|
||||
|
||||
if (field_count > 0) {
|
||||
Type *end_type = t->Record.fields[field_count-1]->type;
|
||||
i64 end_offset = t->Record.offsets[field_count-1];
|
||||
i64 end_size = type_size_of_internal(allocator, end_type, path);
|
||||
max = end_offset + end_size ;
|
||||
}
|
||||
i64 field_size = max;
|
||||
|
||||
for (isize i = 1; i < variant_count; i++) {
|
||||
Type *variant_type = t->Record.variants[i];
|
||||
i64 size = type_size_of_internal(allocator, variant_type, path);
|
||||
if (max < size) {
|
||||
max = size;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(bill): Align to int
|
||||
i64 size = align_formula(max, build_context.word_size);
|
||||
// NOTE(bill): Calculate the padding between the common fields and the tag
|
||||
t->Record.variant_block_size = size - field_size;
|
||||
|
||||
size += type_size_of(allocator, t_int);
|
||||
size = align_formula(size, align);
|
||||
return size;
|
||||
} break;
|
||||
|
||||
case TypeRecord_RawUnion: {
|
||||
i64 count = t->Record.field_count;
|
||||
i64 align = type_align_of_internal(allocator, t, path);
|
||||
@@ -2185,7 +2161,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 || t->Record.kind == TypeRecord_Union)) {
|
||||
if (t->kind == Type_Record && (t->Record.kind == TypeRecord_Struct)) {
|
||||
type_set_offsets(allocator, t);
|
||||
if (gb_is_between(index, 0, t->Record.field_count-1)) {
|
||||
return t->Record.offsets[index];
|
||||
@@ -2342,6 +2318,16 @@ gbString write_type_to_string(gbString str, Type *type) {
|
||||
str = gb_string_appendc(str, "}");
|
||||
break;
|
||||
|
||||
case Type_Union:
|
||||
str = gb_string_appendc(str, "union{");
|
||||
for (isize i = 1; i < type->Union.variant_count; i++) {
|
||||
Type *t = type->Union.variants[i];
|
||||
if (i > 1) str = gb_string_appendc(str, ", ");
|
||||
str = write_type_to_string(str, t);
|
||||
}
|
||||
str = gb_string_appendc(str, "}");
|
||||
break;
|
||||
|
||||
case Type_Record: {
|
||||
switch (type->Record.kind) {
|
||||
case TypeRecord_Struct:
|
||||
@@ -2366,28 +2352,6 @@ gbString write_type_to_string(gbString str, Type *type) {
|
||||
str = gb_string_appendc(str, "}");
|
||||
break;
|
||||
|
||||
case TypeRecord_Union:
|
||||
str = gb_string_appendc(str, "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);
|
||||
}
|
||||
for (isize i = 1; i < type->Record.variant_count; i++) {
|
||||
Type *t = type->Record.variants[i];
|
||||
if (i > 1 || type->Record.field_count > 1) {
|
||||
str = gb_string_appendc(str, ", ");
|
||||
}
|
||||
str = write_type_to_string(str, t);
|
||||
}
|
||||
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++) {
|
||||
|
||||
Reference in New Issue
Block a user