From 9b91f77cf0ce65f264e47b655b122e234f3d48f2 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Wed, 29 Mar 2023 09:52:24 +0200 Subject: [PATCH] Union type sizing and code generation --- core_codegen_c_language.cpp | 58 ++++++++++++----------- core_compiler.cpp | 2 +- core_parsing.cpp | 2 +- core_types.cpp | 93 ++++++++++++++++++++++++++----------- 4 files changed, 98 insertions(+), 57 deletions(-) diff --git a/core_codegen_c_language.cpp b/core_codegen_c_language.cpp index 07f999a..1a98ce8 100644 --- a/core_codegen_c_language.cpp +++ b/core_codegen_c_language.cpp @@ -725,36 +725,37 @@ gen_ast(Ast *ast) { BREAK(); } - CASE(STRUCT, Decl) { - gen("struct "); - gen("%Q{", node->unique_name); - global_indent++; - is_inside_struct++; - For(node->scope->decls) { - genln(""); - gen_ast(it); + case AST_UNION: + CASE(STRUCT, Decl) { + gen("%s ", node->kind == AST_STRUCT ? "struct" : "union"); + gen("%Q{", node->unique_name); + global_indent++; + is_inside_struct++; + For(node->scope->decls) { + genln(""); + gen_ast(it); + } + + is_inside_struct--; + global_indent--; + genln("};"); + BREAK(); } - is_inside_struct--; - global_indent--; - genln("};"); - BREAK(); - } - - CASE(ENUM, Decl) { - gen("/*enum %Q{", node->name); - // @todo add typespec - global_indent++; - For(node->scope->decls) { - genln("%Q", it->name); - gen(" = "); - gen_value(it->pos, it->value); - gen(","); + CASE(ENUM, Decl) { + gen("/*enum %Q{", node->name); + // @todo add typespec + global_indent++; + For(node->scope->decls) { + genln("%Q", it->name); + gen(" = "); + gen_value(it->pos, it->value); + gen(","); + } + global_indent--; + genln("};*/"); + BREAK(); } - global_indent--; - genln("};*/"); - BREAK(); - } case AST_TYPE: CASE(CONST, Decl) { @@ -888,6 +889,9 @@ compile_to_c_code() { if (it->kind == AST_STRUCT) { genln("typedef struct %Q %Q;", it->unique_name, it->unique_name); } + else if (it->kind == AST_UNION) { + genln("typedef union %Q %Q;", it->unique_name, it->unique_name); + } } // Generate slice and tuple types diff --git a/core_compiler.cpp b/core_compiler.cpp index 836efe1..a9e4e07 100644 --- a/core_compiler.cpp +++ b/core_compiler.cpp @@ -291,7 +291,7 @@ resolve_everything_in_module(Ast_Module *module) { For_Named(file->decls, decl) { resolve_name(file, decl->pos, decl->name); - if (decl->kind == AST_STRUCT) { + if (decl->kind == AST_STRUCT || decl->kind == AST_UNION) { type_complete(decl->type_val); } } diff --git a/core_parsing.cpp b/core_parsing.cpp index 2ed93ca..da625f4 100644 --- a/core_parsing.cpp +++ b/core_parsing.cpp @@ -980,7 +980,7 @@ parse_file(Ast_File *file) { if (!decl) break; set_flag(decl->flags, AST_GLOBAL); - if (decl->kind == AST_STRUCT) { + if (decl->kind == AST_STRUCT || decl->kind == AST_UNION) { decl->type = pctx->type_type; decl->type_val = type_incomplete(decl); decl->state = DECL_RESOLVED; diff --git a/core_types.cpp b/core_types.cpp index a4d16aa..fa9199e 100644 --- a/core_types.cpp +++ b/core_types.cpp @@ -29,6 +29,7 @@ get_name_of_type(Ast_Type *type) { //----------------------------------------------------------------------------- force_inline B32 is_any(Ast_Type *a) { return a == pctx->type_any; } force_inline B32 is_struct(Ast_Type *a) { return a->kind == TYPE_STRUCT; } +force_inline B32 is_union(Ast_Type *a) { return a->kind == TYPE_UNION; } force_inline B32 is_lambda(Ast_Type *a) { return a->kind == TYPE_LAMBDA; } force_inline B32 is_array(Ast_Type *a) { return a->kind == TYPE_ARRAY; } force_inline B32 is_slice(Ast_Type *a) { return a->kind == TYPE_SLICE; } @@ -226,35 +227,70 @@ type_incomplete(Ast *ast) { CORE_Static void type_complete(Ast_Type *type); CORE_Static void type_struct_complete(Ast_Type *type, Ast_Decl *node) { - assert(node->kind == AST_STRUCT); - // @todo: compute size, alignement, offset !!! - // @note: resolve all the struct members first - Arena *scratch = pctx->scratch; - Scratch_Scope __scope(scratch); + assert(node->kind == AST_STRUCT || node->kind == AST_UNION); + Scratch_Scope scratch(pctx->scratch); - Array members = {scratch}; - type->kind = TYPE_COMPLETING; - size_t members_size = 0; - For_Named(node->scope->decls, decl) { - resolve_decl(decl); - assert(decl->type->kind != TYPE_INCOMPLETE); - assert(is_pow2(decl->type->align)); + if (node->kind == AST_STRUCT) { + // First resolve and compute sizes of struct members + // + Array members = {scratch.arena}; + type->kind = TYPE_COMPLETING; + size_t members_size = 0; + For(node->scope->decls) { + resolve_decl(it); + assert(it->type->kind != TYPE_INCOMPLETE); + assert(is_pow2(it->type->align)); - Ast_Resolved_Member m = {}; - m.offset = type->size; - members_size += decl->type->size; - type->align = max(type->align, decl->type->align); - type->size = decl->type->size + align_up(type->size, decl->type->align); + Ast_Resolved_Member m = {}; + m.offset = type->size; + members_size += it->type->size; + type->align = max(type->align, it->type->align); + type->size = it->type->size + align_up(type->size, it->type->align); - m.name = decl->name; - m.value = decl->value; - members.add(m); + m.name = it->name; + m.value = it->value; + members.add(m); + } + + // + // Then compute size of struct itself + // + type->size = align_up(type->size, type->align); + type->padding = type->size - members_size; + type->agg.members = members.tight_copy(pctx->perm); + type->kind = TYPE_STRUCT; + node->unique_name = pctx->internf("%Q%Q", pctx->symbol_prefix, node->name); + } + else { + assert(node->kind == AST_UNION); + // First resolve and compute sizes of union members + // + Array members = {scratch.arena}; + type->kind = TYPE_COMPLETING; + For(node->scope->decls) { + resolve_decl(it); + assert(it->type->kind != TYPE_INCOMPLETE); + assert(is_pow2(it->type->align)); + + Ast_Resolved_Member m = {}; + m.offset = type->size; + + type->align = max(type->align, it->type->align); + type->size = max(it->type->size, type->size); + + m.name = it->name; + m.value = it->value; + members.add(m); + } + + // + // Then compute size of union itself + // + type->size = align_up(type->size, type->align); + type->agg.members = members.tight_copy(pctx->perm); + type->kind = TYPE_UNION; + node->unique_name = pctx->internf("%Q%Q", pctx->symbol_prefix, node->name); } - type->size = align_up(type->size, type->align); - type->padding = type->size - members_size; - type->agg.members = members.tight_copy(pctx->perm); - type->kind = TYPE_STRUCT; - node->unique_name = pctx->intern(string_fmt(scratch, "%Q%Q", pctx->symbol_prefix, node->name)); } CORE_Static void @@ -301,6 +337,7 @@ typename_base(String_Builder *sb, Ast_Type *type) { sb->addf("[]"); typename_base(sb, type->base); break; + case TYPE_UNION: case TYPE_STRUCT: case TYPE_ENUM: { // @todo direct access @@ -320,16 +357,16 @@ typename_base(String_Builder *sb, Ast_Type *type) { } CORE_Static String -get_typename(Allocator *a, Ast_Type *type) { +get_typename(Ast_Type *type) { pctx->helper_builder.addf("["); typename_base(&pctx->helper_builder, type); pctx->helper_builder.addf("]"); - String result = string_flatten(a, &pctx->helper_builder); + String result = string_flatten(pctx->stage_arena, &pctx->helper_builder); pctx->helper_builder.reset(); return result; } CORE_Static String typestring(Ast_Type *type) { - return get_typename(pctx->stage_arena, type); + return get_typename(type); }