Union type sizing and code generation
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user