From 8ad9303a950954cab304ef7ecf798ddeb248e867 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Mon, 22 May 2023 09:54:29 -0500 Subject: [PATCH] bugfix: numerous bugs with new type kind --- compiler/src/astnodes.c | 6 ++- compiler/src/checker.c | 2 + compiler/src/parser.c | 5 +- compiler/src/symres.c | 3 +- compiler/src/types.c | 2 + compiler/src/utils.c | 12 +++++ compiler/src/wasm_emit.c | 33 +++++++++---- tests/tagged_unions.onyx | 100 +++++++++++++++++++++++---------------- 8 files changed, 108 insertions(+), 55 deletions(-) diff --git a/compiler/src/astnodes.c b/compiler/src/astnodes.c index 213650e9..1055ddad 100644 --- a/compiler/src/astnodes.c +++ b/compiler/src/astnodes.c @@ -1239,7 +1239,11 @@ b32 cast_is_legal(Type* from_, Type* to_, char** err_msg) { return 0; } - + if (from->kind == Type_Kind_Union && to->kind == Type_Kind_Enum) { + if (from->Union.tag_type->id == to->id) { + return 1; + } + } if (from->kind == Type_Kind_Enum) from = from->Enum.backing; if (to->kind == Type_Kind_Enum) to = to->Enum.backing; diff --git a/compiler/src/checker.c b/compiler/src/checker.c index 4f5a6cc4..fe492897 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -3641,6 +3641,8 @@ void check_entity(Entity* ent) { case Entity_Type_Type_Alias: if (ent->type_alias->kind == Ast_Kind_Struct_Type) cs = check_struct((AstStructType *) ent->type_alias); + else if (ent->type_alias->kind == Ast_Kind_Union_Type) + cs = check_union((AstUnionType *) ent->type_alias); else cs = check_type(&ent->type_alias); break; diff --git a/compiler/src/parser.c b/compiler/src/parser.c index 358083ae..8ad16fb6 100644 --- a/compiler/src/parser.c +++ b/compiler/src/parser.c @@ -2171,7 +2171,10 @@ static AstStructType* parse_struct(OnyxParser* parser) { while (parser->curr->type == '#') { if (parser->hit_unexpected_token) return NULL; - if (parse_possible_directive(parser, "union")) s_node->is_union = 1; + if (next_tokens_are(parser, 2, '#', Token_Type_Keyword_Union)) { + consume_tokens(parser, 2); + s_node->is_union = 1; + } else if (parse_possible_directive(parser, "pack")) s_node->is_packed = 1; diff --git a/compiler/src/symres.c b/compiler/src/symres.c index 50b39221..086cc23a 100644 --- a/compiler/src/symres.c +++ b/compiler/src/symres.c @@ -365,7 +365,8 @@ static SymresStatus symres_field_access(AstFieldAccess** fa) { if (expr->kind == Ast_Kind_Struct_Type || expr->kind == Ast_Kind_Poly_Struct_Type || expr->kind == Ast_Kind_Enum_Type || - expr->kind == Ast_Kind_Type_Raw_Alias) { + expr->kind == Ast_Kind_Type_Raw_Alias || + expr->kind == Ast_Kind_Union_Type) { force_a_lookup = 1; } diff --git a/compiler/src/types.c b/compiler/src/types.c index 6b92c7c8..cd2a4082 100644 --- a/compiler/src/types.c +++ b/compiler/src/types.c @@ -694,6 +694,8 @@ static Type* type_build_from_ast_inner(bh_allocator alloc, AstType* type_node, b u_type = union_->pending_type; } + union_->pending_type_is_valid = 1; + // // All variants need to have type know. bh_arr_each(AstUnionVariant *, pvariant, union_->variants) { diff --git a/compiler/src/utils.c b/compiler/src/utils.c index 3bee7b73..70d3eb6a 100644 --- a/compiler/src/utils.c +++ b/compiler/src/utils.c @@ -330,6 +330,18 @@ all_types_peeled_off: return result; } + case Ast_Kind_Union_Type: { + AstUnionType* utype = (AstUnionType *) node; + if (utype->utcache != NULL) { + // + // nocheckin Should this be hard coded? + if (!strcmp(symbol, "tag_enum")) { + return (AstNode *) utype->utcache->Union.tag_type->ast_type; + } + } + break; + } + case Ast_Kind_Poly_Struct_Type: { AstPolyStructType* stype = ((AstPolyStructType *) node); return symbol_raw_resolve(stype->scope, symbol); diff --git a/compiler/src/wasm_emit.c b/compiler/src/wasm_emit.c index a42c15e9..2ec076f1 100644 --- a/compiler/src/wasm_emit.c +++ b/compiler/src/wasm_emit.c @@ -983,24 +983,29 @@ EMIT_FUNC(store_instruction, Type* type, u32 offset) { i32 store_size = type_size_of(type); i32 is_basic = type->kind == Type_Kind_Basic || type->kind == Type_Kind_Pointer || type->kind == Type_Kind_MultiPointer; - if (is_basic && (type->Basic.flags & Basic_Flag_Pointer)) { + if (!is_basic) { + onyx_report_error((OnyxFilePos) { 0 }, Error_Critical, + "Failed to generate store instruction for type '%s'. (compiler bug)", + type_get_name(type)); + } + + if (type->Basic.flags & Basic_Flag_Pointer) { WID(NULL, WI_I32_STORE, ((WasmInstructionData) { 2, offset })); - } else if (is_basic && ((type->Basic.flags & Basic_Flag_Integer) - || (type->Basic.flags & Basic_Flag_Boolean) - || (type->Basic.flags & Basic_Flag_Type_Index))) { + } else if ((type->Basic.flags & Basic_Flag_Integer) + || (type->Basic.flags & Basic_Flag_Boolean) + || (type->Basic.flags & Basic_Flag_Type_Index)) { if (store_size == 1) WID(NULL, WI_I32_STORE_8, ((WasmInstructionData) { alignment, offset })); else if (store_size == 2) WID(NULL, WI_I32_STORE_16, ((WasmInstructionData) { alignment, offset })); else if (store_size == 4) WID(NULL, WI_I32_STORE, ((WasmInstructionData) { alignment, offset })); else if (store_size == 8) WID(NULL, WI_I64_STORE, ((WasmInstructionData) { alignment, offset })); - } else if (is_basic && (type->Basic.flags & Basic_Flag_Float)) { + } else if (type->Basic.flags & Basic_Flag_Float) { if (store_size == 4) WID(NULL, WI_F32_STORE, ((WasmInstructionData) { alignment, offset })); else if (store_size == 8) WID(NULL, WI_F64_STORE, ((WasmInstructionData) { alignment, offset })); - } else if (is_basic && (type->Basic.flags & Basic_Flag_SIMD)) { + } else if (type->Basic.flags & Basic_Flag_SIMD) { WID(NULL, WI_V128_STORE, ((WasmInstructionData) { alignment, offset })); - } else { - onyx_report_error((OnyxFilePos) { 0 }, Error_Critical, - "Failed to generate store instruction for type '%s'.", - type_get_name(type)); + } else if (type->Basic.kind == Basic_Kind_Void) { + // Do nothing, but drop the destination pointer. + WI(NULL, WI_DROP); } *pcode = code; @@ -3794,6 +3799,14 @@ EMIT_FUNC(cast, AstUnaryOp* cast) { return; } + if (from->kind == Type_Kind_Union) { + // This should be check in the checker that are only casting + // to the union's tag_type. + emit_load_instruction(mod, &code, from->Union.tag_type, 0); + *pcode = code; + return; + } + if (to->kind == Type_Kind_Basic && from->kind == Type_Kind_Function) { WI(NULL, WI_DROP); WI(NULL, WI_DROP); diff --git a/tests/tagged_unions.onyx b/tests/tagged_unions.onyx index 95a13dcc..5bfb2fa4 100644 --- a/tests/tagged_unions.onyx +++ b/tests/tagged_unions.onyx @@ -4,58 +4,74 @@ use core {*} SimpleUnion :: union { a: i32; b: struct { - c, d: str; + c: str; }; + + empty: void; + large: i64; +} + +call_test :: (u_: SimpleUnion) { + u := u_; + __byte_dump(&u, sizeof typeof u); + + switch cast(SimpleUnion.tag_enum) u { + case .a do println("It was a!"); + case .b do println("It was B!"); + case .empty do println("It was EMPTY!"); + case .large do println("It was a large number!"); + } } simple_test :: () { - u := SimpleUnion.{ a = 123 }; + u := SimpleUnion.{ b = .{ "asdf" } }; + u = .{ a = 123 }; + u = .{ empty = .{} }; + u = .{ large = 0x0123456789abcdef }; - println(sizeof str); - println(sizeof str * 2 + sizeof i32); + println(cast(SimpleUnion.tag_enum) u); - __byte_dump(&u, sizeof typeof u); - println(u.a); + call_test(u); } -main :: () {simple_test();} +main :: () {simple_test();} //link_test();} +Link :: union { + End: void; + Next: struct { + data: i32; + next: &Link; + } +} + +/* +print_links :: (l: Link) { + walker := l; + while true { + switch walker { + case Link.End do break; + case Link.Next => &next { + printf("{} ", next.data); + walker = next.next; + } + } + } +} + +link_test :: () { + l := Link.{ + Next = .{ + data = 123, + next = &Link.{ + End = .{} + } + } + }; + + print_links(l); +} +*/ -// Link :: union { -// End: void; -// Next: struct { -// data: i32; -// next: &Link; -// } -// } -// -// print_links :: (l: Link) { -// walker := l; -// while true { -// switch walker { -// case .End do break; -// case .Next { -// next: struct {data: i32; next: rawptr}; -// printf("{} ", next.data); -// walker = next.next; -// } -// } -// } -// } -// -// link_test :: () { -// l := Link.{ -// Next = .{ -// data = 123, -// next = &Link.{ -// End = .{} -// } -// } -// }; -// -// print_links(l); -// } -// // main :: () { link_test(); } // Optional :: union (T: type_expr) { -- 2.25.1