diff --git a/src/cc/backend/codegen.c b/src/cc/backend/codegen.c index 5e536eec3..431147982 100644 --- a/src/cc/backend/codegen.c +++ b/src/cc/backend/codegen.c @@ -662,18 +662,13 @@ void prepare_register_allocation(Function *func) { // Handle function parameters first. const Vector *params = func->params; if (params != NULL) { - const int DEFAULT_OFFSET = POINTER_SIZE * 2; // Return address, saved base pointer. assert((Scope*)func->scopes->data[0] != NULL); int ireg_index = is_stack_param(func->type->func.ret) ? 1 : 0; int freg_index = 0; - int offset = DEFAULT_OFFSET; for (int i = 0, param_count = params->len; i < param_count; ++i) { VarInfo *varinfo = params->data[i]; if (is_stack_param(varinfo->type)) { // stack parameters - FrameInfo *fi = varinfo->local.frameinfo; - fi->offset = offset = ALIGN(offset, align_size(varinfo->type)); - offset += ALIGN(type_size(varinfo->type), POINTER_SIZE); require_stack_frame = true; continue; } @@ -687,14 +682,8 @@ void prepare_register_allocation(Function *func) { (!flo && ireg_index >= MAX_REG_ARGS)) { // Function argument passed through the stack. spill_vreg(vreg); - vreg->frame.offset = offset; - offset += POINTER_SIZE; + vreg->flag |= VRF_STACK_PARAM; require_stack_frame = true; - } else if (func->type->func.vaargs) { // Variadic function parameters. - if (i >= param_count) { // Store vaargs to jmp_buf. - vreg->frame.offset = flo ? (freg_index - MAX_FREG_ARGS) * POINTER_SIZE - : (ireg_index - MAX_REG_ARGS - MAX_FREG_ARGS) * POINTER_SIZE; - } } ireg_index += 1 - flo; @@ -714,11 +703,7 @@ void prepare_register_allocation(Function *func) { VReg *vreg = varinfo->local.vreg; if (vreg == NULL) { assert(!is_prim_type(varinfo->type)); - // Confirm whether this variable require stack frame: - // If the variable is function parameter, it passed through the stack, - // and it is not consume current stack frame, so exclude it. - if (!require_stack_frame && !(varinfo->storage & VS_PARAM)) - require_stack_frame = true; + require_stack_frame = true; continue; } @@ -815,6 +800,7 @@ void detect_living_registers(RegAlloc *ra, BBContainer *bbcon) { void alloc_stack_variables_onto_stack_frame(Function *func) { FuncBackend *fnbe = func->extra; size_t frame_size = fnbe->frame_size; + int param_offset = POINTER_SIZE * 2; // Return address, saved base pointer. for (int i = 0; i < func->scopes->len; ++i) { Scope *scope = func->scopes->data[i]; @@ -823,16 +809,37 @@ void alloc_stack_variables_onto_stack_frame(Function *func) { for (int j = 0; j < scope->vars->len; ++j) { VarInfo *varinfo = scope->vars->data[j]; - if (!is_local_storage(varinfo) || is_prim_type(varinfo->type)) + if (!is_local_storage(varinfo)) continue; + if (varinfo->storage & VS_PARAM) { + assert(is_stack_param(varinfo->type) || varinfo->local.vreg != NULL); + if (is_stack_param(varinfo->type)) { + FrameInfo *fi = varinfo->local.frameinfo; + fi->offset = param_offset = ALIGN(param_offset, align_size(varinfo->type)); + param_offset += ALIGN(type_size(varinfo->type), POINTER_SIZE); + continue; + } else if ((varinfo->local.vreg->flag & VRF_STACK_PARAM)) { + FrameInfo *fi = varinfo->local.frameinfo; + fi->offset = param_offset = ALIGN(param_offset, POINTER_SIZE); + param_offset += POINTER_SIZE; + continue; + } + } + + if (is_prim_type(varinfo->type)) { + // Primitive type variables are handled according to RegAlloc results. + continue; + } + assert(varinfo->local.vreg == NULL); FrameInfo *fi = varinfo->local.frameinfo; assert(fi != NULL); - if (fi->offset != 0) { - // Variadic function parameter or stack parameter, set in `prepare_register_allocation`. - continue; - } +assert(fi->offset == 0); + // if (fi->offset != 0) { + // // Variadic function parameter or stack parameter, set in `prepare_register_allocation`. + // continue; + // } Type *type = varinfo->type; size_t size = type_size(type); @@ -866,12 +873,8 @@ void alloc_stack_variables_onto_stack_frame(Function *func) { if (li->state != LI_SPILL) continue; VReg *vreg = ra->vregs->data[li->virt]; - if (vreg->frame.offset != 0) { - // Variadic function parameter or stack parameter, set in `prepare_register_allocation`. - if (-vreg->frame.offset > (int)frame_size) - frame_size = -vreg->frame.offset; - continue; - } + if (vreg->flag & VRF_STACK_PARAM) + continue; // Handled in above, so skip here. int size, align; size = align = 1 << vreg->vsize; diff --git a/src/cc/backend/ir.h b/src/cc/backend/ir.h index 406844491..8e231f0ec 100644 --- a/src/cc/backend/ir.h +++ b/src/cc/backend/ir.h @@ -32,6 +32,7 @@ enum VRegSize { #define VRF_NO_SPILL (1 << 4) // No Spill #define VRF_FLONUM (1 << 6) // Floating-point register? #define VRF_UNUSED (1 << 9) // Unused +#define VRF_STACK_PARAM (1 << 10) // Function parameter, but through stack (spilled by default, so no regalloc needed) #define VRF_MASK (VRF_FLONUM)