Union type sizing and code generation

This commit is contained in:
Krzosa Karol
2023-03-29 09:52:24 +02:00
parent b572f4ef7c
commit 9b91f77cf0
4 changed files with 98 additions and 57 deletions

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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<Ast_Resolved_Member> 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<Ast_Resolved_Member> 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<Ast_Resolved_Member> 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);
}