Union type sizing and code generation
This commit is contained in:
@@ -725,8 +725,9 @@ gen_ast(Ast *ast) {
|
|||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AST_UNION:
|
||||||
CASE(STRUCT, Decl) {
|
CASE(STRUCT, Decl) {
|
||||||
gen("struct ");
|
gen("%s ", node->kind == AST_STRUCT ? "struct" : "union");
|
||||||
gen("%Q{", node->unique_name);
|
gen("%Q{", node->unique_name);
|
||||||
global_indent++;
|
global_indent++;
|
||||||
is_inside_struct++;
|
is_inside_struct++;
|
||||||
@@ -888,6 +889,9 @@ compile_to_c_code() {
|
|||||||
if (it->kind == AST_STRUCT) {
|
if (it->kind == AST_STRUCT) {
|
||||||
genln("typedef struct %Q %Q;", it->unique_name, it->unique_name);
|
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
|
// Generate slice and tuple types
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ resolve_everything_in_module(Ast_Module *module) {
|
|||||||
For_Named(file->decls, decl) {
|
For_Named(file->decls, decl) {
|
||||||
resolve_name(file, decl->pos, decl->name);
|
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);
|
type_complete(decl->type_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -980,7 +980,7 @@ parse_file(Ast_File *file) {
|
|||||||
if (!decl) break;
|
if (!decl) break;
|
||||||
|
|
||||||
set_flag(decl->flags, AST_GLOBAL);
|
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 = pctx->type_type;
|
||||||
decl->type_val = type_incomplete(decl);
|
decl->type_val = type_incomplete(decl);
|
||||||
decl->state = DECL_RESOLVED;
|
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_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_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_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_array(Ast_Type *a) { return a->kind == TYPE_ARRAY; }
|
||||||
force_inline B32 is_slice(Ast_Type *a) { return a->kind == TYPE_SLICE; }
|
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_complete(Ast_Type *type);
|
||||||
CORE_Static void
|
CORE_Static void
|
||||||
type_struct_complete(Ast_Type *type, Ast_Decl *node) {
|
type_struct_complete(Ast_Type *type, Ast_Decl *node) {
|
||||||
assert(node->kind == AST_STRUCT);
|
assert(node->kind == AST_STRUCT || node->kind == AST_UNION);
|
||||||
// @todo: compute size, alignement, offset !!!
|
Scratch_Scope scratch(pctx->scratch);
|
||||||
// @note: resolve all the struct members first
|
|
||||||
Arena *scratch = pctx->scratch;
|
|
||||||
Scratch_Scope __scope(scratch);
|
|
||||||
|
|
||||||
Array<Ast_Resolved_Member> members = {scratch};
|
if (node->kind == AST_STRUCT) {
|
||||||
|
// First resolve and compute sizes of struct members
|
||||||
|
//
|
||||||
|
Array<Ast_Resolved_Member> members = {scratch.arena};
|
||||||
type->kind = TYPE_COMPLETING;
|
type->kind = TYPE_COMPLETING;
|
||||||
size_t members_size = 0;
|
size_t members_size = 0;
|
||||||
For_Named(node->scope->decls, decl) {
|
For(node->scope->decls) {
|
||||||
resolve_decl(decl);
|
resolve_decl(it);
|
||||||
assert(decl->type->kind != TYPE_INCOMPLETE);
|
assert(it->type->kind != TYPE_INCOMPLETE);
|
||||||
assert(is_pow2(decl->type->align));
|
assert(is_pow2(it->type->align));
|
||||||
|
|
||||||
Ast_Resolved_Member m = {};
|
Ast_Resolved_Member m = {};
|
||||||
m.offset = type->size;
|
m.offset = type->size;
|
||||||
members_size += decl->type->size;
|
members_size += it->type->size;
|
||||||
type->align = max(type->align, decl->type->align);
|
type->align = max(type->align, it->type->align);
|
||||||
type->size = decl->type->size + align_up(type->size, decl->type->align);
|
type->size = it->type->size + align_up(type->size, it->type->align);
|
||||||
|
|
||||||
m.name = decl->name;
|
m.name = it->name;
|
||||||
m.value = decl->value;
|
m.value = it->value;
|
||||||
members.add(m);
|
members.add(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Then compute size of struct itself
|
||||||
|
//
|
||||||
type->size = align_up(type->size, type->align);
|
type->size = align_up(type->size, type->align);
|
||||||
type->padding = type->size - members_size;
|
type->padding = type->size - members_size;
|
||||||
type->agg.members = members.tight_copy(pctx->perm);
|
type->agg.members = members.tight_copy(pctx->perm);
|
||||||
type->kind = TYPE_STRUCT;
|
type->kind = TYPE_STRUCT;
|
||||||
node->unique_name = pctx->intern(string_fmt(scratch, "%Q%Q", pctx->symbol_prefix, node->name));
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE_Static void
|
CORE_Static void
|
||||||
@@ -301,6 +337,7 @@ typename_base(String_Builder *sb, Ast_Type *type) {
|
|||||||
sb->addf("[]");
|
sb->addf("[]");
|
||||||
typename_base(sb, type->base);
|
typename_base(sb, type->base);
|
||||||
break;
|
break;
|
||||||
|
case TYPE_UNION:
|
||||||
case TYPE_STRUCT:
|
case TYPE_STRUCT:
|
||||||
case TYPE_ENUM: {
|
case TYPE_ENUM: {
|
||||||
// @todo direct access
|
// @todo direct access
|
||||||
@@ -320,16 +357,16 @@ typename_base(String_Builder *sb, Ast_Type *type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CORE_Static String
|
CORE_Static String
|
||||||
get_typename(Allocator *a, Ast_Type *type) {
|
get_typename(Ast_Type *type) {
|
||||||
pctx->helper_builder.addf("[");
|
pctx->helper_builder.addf("[");
|
||||||
typename_base(&pctx->helper_builder, type);
|
typename_base(&pctx->helper_builder, type);
|
||||||
pctx->helper_builder.addf("]");
|
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();
|
pctx->helper_builder.reset();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE_Static String
|
CORE_Static String
|
||||||
typestring(Ast_Type *type) {
|
typestring(Ast_Type *type) {
|
||||||
return get_typename(pctx->stage_arena, type);
|
return get_typename(type);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user