mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-23 22:25:00 -07:00
Change union layout to store type info rather than an integer; ternary expression for types with constant condition
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
import "fmt.odin";
|
||||
|
||||
main :: proc() {
|
||||
fmt.println("Hellope, World!");
|
||||
fmt.println("Hellope!");
|
||||
}
|
||||
|
||||
+2
-1
@@ -82,7 +82,8 @@ TypeInfo :: struct #ordered {
|
||||
Struct :: Record;
|
||||
RawUnion :: Record;
|
||||
Union :: struct #ordered {
|
||||
variants: []^TypeInfo;
|
||||
variants: []^TypeInfo;
|
||||
tag_offset: int;
|
||||
};
|
||||
Enum :: struct #ordered {
|
||||
base: ^TypeInfo;
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
CHAR_BIT :: 8;
|
||||
|
||||
c_bool :: bool;
|
||||
|
||||
c_char :: u8;
|
||||
|
||||
c_schar :: i8;
|
||||
c_uchar :: i8;
|
||||
|
||||
c_short :: i16;
|
||||
c_ushort :: i16;
|
||||
|
||||
c_int :: i32;
|
||||
c_uint :: u32;
|
||||
|
||||
c_long :: ODIN_OS == "windows" ?
|
||||
i32 :
|
||||
(size_of(int) == 4) ?
|
||||
i32 :
|
||||
i64;
|
||||
|
||||
c_ulong :: ODIN_OS == "windows" ?
|
||||
u32 :
|
||||
(size_of(int) == 4) ?
|
||||
u32 :
|
||||
u64;
|
||||
|
||||
c_longlong :: i64;
|
||||
c_ulonglong :: u64;
|
||||
|
||||
c_float :: f32;
|
||||
c_double :: f64;
|
||||
|
||||
c_complex_float :: complex64;
|
||||
c_complex_double :: complex128;
|
||||
|
||||
c_size_t :: uint;
|
||||
c_ssize_t :: int;
|
||||
c_ptrdiff_t :: int;
|
||||
c_uintptr_t :: uint;
|
||||
c_intptr_t :: int;
|
||||
+9
-1
@@ -866,7 +866,15 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
}
|
||||
|
||||
case Union:
|
||||
write_string(fi.buf, "(union)");
|
||||
data := cast(^u8)v.data;
|
||||
tipp := cast(^^TypeInfo)(data + info.tag_offset);
|
||||
if data == nil || tipp == nil {
|
||||
write_string(fi.buf, "(union)");
|
||||
} else {
|
||||
ti := tipp^;
|
||||
fmt_arg(fi, any{data, ti}, verb);
|
||||
}
|
||||
|
||||
|
||||
case RawUnion:
|
||||
write_string(fi.buf, "(raw_union)");
|
||||
|
||||
+129
-20
@@ -1326,10 +1326,6 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n
|
||||
array_add(&variants, t_invalid);
|
||||
|
||||
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->Union.union__tag = __tag;
|
||||
}
|
||||
|
||||
for_array(i, ut->variants) {
|
||||
AstNode *node = ut->variants[i];
|
||||
@@ -1353,7 +1349,10 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ok) array_add(&variants, t);
|
||||
if (ok) {
|
||||
add_type_info_type(c, t);
|
||||
array_add(&variants, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2044,8 +2043,10 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
|
||||
success = false;
|
||||
type = t_invalid;
|
||||
}
|
||||
if (is_type_polymorphic_struct(type)) {
|
||||
error(o.expr, "Cannot pass polymorphic struct as a parameter");
|
||||
if (is_type_polymorphic(type)) {
|
||||
gbString str = type_to_string(type);
|
||||
error(o.expr, "Cannot pass polymorphic type as a parameter, got `%s`", str);
|
||||
gb_string_free(str);
|
||||
success = false;
|
||||
type = t_invalid;
|
||||
}
|
||||
@@ -3079,6 +3080,15 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
|
||||
return true;
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(te, TernaryExpr, e);
|
||||
Operand o = {};
|
||||
check_expr_or_type(c, &o, e);
|
||||
if (o.mode == Addressing_Type) {
|
||||
*type = o.type;
|
||||
return true;
|
||||
}
|
||||
case_end;
|
||||
}
|
||||
|
||||
*type = t_invalid;
|
||||
@@ -4290,6 +4300,90 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
|
||||
}
|
||||
} break;
|
||||
|
||||
case Type_Union:
|
||||
{
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
i32 count = t->Union.variant_count;
|
||||
i64 *scores = gb_alloc_array(c->tmp_allocator, i64, count);
|
||||
i32 success_count = 0;
|
||||
i32 first_success_index = -1;
|
||||
for (i32 i = 1; i < count; i++) {
|
||||
Type *vt = t->Union.variants[i];
|
||||
i64 score = 0;
|
||||
if (check_is_assignable_to_with_score(c, operand, vt, &score)) {
|
||||
scores[i] = score;
|
||||
success_count += 1;
|
||||
if (first_success_index < 0) {
|
||||
first_success_index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gbString type_str = type_to_string(target_type);
|
||||
defer (gb_string_free(type_str));
|
||||
|
||||
if (success_count == 1) {
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = t->Union.variants[first_success_index];
|
||||
target_type = t->Union.variants[first_success_index];
|
||||
break;
|
||||
} else if (success_count > 1) {
|
||||
GB_ASSERT(first_success_index >= 0);
|
||||
operand->mode = Addressing_Invalid;
|
||||
convert_untyped_error(c, operand, target_type);
|
||||
|
||||
gb_printf_err("Ambiguous type conversion to `%s`, which variant did you mean:\n\t", type_str);
|
||||
i32 j = 0;
|
||||
for (i32 i = first_success_index; i < count; i++) {
|
||||
if (scores[i] == 0) continue;
|
||||
if (j > 0 && success_count > 2) gb_printf_err(", ");
|
||||
if (j == success_count-1) {
|
||||
if (success_count == 2) {
|
||||
gb_printf_err(" or ");
|
||||
} else {
|
||||
gb_printf_err(" or ");
|
||||
}
|
||||
}
|
||||
gbString str = type_to_string(t->Union.variants[i]);
|
||||
gb_printf_err("`%s`", str);
|
||||
gb_string_free(str);
|
||||
j++;
|
||||
}
|
||||
gb_printf_err("\n\n");
|
||||
|
||||
return;
|
||||
} else if (is_type_untyped_undef(operand->type) && type_has_undef(target_type)) {
|
||||
target_type = t_untyped_undef;
|
||||
} else if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) {
|
||||
operand->mode = Addressing_Invalid;
|
||||
convert_untyped_error(c, operand, target_type);
|
||||
if (count > 1) {
|
||||
gb_printf_err("`%s` is a union which only excepts the following types:\n", type_str);
|
||||
gb_printf_err("\t");
|
||||
for (i32 i = 1; i < count; i++) {
|
||||
Type *v = t->Union.variants[i];
|
||||
if (i > 1 && count > 3) gb_printf_err(", ");
|
||||
if (i == count-1) {
|
||||
if (count == 3) {
|
||||
gb_printf_err(" or ");
|
||||
} else {
|
||||
gb_printf_err("or ");
|
||||
}
|
||||
}
|
||||
gbString str = type_to_string(v);
|
||||
gb_printf_err("`%s`", str);
|
||||
gb_string_free(str);
|
||||
}
|
||||
gb_printf_err("\n\n");
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
/* fallthrough */
|
||||
|
||||
|
||||
default:
|
||||
if (is_type_untyped_undef(operand->type) && type_has_undef(target_type)) {
|
||||
@@ -6894,16 +6988,6 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
|
||||
}
|
||||
|
||||
|
||||
ExprKind Ov(Checker *c, Operand *operand, AstNode *call) {
|
||||
GB_ASSERT(call->kind == AstNode_MacroCallExpr);
|
||||
ast_node(mce, MacroCallExpr, call);
|
||||
|
||||
error(call, "Macro call expressions are not yet supported");
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->expr = call;
|
||||
return Expr_Stmt;
|
||||
}
|
||||
|
||||
void check_expr_with_type_hint(Checker *c, Operand *o, AstNode *e, Type *t) {
|
||||
check_expr_base(c, o, e, t);
|
||||
check_not_tuple(c, o);
|
||||
@@ -7139,10 +7223,10 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
|
||||
Operand x = {Addressing_Invalid};
|
||||
Operand y = {Addressing_Invalid};
|
||||
check_expr_with_type_hint(c, &x, te->x, type_hint);
|
||||
check_expr_or_type(c, &x, te->x, type_hint);
|
||||
|
||||
if (te->y != nullptr) {
|
||||
check_expr_with_type_hint(c, &y, te->y, type_hint);
|
||||
check_expr_or_type(c, &y, te->y, type_hint);
|
||||
} else {
|
||||
error(node, "A ternary expression must have an else clause");
|
||||
return kind;
|
||||
@@ -7153,6 +7237,19 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
return kind;
|
||||
}
|
||||
|
||||
if (x.mode == Addressing_Type && y.mode == Addressing_Type &&
|
||||
cond.mode == Addressing_Constant && is_type_boolean(cond.type)) {
|
||||
o->mode = Addressing_Type;
|
||||
if (cond.value.value_bool) {
|
||||
o->type = x.type;
|
||||
o->expr = x.expr;
|
||||
} else {
|
||||
o->type = y.type;
|
||||
o->expr = y.expr;
|
||||
}
|
||||
return Expr_Expr;
|
||||
}
|
||||
|
||||
convert_to_typed(c, &x, y.type, 0);
|
||||
if (x.mode == Addressing_Invalid) {
|
||||
return kind;
|
||||
@@ -7218,7 +7315,18 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
return kind;
|
||||
}
|
||||
|
||||
|
||||
Type *t = base_type(type);
|
||||
if (is_type_polymorphic(t)) {
|
||||
gbString str = type_to_string(type);
|
||||
error(node, "Cannot use a polymorphic type for a compound literal, got `%s`", str);
|
||||
o->expr = node;
|
||||
o->type = type;
|
||||
gb_string_free(str);
|
||||
return kind;
|
||||
}
|
||||
|
||||
|
||||
switch (t->kind) {
|
||||
case Type_Record: {
|
||||
if (is_type_union(t)) {
|
||||
@@ -7909,7 +8017,8 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
case_end;
|
||||
|
||||
case_ast_node(ce, MacroCallExpr, node);
|
||||
return Ov(c, o, node);
|
||||
error(node, "Macro calls are not yet supported");
|
||||
return kind;
|
||||
case_end;
|
||||
|
||||
case_ast_node(de, DerefExpr, node);
|
||||
|
||||
+26
-56
@@ -954,7 +954,7 @@ irValue *ir_instr_union_tag_ptr(irProcedure *p, irValue *address) {
|
||||
irValue *v = ir_alloc_instr(p, irInstr_UnionTagPtr);
|
||||
irInstr *i = &v->Instr;
|
||||
i->UnionTagPtr.address = address;
|
||||
i->UnionTagPtr.type = t_int_ptr;
|
||||
i->UnionTagPtr.type = make_type_pointer(p->module->allocator, t_type_info_ptr);
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -962,7 +962,7 @@ irValue *ir_instr_union_tag_value(irProcedure *p, irValue *address) {
|
||||
irValue *v = ir_alloc_instr(p, irInstr_UnionTagValue);
|
||||
irInstr *i = &v->Instr;
|
||||
i->UnionTagValue.address = address;
|
||||
i->UnionTagValue.type = t_int;
|
||||
i->UnionTagValue.type = t_type_info_ptr;
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -2218,7 +2218,7 @@ irValue *ir_emit_union_tag_ptr(irProcedure *proc, irValue *u) {
|
||||
Type *tpt = ir_type(tag_ptr);
|
||||
GB_ASSERT(is_type_pointer(tpt));
|
||||
tpt = base_type(type_deref(tpt));
|
||||
GB_ASSERT(tpt == t_int);
|
||||
GB_ASSERT(tpt == t_type_info_ptr);
|
||||
return tag_ptr;
|
||||
}
|
||||
|
||||
@@ -2379,15 +2379,8 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
|
||||
GB_ASSERT_MSG(gb_is_between(index, 0, t->Record.field_count-1), "0..%d..%d", index, t->Record.field_count);
|
||||
result_type = make_type_pointer(a, t->Record.fields[index]->type);
|
||||
} else if (is_type_union(t)) {
|
||||
type_set_offsets(a, t);
|
||||
GB_ASSERT(t->Record.field_count > 0);
|
||||
if (index == -1) {
|
||||
index = t->Record.field_count+1;
|
||||
result_type = t_int_ptr;
|
||||
} else {
|
||||
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
||||
result_type = make_type_pointer(a, t->Record.fields[index]->type);
|
||||
}
|
||||
GB_ASSERT(index == -1);
|
||||
return ir_emit_union_tag_ptr(proc, s);
|
||||
} else if (is_type_tuple(t)) {
|
||||
GB_ASSERT(t->Tuple.variable_count > 0);
|
||||
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
||||
@@ -2449,14 +2442,8 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
|
||||
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
||||
result_type = t->Record.fields[index]->type;
|
||||
} else if (is_type_union(t)) {
|
||||
type_set_offsets(a, t);
|
||||
if (index == -1) {
|
||||
index = t->Record.field_count+1;
|
||||
result_type = t_int_ptr;
|
||||
} else {
|
||||
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
||||
}
|
||||
result_type = t->Record.fields[index]->type;
|
||||
GB_ASSERT(index == -1);
|
||||
return ir_emit_union_tag_value(proc, s);
|
||||
} else if (is_type_tuple(t)) {
|
||||
GB_ASSERT(t->Tuple.variable_count > 0);
|
||||
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
||||
@@ -2523,12 +2510,12 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, irValue *e, Selection sel) {
|
||||
if (is_type_raw_union(type)) {
|
||||
type = type->Record.fields[index]->type;
|
||||
e = ir_emit_conv(proc, e, make_type_pointer(proc->module->allocator, type));
|
||||
} else if (type->kind == Type_Union) {
|
||||
GB_ASSERT(index == -1);
|
||||
type = t_type_info_ptr;
|
||||
e = ir_emit_struct_ep(proc, e, index);
|
||||
} else if (type->kind == Type_Record) {
|
||||
if (index == -1) {
|
||||
type = t_int;
|
||||
} else {
|
||||
type = type->Record.fields[index]->type;
|
||||
}
|
||||
type = type->Record.fields[index]->type;
|
||||
e = ir_emit_struct_ep(proc, e, index);
|
||||
} else if (type->kind == Type_Tuple) {
|
||||
type = type->Tuple.variables[index]->type;
|
||||
@@ -2983,7 +2970,7 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
||||
ir_emit_store(proc, underlying, value);
|
||||
|
||||
irValue *tag_ptr = ir_emit_union_tag_ptr(proc, parent);
|
||||
ir_emit_store(proc, tag_ptr, ir_const_int(a, i));
|
||||
ir_emit_store(proc, tag_ptr, ir_type_info(proc, vt));
|
||||
|
||||
return ir_emit_load(proc, parent);
|
||||
}
|
||||
@@ -3308,20 +3295,11 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token
|
||||
Type *src = base_type(type_deref(src_type));
|
||||
GB_ASSERT(is_type_union(src));
|
||||
Type *dst = tuple->Tuple.variables[0]->type;
|
||||
Type *dst_ptr = make_type_pointer(a, dst);
|
||||
|
||||
irValue *value_ = ir_address_from_load_or_generate_local(proc, value);
|
||||
|
||||
irValue *tag = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, value_));
|
||||
irValue *dst_tag = nullptr;
|
||||
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;
|
||||
}
|
||||
}
|
||||
GB_ASSERT(dst_tag != nullptr);
|
||||
irValue *dst_tag = ir_type_info(proc, dst);
|
||||
|
||||
irBlock *ok_block = ir_new_block(proc, nullptr, "union_cast.ok");
|
||||
irBlock *end_block = ir_new_block(proc, nullptr, "union_cast.end");
|
||||
@@ -6943,18 +6921,18 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
irValue *cond = nullptr;
|
||||
if (match_type_kind == MatchType_Union) {
|
||||
Type *bt = type_deref(case_type);
|
||||
irValue *index = nullptr;
|
||||
irValue *variant_tag = nullptr;
|
||||
Type *ut = base_type(type_deref(parent_type));
|
||||
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);
|
||||
variant_tag = ir_type_info(proc, vt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
GB_ASSERT(index != nullptr);
|
||||
cond = ir_emit_comp(proc, Token_CmpEq, tag_index, index);
|
||||
GB_ASSERT(variant_tag != nullptr);
|
||||
cond = ir_emit_comp(proc, Token_CmpEq, tag_index, variant_tag);
|
||||
} else if (match_type_kind == MatchType_Any) {
|
||||
irValue *any_ti = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 1));
|
||||
irValue *case_ti = ir_type_info(proc, case_type);
|
||||
@@ -8166,7 +8144,8 @@ void ir_gen_tree(irGen *s) {
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_union_ptr);
|
||||
|
||||
{
|
||||
irValue *variant_types = ir_emit_struct_ep(proc, tag, 0);
|
||||
irValue *variant_types = ir_emit_struct_ep(proc, tag, 0);
|
||||
irValue *tag_offset_ptr = ir_emit_struct_ep(proc, tag, 1);
|
||||
|
||||
isize variant_count = gb_max(0, t->Union.variant_count-1);
|
||||
irValue *memory_types = ir_type_info_member_types_offset(proc, variant_count);
|
||||
@@ -8183,6 +8162,9 @@ void ir_gen_tree(irGen *s) {
|
||||
|
||||
irValue *count = ir_const_int(a, variant_count);
|
||||
ir_fill_slice(proc, variant_types, memory_types, count, count);
|
||||
|
||||
i64 tag_offset = align_formula(t->Union.variant_block_size, build_context.word_size);
|
||||
ir_emit_store(proc, tag_offset_ptr, ir_const_int(a, tag_offset));
|
||||
}
|
||||
|
||||
} break;
|
||||
@@ -8323,21 +8305,9 @@ void ir_gen_tree(irGen *s) {
|
||||
if (tag != nullptr) {
|
||||
Type *tag_type = type_deref(ir_type(tag));
|
||||
GB_ASSERT(is_type_named(tag_type));
|
||||
Type *ti = base_type(t_type_info);
|
||||
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->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);
|
||||
irValue *ptr = ir_emit_union_tag_ptr(proc, variant_ptr);
|
||||
ir_emit_store(proc, ptr, tag_val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
GB_ASSERT_MSG(found, "Tag type not found: %s", type_to_string(tag_type));
|
||||
irValue *ti = ir_type_info(proc, tag_type);
|
||||
irValue *ptr = ir_emit_union_tag_ptr(proc, variant_ptr);
|
||||
ir_emit_store(proc, ptr, ti);
|
||||
} else {
|
||||
GB_PANIC("Unhandled TypeInfo type: %s", type_to_string(t));
|
||||
}
|
||||
|
||||
+2
-1
@@ -292,7 +292,8 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
||||
|
||||
ir_fprintf(f, "{[0 x <%lld x i8>], ", align);
|
||||
ir_fprintf(f, "[%lld x i8], ", block_size);
|
||||
ir_fprintf(f, "i%lld}", word_bits);
|
||||
ir_print_type(f, m, t_type_info_ptr);
|
||||
ir_fprintf(f, "}");
|
||||
#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);
|
||||
|
||||
+1
-1
@@ -4942,7 +4942,7 @@ ParseFileError parse_files(Parser *p, String init_filename) {
|
||||
GB_ASSERT(init_filename.text[init_filename.len] == 0);
|
||||
|
||||
char *fullpath_str = gb_path_get_full_name(heap_allocator(), cast(char *)&init_filename[0]);
|
||||
String init_fullpath = make_string_c(fullpath_str);
|
||||
String init_fullpath = string_trim_whitespace(make_string_c(fullpath_str));
|
||||
TokenPos init_pos = {};
|
||||
ImportedFile init_imported_file = {init_fullpath, init_fullpath, init_pos};
|
||||
|
||||
|
||||
+11
-4
@@ -123,7 +123,7 @@ struct TypeRecord {
|
||||
i32 variant_count; \
|
||||
AstNode *node; \
|
||||
Scope * scope; \
|
||||
Entity * union__tag; \
|
||||
Entity * union__type_info; \
|
||||
i64 variant_block_size; \
|
||||
i64 custom_align; \
|
||||
}) \
|
||||
@@ -1596,11 +1596,18 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
||||
}
|
||||
|
||||
} else if (type->kind == Type_Union) {
|
||||
if (field_name == "__tag") {
|
||||
Entity *e = type->Union.union__tag;
|
||||
if (field_name == "__type_info") {
|
||||
Entity *e = type->Union.union__type_info;
|
||||
if (e == nullptr) {
|
||||
Entity *__type_info = make_entity_field(a, nullptr, make_token_ident(str_lit("__type_info")), t_type_info_ptr, false, -1);
|
||||
type->Union.union__type_info = __type_info;
|
||||
e = __type_info;
|
||||
}
|
||||
|
||||
GB_ASSERT(e != nullptr);
|
||||
selection_add_index(&sel, -1); // HACK(bill): Leaky memory
|
||||
sel.entity = e;
|
||||
|
||||
return sel;
|
||||
}
|
||||
} else if (type->kind == Type_Record) {
|
||||
@@ -2067,9 +2074,9 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
||||
}
|
||||
|
||||
i64 max = 0;
|
||||
i64 field_size = 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];
|
||||
|
||||
Reference in New Issue
Block a user