mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-07 16:18:52 +00: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";
|
import "fmt.odin";
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
fmt.println("Hellope, World!");
|
fmt.println("Hellope!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ TypeInfo :: struct #ordered {
|
|||||||
RawUnion :: Record;
|
RawUnion :: Record;
|
||||||
Union :: struct #ordered {
|
Union :: struct #ordered {
|
||||||
variants: []^TypeInfo;
|
variants: []^TypeInfo;
|
||||||
|
tag_offset: int;
|
||||||
};
|
};
|
||||||
Enum :: struct #ordered {
|
Enum :: struct #ordered {
|
||||||
base: ^TypeInfo;
|
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;
|
||||||
@@ -866,7 +866,15 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Union:
|
case Union:
|
||||||
|
data := cast(^u8)v.data;
|
||||||
|
tipp := cast(^^TypeInfo)(data + info.tag_offset);
|
||||||
|
if data == nil || tipp == nil {
|
||||||
write_string(fi.buf, "(union)");
|
write_string(fi.buf, "(union)");
|
||||||
|
} else {
|
||||||
|
ti := tipp^;
|
||||||
|
fmt_arg(fi, any{data, ti}, verb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
case RawUnion:
|
case RawUnion:
|
||||||
write_string(fi.buf, "(raw_union)");
|
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);
|
array_add(&variants, t_invalid);
|
||||||
|
|
||||||
union_type->Union.scope = c->context.scope;
|
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) {
|
for_array(i, ut->variants) {
|
||||||
AstNode *node = ut->variants[i];
|
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;
|
success = false;
|
||||||
type = t_invalid;
|
type = t_invalid;
|
||||||
}
|
}
|
||||||
if (is_type_polymorphic_struct(type)) {
|
if (is_type_polymorphic(type)) {
|
||||||
error(o.expr, "Cannot pass polymorphic struct as a parameter");
|
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;
|
success = false;
|
||||||
type = t_invalid;
|
type = t_invalid;
|
||||||
}
|
}
|
||||||
@@ -3079,6 +3080,15 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case_end;
|
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;
|
*type = t_invalid;
|
||||||
@@ -4290,6 +4300,90 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
|
|||||||
}
|
}
|
||||||
} break;
|
} 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:
|
default:
|
||||||
if (is_type_untyped_undef(operand->type) && type_has_undef(target_type)) {
|
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) {
|
void check_expr_with_type_hint(Checker *c, Operand *o, AstNode *e, Type *t) {
|
||||||
check_expr_base(c, o, e, t);
|
check_expr_base(c, o, e, t);
|
||||||
check_not_tuple(c, o);
|
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 x = {Addressing_Invalid};
|
||||||
Operand y = {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) {
|
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 {
|
} else {
|
||||||
error(node, "A ternary expression must have an else clause");
|
error(node, "A ternary expression must have an else clause");
|
||||||
return kind;
|
return kind;
|
||||||
@@ -7153,6 +7237,19 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
|||||||
return kind;
|
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);
|
convert_to_typed(c, &x, y.type, 0);
|
||||||
if (x.mode == Addressing_Invalid) {
|
if (x.mode == Addressing_Invalid) {
|
||||||
return kind;
|
return kind;
|
||||||
@@ -7218,7 +7315,18 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
|||||||
return kind;
|
return kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Type *t = base_type(type);
|
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) {
|
switch (t->kind) {
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
if (is_type_union(t)) {
|
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_end;
|
||||||
|
|
||||||
case_ast_node(ce, MacroCallExpr, node);
|
case_ast_node(ce, MacroCallExpr, node);
|
||||||
return Ov(c, o, node);
|
error(node, "Macro calls are not yet supported");
|
||||||
|
return kind;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(de, DerefExpr, node);
|
case_ast_node(de, DerefExpr, node);
|
||||||
|
|||||||
+23
-53
@@ -954,7 +954,7 @@ irValue *ir_instr_union_tag_ptr(irProcedure *p, irValue *address) {
|
|||||||
irValue *v = ir_alloc_instr(p, irInstr_UnionTagPtr);
|
irValue *v = ir_alloc_instr(p, irInstr_UnionTagPtr);
|
||||||
irInstr *i = &v->Instr;
|
irInstr *i = &v->Instr;
|
||||||
i->UnionTagPtr.address = address;
|
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;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -962,7 +962,7 @@ irValue *ir_instr_union_tag_value(irProcedure *p, irValue *address) {
|
|||||||
irValue *v = ir_alloc_instr(p, irInstr_UnionTagValue);
|
irValue *v = ir_alloc_instr(p, irInstr_UnionTagValue);
|
||||||
irInstr *i = &v->Instr;
|
irInstr *i = &v->Instr;
|
||||||
i->UnionTagValue.address = address;
|
i->UnionTagValue.address = address;
|
||||||
i->UnionTagValue.type = t_int;
|
i->UnionTagValue.type = t_type_info_ptr;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2218,7 +2218,7 @@ irValue *ir_emit_union_tag_ptr(irProcedure *proc, irValue *u) {
|
|||||||
Type *tpt = ir_type(tag_ptr);
|
Type *tpt = ir_type(tag_ptr);
|
||||||
GB_ASSERT(is_type_pointer(tpt));
|
GB_ASSERT(is_type_pointer(tpt));
|
||||||
tpt = base_type(type_deref(tpt));
|
tpt = base_type(type_deref(tpt));
|
||||||
GB_ASSERT(tpt == t_int);
|
GB_ASSERT(tpt == t_type_info_ptr);
|
||||||
return tag_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);
|
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);
|
result_type = make_type_pointer(a, t->Record.fields[index]->type);
|
||||||
} else if (is_type_union(t)) {
|
} else if (is_type_union(t)) {
|
||||||
type_set_offsets(a, t);
|
GB_ASSERT(index == -1);
|
||||||
GB_ASSERT(t->Record.field_count > 0);
|
return ir_emit_union_tag_ptr(proc, s);
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else if (is_type_tuple(t)) {
|
} else if (is_type_tuple(t)) {
|
||||||
GB_ASSERT(t->Tuple.variable_count > 0);
|
GB_ASSERT(t->Tuple.variable_count > 0);
|
||||||
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
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));
|
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
||||||
result_type = t->Record.fields[index]->type;
|
result_type = t->Record.fields[index]->type;
|
||||||
} else if (is_type_union(t)) {
|
} else if (is_type_union(t)) {
|
||||||
type_set_offsets(a, t);
|
GB_ASSERT(index == -1);
|
||||||
if (index == -1) {
|
return ir_emit_union_tag_value(proc, s);
|
||||||
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;
|
|
||||||
} else if (is_type_tuple(t)) {
|
} else if (is_type_tuple(t)) {
|
||||||
GB_ASSERT(t->Tuple.variable_count > 0);
|
GB_ASSERT(t->Tuple.variable_count > 0);
|
||||||
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
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)) {
|
if (is_type_raw_union(type)) {
|
||||||
type = type->Record.fields[index]->type;
|
type = type->Record.fields[index]->type;
|
||||||
e = ir_emit_conv(proc, e, make_type_pointer(proc->module->allocator, 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) {
|
} 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);
|
e = ir_emit_struct_ep(proc, e, index);
|
||||||
} else if (type->kind == Type_Tuple) {
|
} else if (type->kind == Type_Tuple) {
|
||||||
type = type->Tuple.variables[index]->type;
|
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);
|
ir_emit_store(proc, underlying, value);
|
||||||
|
|
||||||
irValue *tag_ptr = ir_emit_union_tag_ptr(proc, parent);
|
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);
|
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));
|
Type *src = base_type(type_deref(src_type));
|
||||||
GB_ASSERT(is_type_union(src));
|
GB_ASSERT(is_type_union(src));
|
||||||
Type *dst = tuple->Tuple.variables[0]->type;
|
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 *value_ = ir_address_from_load_or_generate_local(proc, value);
|
||||||
|
|
||||||
irValue *tag = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, value_));
|
irValue *tag = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, value_));
|
||||||
irValue *dst_tag = nullptr;
|
irValue *dst_tag = ir_type_info(proc, dst);
|
||||||
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);
|
|
||||||
|
|
||||||
irBlock *ok_block = ir_new_block(proc, nullptr, "union_cast.ok");
|
irBlock *ok_block = ir_new_block(proc, nullptr, "union_cast.ok");
|
||||||
irBlock *end_block = ir_new_block(proc, nullptr, "union_cast.end");
|
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;
|
irValue *cond = nullptr;
|
||||||
if (match_type_kind == MatchType_Union) {
|
if (match_type_kind == MatchType_Union) {
|
||||||
Type *bt = type_deref(case_type);
|
Type *bt = type_deref(case_type);
|
||||||
irValue *index = nullptr;
|
irValue *variant_tag = nullptr;
|
||||||
Type *ut = base_type(type_deref(parent_type));
|
Type *ut = base_type(type_deref(parent_type));
|
||||||
GB_ASSERT(ut->kind == Type_Union);
|
GB_ASSERT(ut->kind == Type_Union);
|
||||||
for (isize variant_index = 1; variant_index < ut->Union.variant_count; variant_index++) {
|
for (isize variant_index = 1; variant_index < ut->Union.variant_count; variant_index++) {
|
||||||
Type *vt = ut->Union.variants[variant_index];
|
Type *vt = ut->Union.variants[variant_index];
|
||||||
if (are_types_identical(vt, bt)) {
|
if (are_types_identical(vt, bt)) {
|
||||||
index = ir_const_int(allocator, variant_index);
|
variant_tag = ir_type_info(proc, vt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GB_ASSERT(index != nullptr);
|
GB_ASSERT(variant_tag != nullptr);
|
||||||
cond = ir_emit_comp(proc, Token_CmpEq, tag_index, index);
|
cond = ir_emit_comp(proc, Token_CmpEq, tag_index, variant_tag);
|
||||||
} else if (match_type_kind == MatchType_Any) {
|
} else if (match_type_kind == MatchType_Any) {
|
||||||
irValue *any_ti = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 1));
|
irValue *any_ti = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 1));
|
||||||
irValue *case_ti = ir_type_info(proc, case_type);
|
irValue *case_ti = ir_type_info(proc, case_type);
|
||||||
@@ -8167,6 +8145,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
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);
|
isize variant_count = gb_max(0, t->Union.variant_count-1);
|
||||||
irValue *memory_types = ir_type_info_member_types_offset(proc, variant_count);
|
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);
|
irValue *count = ir_const_int(a, variant_count);
|
||||||
ir_fill_slice(proc, variant_types, memory_types, count, 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;
|
} break;
|
||||||
@@ -8323,21 +8305,9 @@ void ir_gen_tree(irGen *s) {
|
|||||||
if (tag != nullptr) {
|
if (tag != nullptr) {
|
||||||
Type *tag_type = type_deref(ir_type(tag));
|
Type *tag_type = type_deref(ir_type(tag));
|
||||||
GB_ASSERT(is_type_named(tag_type));
|
GB_ASSERT(is_type_named(tag_type));
|
||||||
Type *ti = base_type(t_type_info);
|
irValue *ti = ir_type_info(proc, tag_type);
|
||||||
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);
|
irValue *ptr = ir_emit_union_tag_ptr(proc, variant_ptr);
|
||||||
ir_emit_store(proc, ptr, tag_val);
|
ir_emit_store(proc, ptr, ti);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GB_ASSERT_MSG(found, "Tag type not found: %s", type_to_string(tag_type));
|
|
||||||
} else {
|
} else {
|
||||||
GB_PANIC("Unhandled TypeInfo type: %s", type_to_string(t));
|
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, "{[0 x <%lld x i8>], ", align);
|
||||||
ir_fprintf(f, "[%lld x i8], ", block_size);
|
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
|
#else
|
||||||
i64 block_size = total_size - build_context.word_size;
|
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);
|
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);
|
GB_ASSERT(init_filename.text[init_filename.len] == 0);
|
||||||
|
|
||||||
char *fullpath_str = gb_path_get_full_name(heap_allocator(), cast(char *)&init_filename[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 = {};
|
TokenPos init_pos = {};
|
||||||
ImportedFile init_imported_file = {init_fullpath, init_fullpath, init_pos};
|
ImportedFile init_imported_file = {init_fullpath, init_fullpath, init_pos};
|
||||||
|
|
||||||
|
|||||||
+11
-4
@@ -123,7 +123,7 @@ struct TypeRecord {
|
|||||||
i32 variant_count; \
|
i32 variant_count; \
|
||||||
AstNode *node; \
|
AstNode *node; \
|
||||||
Scope * scope; \
|
Scope * scope; \
|
||||||
Entity * union__tag; \
|
Entity * union__type_info; \
|
||||||
i64 variant_block_size; \
|
i64 variant_block_size; \
|
||||||
i64 custom_align; \
|
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) {
|
} else if (type->kind == Type_Union) {
|
||||||
if (field_name == "__tag") {
|
if (field_name == "__type_info") {
|
||||||
Entity *e = type->Union.union__tag;
|
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);
|
GB_ASSERT(e != nullptr);
|
||||||
selection_add_index(&sel, -1); // HACK(bill): Leaky memory
|
selection_add_index(&sel, -1); // HACK(bill): Leaky memory
|
||||||
sel.entity = e;
|
sel.entity = e;
|
||||||
|
|
||||||
return sel;
|
return sel;
|
||||||
}
|
}
|
||||||
} else if (type->kind == Type_Record) {
|
} 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 max = 0;
|
||||||
|
i64 field_size = 0;
|
||||||
isize variant_count = t->Union.variant_count;
|
isize variant_count = t->Union.variant_count;
|
||||||
|
|
||||||
i64 field_size = max;
|
|
||||||
|
|
||||||
for (isize i = 1; i < variant_count; i++) {
|
for (isize i = 1; i < variant_count; i++) {
|
||||||
Type *variant_type = t->Union.variants[i];
|
Type *variant_type = t->Union.variants[i];
|
||||||
|
|||||||
Reference in New Issue
Block a user