From f96fa84e6a16f271515029cf9b05afb2e6099c03 Mon Sep 17 00:00:00 2001 From: tyfkda Date: Sat, 5 Oct 2024 09:36:27 +0900 Subject: [PATCH] Remove stack position counting On x64, stack pointer is aligned to 16 if the function contains function call in it. --- src/cc/arch/aarch64/ir_aarch64.c | 11 ++++++----- src/cc/arch/riscv64/ir_riscv64.c | 11 ++++++----- src/cc/arch/x64/emit_code.c | 18 +++++------------- src/cc/arch/x64/emit_code.h | 5 ----- src/cc/arch/x64/ir_x64.c | 24 +++++++----------------- src/cc/backend/codegen_expr.c | 4 ---- src/cc/backend/ir.c | 2 +- 7 files changed, 25 insertions(+), 50 deletions(-) diff --git a/src/cc/arch/aarch64/ir_aarch64.c b/src/cc/arch/aarch64/ir_aarch64.c index 50706df84..a2a981cde 100644 --- a/src/cc/arch/aarch64/ir_aarch64.c +++ b/src/cc/arch/aarch64/ir_aarch64.c @@ -670,8 +670,9 @@ static void ei_precall(IR *ir) { int align_stack = (16 - (ir->precall.stack_args_size)) & 15; ir->precall.stack_aligned = align_stack; - if (align_stack > 0) { - SUB(SP, SP, IM(align_stack)); + int total = align_stack + ir->precall.stack_args_size; + if (total > 0) { + SUB(SP, SP, IM(total)); } } @@ -706,9 +707,9 @@ static void ei_call(IR *ir) { } IR *precall = ir->call.precall; - int align_stack = precall->precall.stack_aligned + precall->precall.stack_args_size; - if (align_stack != 0) { - ADD(SP, SP, IM(align_stack)); + int total = precall->precall.stack_aligned + precall->precall.stack_args_size; + if (total != 0) { + ADD(SP, SP, IM(total)); } // Resore caller save registers. diff --git a/src/cc/arch/riscv64/ir_riscv64.c b/src/cc/arch/riscv64/ir_riscv64.c index 75561a396..900c7445b 100644 --- a/src/cc/arch/riscv64/ir_riscv64.c +++ b/src/cc/arch/riscv64/ir_riscv64.c @@ -646,8 +646,9 @@ static void ei_precall(IR *ir) { int align_stack = (16 - (ir->precall.stack_args_size)) & 15; ir->precall.stack_aligned = align_stack; - if (align_stack > 0) { - ADDI(SP, SP, IM(-align_stack)); + int total = align_stack + ir->precall.stack_args_size; + if (total > 0) { + ADDI(SP, SP, IM(-total)); } } @@ -691,9 +692,9 @@ static void ei_call(IR *ir) { } IR *precall = ir->call.precall; - int align_stack = precall->precall.stack_aligned + precall->precall.stack_args_size; - if (align_stack != 0) { - ADDI(SP, SP, IM(align_stack)); + int total = precall->precall.stack_aligned + precall->precall.stack_args_size; + if (total != 0) { + ADDI(SP, SP, IM(total)); } // Resore caller save registers. diff --git a/src/cc/arch/x64/emit_code.c b/src/cc/arch/x64/emit_code.c index dc6f7f226..f30e3a436 100644 --- a/src/cc/arch/x64/emit_code.c +++ b/src/cc/arch/x64/emit_code.c @@ -153,8 +153,6 @@ void emit_defun(Function *func) { func->extra == NULL) // Code emission is omitted. return; - assert(stackpos == 8); - emit_comment(NULL); _TEXT(); @@ -197,16 +195,17 @@ void emit_defun(Function *func) { FuncBackend *fnbe = func->extra; size_t frame_size = 0; bool rbp_saved = false; + int callee_saved_count = 0; if (!no_stmt) { // Callee save. - int callee_saved_count = push_callee_save_regs(fnbe->ra->used_reg_bits, fnbe->ra->used_freg_bits); + callee_saved_count = push_callee_save_regs(fnbe->ra->used_reg_bits, fnbe->ra->used_freg_bits); // When function is called, return address is pused onto the stack by caller, // so default offset is 8. size_t frame_offset = 8; if (fnbe->frame_size > 0 || fnbe->ra->flag & RAF_STACK_FRAME) { - PUSH(RBP); PUSH_STACK_POS(); + PUSH(RBP); MOV(RSP, RBP); rbp_saved = true; // RBP is pushed so the 16-bytes-align offset becomes 0. @@ -215,13 +214,12 @@ void emit_defun(Function *func) { size_t callee_saved_size = callee_saved_count * TARGET_POINTER_SIZE; frame_size = fnbe->frame_size; - if (func->flag & FUNCF_HAS_FUNCALL) { + if (func->flag & (FUNCF_HAS_FUNCALL | FUNCF_STACK_MODIFIED)) { // Align frame size to 16 only it contains funcall. frame_size += -(fnbe->frame_size + callee_saved_size + frame_offset) & 15; } if (frame_size > 0) { SUB(IM(frame_size), RSP); - stackpos += frame_size; } move_params_to_assigned(func); @@ -234,21 +232,15 @@ void emit_defun(Function *func) { if (!no_stmt) { if (rbp_saved) { MOV(RBP, RSP); - stackpos -= frame_size; - POP(RBP); POP_STACK_POS(); + POP(RBP); } else if (frame_size > 0) { ADD(IM(frame_size), RSP); - stackpos -= frame_size; } pop_callee_save_regs(fnbe->ra->used_reg_bits, fnbe->ra->used_freg_bits); } RET(); - - assert(stackpos == 8); - } else { - stackpos = 8; } // Static variables are emitted through global variables. diff --git a/src/cc/arch/x64/emit_code.h b/src/cc/arch/x64/emit_code.h index 238b1f196..96d4a63d7 100644 --- a/src/cc/arch/x64/emit_code.h +++ b/src/cc/arch/x64/emit_code.h @@ -6,11 +6,6 @@ typedef struct Vector Vector; -extern int stackpos; - -#define PUSH_STACK_POS() do { stackpos += TARGET_POINTER_SIZE; } while (0) -#define POP_STACK_POS() do { stackpos -= TARGET_POINTER_SIZE; } while (0) - char *im(int64_t x); // $x char *indirect(const char *base, const char *index, int scale); char *offset_indirect(int offset, const char *base, const char *index, int scale); diff --git a/src/cc/arch/x64/ir_x64.c b/src/cc/arch/x64/ir_x64.c index f65ca39d1..f1b7a9549 100644 --- a/src/cc/arch/x64/ir_x64.c +++ b/src/cc/arch/x64/ir_x64.c @@ -16,8 +16,6 @@ static Vector *push_caller_save_regs(unsigned long living); static void pop_caller_save_regs(Vector *saves); -int stackpos = 8; - // Register allocator const char *kRegSizeTable[][PHYSICAL_REG_MAX] = { @@ -715,12 +713,12 @@ static void ei_precall(IR *ir) { // so safely saved before calculating argument values. ir->precall.caller_saves = push_caller_save_regs(ir->precall.living_pregs); - int align_stack = (16 - (stackpos + ir->precall.stack_args_size)) & 15; + int align_stack = (16 - (ir->precall.caller_saves->len * TARGET_POINTER_SIZE + ir->precall.stack_args_size)) & 15; ir->precall.stack_aligned = align_stack; - if (align_stack > 0) { - SUB(IM(align_stack), RSP); - stackpos += align_stack; + int total = align_stack + ir->precall.stack_args_size; + if (total > 0) { + SUB(IM(total), RSP); } } @@ -775,10 +773,9 @@ static void ei_call(IR *ir) { } IR *precall = ir->call.precall; - int align_stack = precall->precall.stack_aligned + precall->precall.stack_args_size; - if (align_stack != 0) { - ADD(IM(align_stack), RSP); - stackpos -= precall->precall.stack_aligned; + int total = precall->precall.stack_aligned + precall->precall.stack_args_size; + if (total != 0) { + ADD(IM(total), RSP); } // Resore caller save registers. @@ -834,7 +831,6 @@ static void ei_subsp(IR *ir) { SUB(IM(ir->opr1->fixnum), RSP); else if (ir->opr1->fixnum < 0) ADD(IM(-ir->opr1->fixnum), RSP); - // stackpos += ir->opr1->fixnum; } else { SUB(kReg64s[ir->opr1->phys], RSP); } @@ -1008,7 +1004,6 @@ int push_callee_save_regs(unsigned long used, unsigned long fused) { int ireg = kCalleeSaveRegs[i]; if (used & (1 << ireg)) { PUSH(kReg64s[ireg]); - PUSH_STACK_POS(); ++count; } } @@ -1023,7 +1018,6 @@ void pop_callee_save_regs(unsigned long used, unsigned long fused) { int ireg = kCalleeSaveRegs[i]; if (used & (1 << ireg)) { POP(kReg64s[ireg]); - POP_STACK_POS(); } } } @@ -1044,7 +1038,6 @@ static Vector *push_caller_save_regs(unsigned long living) { if (living & (1UL << ireg)) { const char *reg = kReg64s[ireg]; PUSH(reg); - PUSH_STACK_POS(); vec_push(saves, reg); } } @@ -1062,7 +1055,6 @@ static Vector *push_caller_save_regs(unsigned long living) { if (n > 0) { int ofs = n * TARGET_POINTER_SIZE; SUB(IM(ofs), RSP); - stackpos += ofs; for (int i = 0; i < n; ++i) { ofs -= TARGET_POINTER_SIZE; MOVSD(saves->data[i + fstart], OFFSET_INDIRECT(ofs, RSP, NULL, 1)); @@ -1085,14 +1077,12 @@ static void pop_caller_save_regs(Vector *saves) { } if (ofs > 0) { ADD(IM(ofs), RSP); - stackpos -= ofs; } ++i; while (--i >= 0) { const char *reg = saves->data[i]; POP(reg); - POP_STACK_POS(); } } diff --git a/src/cc/backend/codegen_expr.c b/src/cc/backend/codegen_expr.c index d46aad6d0..3880cd27f 100644 --- a/src/cc/backend/codegen_expr.c +++ b/src/cc/backend/codegen_expr.c @@ -410,13 +410,9 @@ static VReg *gen_funcall(Expr *expr) { } } } - offset = ALIGN(offset, 16); IR *precall = new_ir_precall(arg_count - stack_arg_count, offset); - if (offset > 0) - new_ir_subsp(new_const_vreg(offset, to_vsize(&tySSize)), NULL); - int total_arg_count = arg_count + (ret_varinfo != NULL ? 1 : 0); VReg **arg_vregs = total_arg_count == 0 ? NULL : calloc_or_die(total_arg_count * sizeof(*arg_vregs)); diff --git a/src/cc/backend/ir.c b/src/cc/backend/ir.c index 8634804d1..fd8fbdae5 100644 --- a/src/cc/backend/ir.c +++ b/src/cc/backend/ir.c @@ -270,7 +270,7 @@ IR *new_ir_precall(int arg_count, int stack_args_size) { IR *ir = new_ir(IR_PRECALL); ir->precall.arg_count = arg_count; ir->precall.stack_args_size = stack_args_size; - ir->precall.stack_aligned = false; + ir->precall.stack_aligned = 0; ir->precall.living_pregs = 0; ir->precall.caller_saves = NULL; return ir;