diff options
| author | Carson Fleming <cflems@cflems.net> | 2026-07-18 23:38:59 -0700 |
|---|---|---|
| committer | Carson Fleming <cflems@cflems.net> | 2026-07-18 23:38:59 -0700 |
| commit | 1e712cf04567c48100526f9a3a0f796497168268 (patch) | |
| tree | 28a1676d36620500578d1a386d8d0b976637ce9f | |
| parent | feb1cac139ca5aa2ba76ac6a0a318bced03d8638 (diff) | |
| download | ccc-1e712cf04567c48100526f9a3a0f796497168268.tar.gz | |
type system surely
| -rw-r--r-- | ast.h | 7 | ||||
| -rw-r--r-- | codegen.c | 34 | ||||
| -rw-r--r-- | parser.c | 9 | ||||
| -rw-r--r-- | scope.c | 2 | ||||
| -rw-r--r-- | scope.h | 6 | ||||
| -rw-r--r-- | type_checker.c | 9 |
6 files changed, 37 insertions, 30 deletions
@@ -7,8 +7,7 @@ struct stmt_node; struct expr_node; struct type_ref_node { - unsigned char ptr_level; - const struct type_def* def_ref; + struct type type; }; struct int_lit_node { @@ -126,6 +125,8 @@ struct fn_decl_node { struct args_decl_node* args; struct group_node body; struct scope* scope; + + const struct type_def* resolved_return_type; }; struct return_node { @@ -189,7 +190,7 @@ struct ast { const struct type_def* char_type; const struct type_def* integral_type; const struct type_def* decimal_type; - const struct type_def* string_type; + const struct type_def* pointer_type; }; void ast_destroy(struct ast* ast); @@ -225,12 +225,6 @@ static void emit_cmp_zero(FILE* outfile, const struct lval_def* lval) { fprintf(outfile, ", 0\n"); } -/* TODO: move this utility to the type checker and use resolved_type */ -static unsigned long long get_type_size(const struct type_ref_node* type) { - if (type->ptr_level > 0) return PTR_SIZE; - return type->def_ref->sz; -} - static inline struct lval_def make_stack_lval( FILE* outfile, const struct type_def* type @@ -310,7 +304,8 @@ static struct var_def* emit_var_decl( FILE* outfile, const struct var_decl_node* node ) { - struct lval_def var_dst = make_stack_lval(outfile, node->type.def_ref); + struct lval_def var_dst = + make_stack_lval(outfile, node->def_ref->resolved_type); fprintf(outfile, "\t; '%s' lives in: ", node->def_ref->name); emit_storage_loc(outfile, &var_dst.loc, var_dst.type->sz); @@ -365,7 +360,7 @@ static void emit_call( struct args_eval_node* arg_eval = node->args; while (arg_decl != NULL && arg_eval != NULL) { struct lval_def arg_dst = - make_stack_lval(outfile, arg_decl->decl->type.def_ref); + make_stack_lval(outfile, arg_decl->decl->def_ref->resolved_type); emit_expr(outfile, arg_eval->expr, &arg_dst); arg_decl = arg_decl->next; @@ -384,20 +379,21 @@ static void emit_call( unsigned char arg_regnum = 0; arg_decl = node->called_fn_ref->args; while (arg_decl != NULL) { - unsigned long long type_sz = get_type_size(&arg_decl->decl->type); - arg_bp_offset += type_sz; + const struct type_def* arg_type = + arg_decl->decl->def_ref->resolved_type; + arg_bp_offset += arg_type->sz; struct lval_def arg_dst; if (arg_regnum < CC_N_REGS) arg_dst = (struct lval_def) { - .type = arg_decl->decl->type.def_ref, + .type = arg_type, .loc = (struct storage_location) { .type = STO_REG, .reg = CALLING_CONV[arg_regnum++], }, }; else - arg_dst = make_stack_lval(outfile, arg_decl->decl->type.def_ref); + arg_dst = make_stack_lval(outfile, arg_type); emit_mov(outfile, &arg_dst, &(struct storage_location) { .type = STO_STACK, @@ -408,7 +404,7 @@ static void emit_call( fprintf(outfile, "\tcall %s\n", node->called_fn_ref->name); if (dst != NULL) { - if (get_type_size(&node->called_fn_ref->return_type) == 0) + if (node->called_fn_ref->resolved_return_type->sz == 0) CGEN_PANIC("can't assign the result of a void function"); emit_mov(outfile, dst, &RV_LOC); @@ -542,10 +538,9 @@ static void emit_expr( static void emit_return(FILE* outfile, const struct return_node* node) { if (active_fn == NULL) CGEN_PANIC("must be inside a function to return"); - const struct type_def* return_type = active_fn->return_type.def_ref; if (node->ret_val != NULL) { - if (return_type->sz == 0) + if (active_fn->resolved_return_type->sz == 0) CGEN_PANIC( "returning a value from void function %s", active_fn->name); @@ -554,9 +549,9 @@ static void emit_return(FILE* outfile, const struct return_node* node) { node->ret_val, &(struct lval_def) { .loc = RV_LOC, - .type = return_type, + .type = active_fn->resolved_return_type, }); - } else if (return_type > 0) { + } else if (active_fn->resolved_return_type > 0) { CGEN_PANIC( "non-void function %s should return a value", active_fn->name); } @@ -667,6 +662,7 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) { active_fn->name); active_fn = node; + /* TODO: we need to account for the base pointer moving in var locs */ fprintf(outfile, "%s:\n", node->name); fprintf(outfile, "\tpush rbp\n"); fprintf(outfile, "\tmov rbp, rsp\n"); @@ -679,7 +675,7 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) { for (; arg_decl != NULL; arg_decl = arg_decl->next) { struct var_def* arg_def = arg_decl->decl->def_ref; struct lval_def arg_dst = - make_stack_lval(outfile, arg_decl->decl->type.def_ref); + make_stack_lval(outfile, arg_def->resolved_type); arg_def->loc = arg_dst.loc; struct storage_location arg_src; @@ -693,7 +689,7 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) { .type = STO_STACK, .bp_offset = spilled_bp_ofs, }; - spilled_bp_ofs -= arg_decl->decl->type.def_ref->sz; + spilled_bp_ofs -= arg_def->resolved_type->sz; } emit_mov(outfile, &arg_dst, &arg_src); } @@ -79,13 +79,15 @@ static void parse_type_ref(struct type_ref_node* p_node) { PARSER_PANIC("unknown type name: %s", tok.data.ident); free(tok.data.ident); - p_node->def_ref = type_def; + p_node->type = (struct type) { + .raw_type = type_def, + .ptr_level = 0, + }; peek_or_panic(); - p_node->ptr_level = 0; while (tok.type == TK_STAR) { expect(TK_STAR); - p_node->ptr_level++; + p_node->type.ptr_level++; peek_or_panic(); } } @@ -278,6 +280,7 @@ static void parse_var_decl(struct var_decl_node* p_node) { expect(TK_IDENT); p_node->def_ref = scope_define_var(scope, (struct var_def) { + .type = &p_node->type.type, .name = tok.data.ident, .loc.type = STO_UNRESOLVED, }); @@ -221,7 +221,7 @@ void scope_install_default_types(struct ast* ast) { .is_signed = true, .is_floating = false, }); - ast->string_type = ast->integral_type; /* TODO: support pointers */ + ast->pointer_type = ast->integral_type; /* TODO: support pointers */ scope_define_type(ast->root_scope, (struct type_def) { .key = { @@ -21,6 +21,11 @@ struct storage_location { }; }; +struct type { + const struct type_def* raw_type; + unsigned char ptr_level; +}; + struct type_key { char* name; unsigned char how_long; @@ -36,6 +41,7 @@ struct type_def { }; struct var_def { + const struct type* type; char* name; struct storage_location loc; const struct type_def* resolved_type; diff --git a/type_checker.c b/type_checker.c index d8534e2..8a07f2a 100644 --- a/type_checker.c +++ b/type_checker.c @@ -50,8 +50,9 @@ static void exit_scope(struct scope* child_scope) { static const struct type_def* resolve_type_ref(struct type_ref_node* node) { /* TODO: support pointers and such */ - if (node->def_ref == NULL) TYPE_PANIC("use of unresolved type"); - return node->def_ref; + if (node->type.raw_type == NULL) TYPE_PANIC("use of unresolved type"); + if (node->type.ptr_level > 0) return ast_ref->pointer_type; + return node->type.raw_type; } static const struct type_def* resolve_int_lit(struct int_lit_node* node) { @@ -67,7 +68,7 @@ static const struct type_def* resolve_char_lit(struct char_lit_node* node) { } static const struct type_def* resolve_str_lit(struct str_lit_node* node) { - return ast_ref->string_type; + return ast_ref->pointer_type; } static const struct type_def* resolve_var_ref(struct var_ref_node* node) { @@ -235,7 +236,7 @@ static void type_check_group(struct group_node* node) { static void type_check_fn_decl(struct fn_decl_node* node) { enter_scope(node->scope); - node->return_type.def_ref = resolve_type_ref(&node->return_type); + node->resolved_return_type = resolve_type_ref(&node->return_type); for (struct args_decl_node* arg_decl = node->args; arg_decl != NULL; |
