diff --git a/src/cc/arch/aarch64/emit_code.c b/src/cc/arch/aarch64/emit_code.c index 290499c79..2ef4b83be 100644 --- a/src/cc/arch/aarch64/emit_code.c +++ b/src/cc/arch/aarch64/emit_code.c @@ -391,11 +391,11 @@ static bool is_asm(Stmt *stmt) { } static void put_args_to_stack(Function *func) { - static const char *kReg32s[] = {W0, W1, W2, W3, W4, W5, W6, W7}; - static const char *kReg64s[] = {X0, X1, X2, X3, X4, X5, X6, X7}; - static const char **kRegTable[] = {kReg32s, kReg32s, kReg32s, kReg64s}; - const char *kFReg32s[] = {S0, S1, S2, S3, S4, S5, S6, S7}; - const char *kFReg64s[] = {D0, D1, D2, D3, D4, D5, D6, D7}; + static const char *kRegParam32s[] = {W0, W1, W2, W3, W4, W5, W6, W7}; + static const char *kRegParam64s[] = {X0, X1, X2, X3, X4, X5, X6, X7}; + static const char **kRegParamTable[] = {kRegParam32s, kRegParam32s, kRegParam32s, kRegParam64s}; + const char *kFRegParam32s[] = {S0, S1, S2, S3, S4, S5, S6, S7}; + const char *kFRegParam64s[] = {D0, D1, D2, D3, D4, D5, D6, D7}; static const int kPow2Table[] = {-1, 0, 1, -1, 2, -1, -1, -1, 3}; #define kPow2TableSize ((int)(sizeof(kPow2Table) / sizeof(*kPow2Table))) @@ -403,7 +403,7 @@ static void put_args_to_stack(Function *func) { if (is_stack_param(func->type->func.ret)) { // Received as a pointer at the first parameter. const int pow = 3; - const char *src = kRegTable[pow][0]; + const char *src = kRegParamTable[pow][0]; int offset = ((FuncBackend*)func->extra)->retval->frame.offset; const char *dst = IMMEDIATE_OFFSET(FP, offset); STR(src, dst); @@ -432,54 +432,44 @@ static void put_args_to_stack(Function *func) { if (is_flonum(type)) { if (farg_index < MAX_FREG_ARGS) { - switch (type->flonum.kind) { - case FL_FLOAT: STR(kFReg32s[farg_index], IMMEDIATE_OFFSET(FP, offset)); break; - case FL_DOUBLE: STR(kFReg64s[farg_index], IMMEDIATE_OFFSET(FP, offset)); break; - default: assert(false); break; - } + const char *src = type->flonum.kind == FL_DOUBLE ? kFRegParam64s[farg_index] : kFRegParam32s[farg_index]; + assert(offset != 0); + STR(src, IMMEDIATE_OFFSET(FP, offset)); ++farg_index; } - continue; - } - - switch (type->kind) { - case TY_FIXNUM: - case TY_PTR: - break; - default: assert(false); break; - } - - if (arg_index < MAX_REG_ARGS) { - int size = type_size(type); - assert(0 <= size && size < kPow2TableSize && kPow2Table[size] >= 0); - int pow = kPow2Table[size]; - const char *src = kRegTable[pow][arg_index]; - assert(offset < 0); - const char *dst; - if (offset >= -256) { - dst = IMMEDIATE_OFFSET(FP, offset); - } else { - mov_immediate(X9, offset, true, false); // x9 broken. - dst = REG_OFFSET(FP, X9, NULL); - } - switch (pow) { - case 0: STRB(src, dst); break; - case 1: STRH(src, dst); break; - case 2: case 3: STR(src, dst); break; - default: assert(false); break; + } else { + if (arg_index < MAX_REG_ARGS) { + int size = type_size(type); + assert(0 <= size && size < kPow2TableSize && kPow2Table[size] >= 0); + int pow = kPow2Table[size]; + const char *src = kRegParamTable[pow][arg_index]; + assert(offset < 0); + const char *dst; + if (offset >= -256) { + dst = IMMEDIATE_OFFSET(FP, offset); + } else { + mov_immediate(X9, offset, true, false); // x9 broken. + dst = REG_OFFSET(FP, X9, NULL); + } + switch (pow) { + case 0: STRB(src, dst); break; + case 1: STRH(src, dst); break; + case 2: case 3: STR(src, dst); break; + default: assert(false); break; + } + ++arg_index; } - ++arg_index; } } if (vaargs) { for (int i = arg_index; i < MAX_REG_ARGS; ++i) { int offset = (i - MAX_REG_ARGS - MAX_FREG_ARGS) * WORD_SIZE; - STR(kReg64s[i], IMMEDIATE_OFFSET(FP, offset)); + STR(kRegParam64s[i], IMMEDIATE_OFFSET(FP, offset)); } for (int i = farg_index; i < MAX_FREG_ARGS; ++i) { int offset = (i - MAX_FREG_ARGS) * WORD_SIZE; - STR(kFReg64s[i], IMMEDIATE_OFFSET(FP, offset)); + STR(kFRegParam64s[i], IMMEDIATE_OFFSET(FP, offset)); } } } @@ -539,10 +529,11 @@ static void emit_defun(Function *func) { mov_immediate(value = X9, frame_size, true, false); // x9 broken SUB(SP, SP, value); } - put_args_to_stack(func); // Callee save. callee_saved_count = push_callee_save_regs(fnbe->ra->used_reg_bits, fnbe->ra->used_freg_bits); + + put_args_to_stack(func); } emit_bb_irs(fnbe->bbcon); diff --git a/src/cc/arch/x64/emit_code.c b/src/cc/arch/x64/emit_code.c index 715ce76fb..43b4c3e79 100644 --- a/src/cc/arch/x64/emit_code.c +++ b/src/cc/arch/x64/emit_code.c @@ -393,12 +393,12 @@ static bool is_asm(Stmt *stmt) { } static void put_args_to_stack(Function *func) { - static const char *kReg8s[] = {DIL, SIL, DL, CL, R8B, R9B}; - static const char *kReg16s[] = {DI, SI, DX, CX, R8W, R9W}; - static const char *kReg32s[] = {EDI, ESI, EDX, ECX, R8D, R9D}; - static const char *kReg64s[] = {RDI, RSI, RDX, RCX, R8, R9}; - static const char **kRegTable[] = {kReg8s, kReg16s, kReg32s, kReg64s}; - static const char *kFReg64s[] = {XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7}; + static const char *kRegParam8s[] = {DIL, SIL, DL, CL, R8B, R9B}; + static const char *kRegParam16s[] = {DI, SI, DX, CX, R8W, R9W}; + static const char *kRegParam32s[] = {EDI, ESI, EDX, ECX, R8D, R9D}; + static const char *kRegParam64s[] = {RDI, RSI, RDX, RCX, R8, R9}; + static const char **kRegParamTable[] = {kRegParam8s, kRegParam16s, kRegParam32s, kRegParam64s}; + static const char *kFRegParam64s[] = {XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7}; static const int kPow2Table[] = {-1, 0, 1, -1, 2, -1, -1, -1, 3}; #define kPow2TableSize ((int)(sizeof(kPow2Table) / sizeof(*kPow2Table))) @@ -406,7 +406,7 @@ static void put_args_to_stack(Function *func) { if (is_stack_param(func->type->func.ret)) { // Received as a pointer at the first parameter. const int pow = 3; - const char *src = kRegTable[pow][0]; + const char *src = kRegParamTable[pow][0]; int offset = ((FuncBackend*)func->extra)->retval->frame.offset; const char *dst = OFFSET_INDIRECT(offset, RBP, NULL, 1); MOV(src, dst); @@ -430,41 +430,35 @@ static void put_args_to_stack(Function *func) { if (is_flonum(type)) { if (farg_index < MAX_FREG_ARGS) { + const char *src = kFRegParam64s[farg_index]; + assert(offset != 0); switch (type->flonum.kind) { - case FL_FLOAT: MOVSS(kFReg64s[farg_index], OFFSET_INDIRECT(offset, RBP, NULL, 1)); break; - case FL_DOUBLE: MOVSD(kFReg64s[farg_index], OFFSET_INDIRECT(offset, RBP, NULL, 1)); break; + case FL_FLOAT: MOVSS(src, OFFSET_INDIRECT(offset, RBP, NULL, 1)); break; + case FL_DOUBLE: MOVSD(src, OFFSET_INDIRECT(offset, RBP, NULL, 1)); break; default: assert(false); break; } ++farg_index; } - continue; - } - - switch (type->kind) { - case TY_FIXNUM: - case TY_PTR: - break; - default: assert(false); break; - } - - if (arg_index < MAX_REG_ARGS) { - int size = type_size(type); - assert(0 <= size && size < kPow2TableSize && kPow2Table[size] >= 0); - int pow = kPow2Table[size]; - const char *src = kRegTable[pow][arg_index]; - MOV(src, OFFSET_INDIRECT(offset, RBP, NULL, 1)); - ++arg_index; + } else { + if (arg_index < MAX_REG_ARGS) { + int size = type_size(type); + assert(0 <= size && size < kPow2TableSize && kPow2Table[size] >= 0); + int pow = kPow2Table[size]; + const char *src = kRegParamTable[pow][arg_index]; + MOV(src, OFFSET_INDIRECT(offset, RBP, NULL, 1)); + ++arg_index; + } } } if (func->type->func.vaargs) { for (int i = arg_index; i < MAX_REG_ARGS; ++i) { int offset = (i - MAX_REG_ARGS - MAX_FREG_ARGS) * WORD_SIZE; - MOV(kReg64s[i], OFFSET_INDIRECT(offset, RBP, NULL, 1)); + MOV(kRegParam64s[i], OFFSET_INDIRECT(offset, RBP, NULL, 1)); } for (int i = farg_index; i < MAX_FREG_ARGS; ++i) { int offset = (i - MAX_FREG_ARGS) * WORD_SIZE; - MOVSD(kFReg64s[i], OFFSET_INDIRECT(offset, RBP, NULL, 1)); + MOVSD(kFRegParam64s[i], OFFSET_INDIRECT(offset, RBP, NULL, 1)); } } } @@ -525,10 +519,10 @@ static void emit_defun(Function *func) { stackpos += frame_size; } - put_args_to_stack(func); - // Callee save. push_callee_save_regs(fnbe->ra->used_reg_bits, fnbe->ra->used_freg_bits); + + put_args_to_stack(func); } emit_bb_irs(fnbe->bbcon); diff --git a/src/cc/backend/codegen.c b/src/cc/backend/codegen.c index cf3125bbd..52ec28c4b 100644 --- a/src/cc/backend/codegen.c +++ b/src/cc/backend/codegen.c @@ -63,7 +63,7 @@ static VarInfo *prepare_retvar(Function *func) { Scope *top_scope = func->scopes->data[0]; VarInfo *varinfo = scope_add(top_scope, retval_name, retptrtype, 0); VReg *vreg = add_new_reg(varinfo->type, VRF_PARAM); - vreg->param_index = 0; + vreg->reg_param_index = 0; varinfo->local.vreg = vreg; FuncBackend *fnbe = func->extra; fnbe->retval = vreg; @@ -105,20 +105,27 @@ static void alloc_variable_registers(Function *func) { } // Handle if return value is on the stack. - int param_index_offset = 0; + int iregindex = 0; if (is_stack_param(func->type->func.ret)) { prepare_retvar(func); - ++param_index_offset; + ++iregindex; } // Add flag to parameters. + int fregindex = 0; if (func->type->func.params != NULL) { for (int i = 0; i < func->type->func.params->len; ++i) { VarInfo *varinfo = func->type->func.params->data[i]; VReg *vreg = varinfo->local.vreg; if (vreg != NULL) { vreg->flag |= VRF_PARAM; - vreg->param_index = i + param_index_offset; + if (vreg->vtype->flag & VRTF_FLONUM) { + if (fregindex < MAX_FREG_ARGS) + vreg->reg_param_index = fregindex++; + } else { + if (iregindex < MAX_REG_ARGS) + vreg->reg_param_index = iregindex++; + } } } } @@ -591,13 +598,14 @@ static void prepare_register_allocation(Function *func) { int offset = DEFAULT_OFFSET; for (int i = 0; i < func->type->func.params->len; ++i) { VarInfo *varinfo = func->type->func.params->data[i]; - if (!is_prim_type(varinfo->type)) { + 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), WORD_SIZE); continue; } + assert(is_prim_type(varinfo->type)); VReg *vreg = varinfo->local.vreg; assert(vreg != NULL); diff --git a/src/cc/backend/ir.h b/src/cc/backend/ir.h index f632dc0cb..f3d52f8c6 100644 --- a/src/cc/backend/ir.h +++ b/src/cc/backend/ir.h @@ -40,7 +40,7 @@ typedef struct VReg { int virt; // Virtual reg no. int phys; // Physical reg no. int flag; - int param_index; // Function parameter index: -1=not a param + int reg_param_index; // Index of function parameter through register: -1=not a register param. int64_t fixnum; // Constant value. FrameInfo frame; // FrameInfo for spilled register. } VReg; diff --git a/src/cc/backend/regalloc.c b/src/cc/backend/regalloc.c index 45398e6f1..432c969e5 100644 --- a/src/cc/backend/regalloc.c +++ b/src/cc/backend/regalloc.c @@ -39,7 +39,7 @@ VReg *reg_alloc_spawn(RegAlloc *ra, const VRegType *vtype, int flag) { vreg->fixnum = 0; vreg->vtype = vtype; vreg->flag = flag; - vreg->param_index = -1; + vreg->reg_param_index = -1; vreg->frame.offset = 0; vec_push(ra->vregs, vreg); @@ -256,14 +256,14 @@ static void linear_scan_register_allocation(RegAlloc *ra, LiveInterval **sorted_ } else { int regno = -1; for (int j = start_index; j < prsp->phys_max; ++j) { - if (!(prsp->using_bits & (1 << j))) { + if (!(prsp->using_bits & (1UL << j))) { regno = j; break; } } assert(regno >= 0); li->phys = regno; - prsp->using_bits |= 1 << regno; + prsp->using_bits |= 1UL << regno; insert_active(prsp->active, prsp->active_count, li); ++prsp->active_count; @@ -394,7 +394,7 @@ void alloc_physical_registers(RegAlloc *ra, BBContainer *bbcon) { } // Force function parameter spilled. - if (vreg->param_index >= 0) { + if (vreg->flag & VRF_PARAM) { spill_vreg(vreg); li->start = 0; li->state = LI_SPILL;