diff options
Diffstat (limited to 'codegen.c')
| -rw-r--r-- | codegen.c | 110 |
1 files changed, 65 insertions, 45 deletions
@@ -15,7 +15,7 @@ } struct lval_def { - const struct type_def* type; + const struct type* type; struct storage_location loc; }; @@ -57,7 +57,7 @@ static void exit_scope(struct scope* child_scope, bool save_bp_offset) { if (save_bp_offset) scope->bp_offset = child_scope->bp_offset; } -static struct lval_def allocate_register(const struct type_def* type) { +static struct lval_def allocate_register(const struct type* type) { return (struct lval_def) { .loc = { .type = STO_REG, @@ -67,12 +67,25 @@ static struct lval_def allocate_register(const struct type_def* type) { }; } +static const struct data_type* get_effective_data_type( + const struct type* type +) { + switch (type->type) { + case TP_DATA: + return type->data.data_type; + case TP_PTR: + return &long_long_type; + } + CGEN_PANIC("unhandled type of type case"); +} + static struct lval_def allocate_stack( FILE* outfile, - const struct type_def* type + const struct type* type ) { - fprintf(outfile, "\tsub rsp, %llu\n", type->sz); - scope->bp_offset += type->sz; + integral_t type_sz = get_effective_data_type(type)->sz; + fprintf(outfile, "\tsub rsp, %llu\n", type_sz); + scope->bp_offset += type_sz; return (struct lval_def) { .loc = { .type = STO_STACK, @@ -84,15 +97,18 @@ static struct lval_def allocate_stack( static struct lval_def allocate_temporary( FILE* outfile, - const struct type_def* type + const struct type* type ) { return allocate_stack(outfile, type); } static void deallocate_temporary(FILE* outfile, const struct lval_def* tmp) { if (tmp->loc.type == STO_STACK) { - fprintf(outfile, "\tadd rsp, %llu\n", tmp->type->sz); - scope->bp_offset -= tmp->type->sz; + integral_t type_sz = get_effective_data_type(tmp->type)->sz; + fprintf(outfile, "\tadd rsp, %llu\n", type_sz); + scope->bp_offset -= type_sz; + } else if (tmp->loc.type == STO_REG) { + /* TOOD: release the register back to the algo */ } } @@ -168,18 +184,19 @@ static void emit_mov( /* first optimization: if dst == src, emit nothing */ if (locs_equal(&dst->loc, src)) return; + integral_t dst_sz = get_effective_data_type(dst->type)->sz; switch (dst->loc.type) { case STO_REG: - if (src->type == STO_REG && dst->type->sz < 4) { + if (src->type == STO_REG && dst_sz < 4) { fprintf(outfile, "\tmovzx "); emit_storage_loc(outfile, &dst->loc, FULL_REG_SZ); } else { fprintf(outfile, "\tmov "); - emit_storage_loc(outfile, &dst->loc, dst->type->sz); + emit_storage_loc(outfile, &dst->loc, dst_sz); } fprintf(outfile, ", "); - emit_storage_loc(outfile, src, dst->type->sz); + emit_storage_loc(outfile, src, dst_sz); break; case STO_STACK: if (src->type == STO_STACK) { @@ -191,11 +208,11 @@ static void emit_mov( } fprintf(outfile, "\tmov "); - if (src->type == STO_IMM) emit_size_const(outfile, dst->type->sz); + if (src->type == STO_IMM) emit_size_const(outfile, dst_sz); - emit_storage_loc(outfile, &dst->loc, dst->type->sz); + emit_storage_loc(outfile, &dst->loc, dst_sz); fprintf(outfile, ", "); - emit_storage_loc(outfile, src, dst->type->sz); + emit_storage_loc(outfile, src, dst_sz); break; case STO_LABEL: case STO_IMM: @@ -208,13 +225,14 @@ static void emit_mov( static void emit_cmp_zero(FILE* outfile, const struct lval_def* lval) { fprintf(outfile, "\tcmp "); + integral_t type_sz = get_effective_data_type(lval->type)->sz; switch (lval->loc.type) { case STO_REG: - emit_storage_loc(outfile, &lval->loc, lval->type->sz); + emit_storage_loc(outfile, &lval->loc, type_sz); break; case STO_STACK: - emit_size_const(outfile, lval->type->sz); - emit_storage_loc(outfile, &lval->loc, lval->type->sz); + emit_size_const(outfile, type_sz); + emit_storage_loc(outfile, &lval->loc, type_sz); break; case STO_LABEL: case STO_IMM: @@ -225,13 +243,6 @@ static void emit_cmp_zero(FILE* outfile, const struct lval_def* lval) { fprintf(outfile, ", 0\n"); } -static inline struct lval_def make_stack_lval( - FILE* outfile, - const struct type_def* type -) { - return allocate_stack(outfile, type); -} - static void emit_expr( FILE* outfile, const struct expr_node* node, @@ -305,11 +316,12 @@ static void emit_var_decl( const struct var_decl_node* node ) { struct lval_def var_dst = - make_stack_lval(outfile, node->def_ref->resolved_type); + allocate_stack(outfile, node->def_ref->type); node->def_ref->loc = var_dst.loc; fprintf(outfile, "\t; '%s' lives in: ", node->def_ref->name); - emit_storage_loc(outfile, &var_dst.loc, var_dst.type->sz); + integral_t dst_sz = get_effective_data_type(var_dst.type)->sz; + emit_storage_loc(outfile, &var_dst.loc, dst_sz); fprintf(outfile, "\n"); if (node->initial_value != NULL) @@ -326,7 +338,7 @@ static void emit_assignment( case EXPR_VAR_REF: struct var_ref_node* var_ref = &node->lval->inner.var_ref; lval_def = (struct lval_def) { - .type = var_ref->def_ref->resolved_type, + .type = var_ref->def_ref->type, .loc = var_ref->def_ref->loc, }; break; @@ -349,7 +361,7 @@ static void emit_call( struct expr_list_node* arg_eval = node->args; while (arg_decl != NULL && arg_eval != NULL) { struct lval_def arg_dst = - make_stack_lval(outfile, arg_decl->decl->def_ref->resolved_type); + allocate_stack(outfile, arg_decl->decl->def_ref->type); emit_expr(outfile, arg_eval->expr, &arg_dst); arg_decl = arg_decl->next; @@ -368,11 +380,13 @@ static void emit_call( unsigned char arg_regnum = 0; arg_decl = node->called_fn_ref->args; while (arg_decl != NULL) { - const struct type_def* arg_type = - arg_decl->decl->def_ref->resolved_type; - arg_bp_offset += arg_type->sz; + const struct type* arg_type = + arg_decl->decl->def_ref->type; + arg_bp_offset += get_effective_data_type(arg_type)->sz; struct lval_def arg_dst; + /* TODO: if the convention register is used, + * will need to spill the current value */ if (arg_regnum < CC_N_REGS) arg_dst = (struct lval_def) { .type = arg_type, @@ -382,7 +396,7 @@ static void emit_call( }, }; else - arg_dst = make_stack_lval(outfile, arg_type); + arg_dst = allocate_stack(outfile, arg_type); emit_mov(outfile, &arg_dst, &(struct storage_location) { .type = STO_STACK, @@ -393,7 +407,8 @@ static void emit_call( fprintf(outfile, "\tcall %s\n", node->called_fn_ref->name); if (dst != NULL) { - if (node->called_fn_ref->resolved_return_type->sz == 0) + if (get_effective_data_type( + &node->called_fn_ref->return_type) == &void_type) CGEN_PANIC("can't assign the result of a void function"); emit_mov(outfile, dst, &RV_LOC); @@ -415,14 +430,15 @@ static void emit_unary( emit_expr(outfile, node->expr, dst); if (dst == NULL) return; + integral_t dst_sz = get_effective_data_type(dst->type)->sz; switch (node->op) { case UNARY_NEG: fprintf(outfile, "\tneg "); if (dst->loc.type == STO_STACK) - emit_size_const(outfile, dst->type->sz); + emit_size_const(outfile, dst_sz); - emit_storage_loc(outfile, &dst->loc, dst->type->sz); + emit_storage_loc(outfile, &dst->loc, dst_sz); fprintf(outfile, "\n"); break; } @@ -449,21 +465,22 @@ static void emit_binary( }; emit_expr(outfile, node->lhs, &lhs_dst); + integral_t dst_sz = get_effective_data_type(dst->type)->sz; switch (node->op) { case BINARY_ADD: fprintf(outfile, "\tadd "); - emit_storage_loc(outfile, &lhs_dst.loc, dst->type->sz); + emit_storage_loc(outfile, &lhs_dst.loc, dst_sz); fprintf(outfile, ", "); break; case BINARY_SUB: fprintf(outfile, "\tsub "); - emit_storage_loc(outfile, &lhs_dst.loc, dst->type->sz); + emit_storage_loc(outfile, &lhs_dst.loc, dst_sz); fprintf(outfile, ", "); break; case BINARY_MUL: fprintf(outfile, "\timul "); if (rhs_dst.loc.type == STO_STACK) - emit_size_const(outfile, dst->type->sz); + emit_size_const(outfile, dst_sz); break; case BINARY_DIV: /* nothing in the top half reg */ @@ -475,11 +492,11 @@ static void emit_binary( fprintf(outfile, "\tidiv "); if (rhs_dst.loc.type == STO_STACK) - emit_size_const(outfile, dst->type->sz); + emit_size_const(outfile, dst_sz); break; } - emit_storage_loc(outfile, &rhs_dst.loc, dst->type->sz); + emit_storage_loc(outfile, &rhs_dst.loc, dst_sz); fprintf(outfile, "\n"); /* TODO: deal with RDX overflow shit for imul and idiv */ @@ -527,9 +544,11 @@ 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"); + bool is_void_fn = + get_effective_data_type(&active_fn->return_type) == &void_type; if (node->ret_val != NULL) { - if (active_fn->resolved_return_type->sz == 0) + if (is_void_fn) CGEN_PANIC( "returning a value from void function %s", active_fn->name); @@ -538,9 +557,9 @@ static void emit_return(FILE* outfile, const struct return_node* node) { node->ret_val, &(struct lval_def) { .loc = RV_LOC, - .type = active_fn->resolved_return_type, + .type = &active_fn->return_type, }); - } else if (active_fn->resolved_return_type > 0) { + } else if (!is_void_fn) { CGEN_PANIC( "non-void function %s should return a value", active_fn->name); } @@ -680,7 +699,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_def->resolved_type); + allocate_stack(outfile, arg_def->type); arg_def->loc = arg_dst.loc; struct storage_location arg_src; @@ -694,7 +713,8 @@ 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_def->resolved_type->sz; + integral_t arg_sz = get_effective_data_type(arg_def->type)->sz; + spilled_bp_ofs -= arg_sz; } emit_mov(outfile, &arg_dst, &arg_src); } |
