Pass arguments through stack in reverse order

This commit is contained in:
Dmitry Stogov 2022-05-17 12:34:31 +03:00
parent 92ba2fb534
commit 1e7059d7e0
3 changed files with 174 additions and 32 deletions

View File

@ -3556,6 +3556,42 @@ static int ir_parallel_copy(ir_ctx *ctx, ir_copy *copies, int count, ir_reg tmp_
return 1;
}
static int32_t ir_call_used_stack(ir_ctx *ctx, ir_insn *insn)
{
int j, n;
ir_type type;
int int_param = 0;
int fp_param = 0;
int int_reg_params_count = IR_REG_INT_ARGS;
int fp_reg_params_count = IR_REG_FP_ARGS;
int32_t used_stack = 0;
n = ir_input_edges_count(ctx, insn);
for (j = 3; j <= n; j++) {
type = ctx->ir_base[insn->ops[j]].type;
if (IR_IS_TYPE_INT(type)) {
if (int_param >= int_reg_params_count) {
used_stack += sizeof(void*);
}
int_param++;
} else if (IR_IS_TYPE_FP(type)) {
if (fp_param >= fp_reg_params_count) {
used_stack += sizeof(void*);
}
fp_param++;
} else {
IR_ASSERT(0);
}
}
if (used_stack % 16 != 0) {
/* Stack must be 16 byte aligned */
used_stack += 8;
}
return used_stack;
}
static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg tmp_reg)
{
ir_backend_data *data = ctx->data;
@ -3572,11 +3608,21 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg
int fp_reg_params_count = IR_REG_FP_ARGS;
const int8_t *int_reg_params = _ir_int_reg_params;
const int8_t *fp_reg_params = _ir_fp_reg_params;
int32_t used_stack = 0;
int32_t used_stack, stack_offset = 0;
ir_copy *copies;
bool has_mem_const_args = 0;
ir_reg tmp_fp_reg = IR_REG_FP_LAST; /* Temporary register for FP loads and swap */
if (0) {
// TODO: support for preallocated stack
used_stack = 0;
} else {
used_stack = ir_call_used_stack(ctx, insn);
if (used_stack) {
| lea rsp, [rsp-used_stack]
}
}
n = ir_input_edges_count(ctx, insn);
copies = ir_mem_malloc((n - 2) * sizeof(ir_copy));
for (j = 3; j <= n; j++) {
@ -3620,43 +3666,42 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg
}
} else {
/* Pass argument through stack */
if (0) {
// TODO: support for preallocated stack
} else {
used_stack += sizeof(void*);
if (IR_IS_TYPE_INT(type)) {
if (IR_IS_CONST_REF(arg)) {
ir_val *val = &ctx->ir_base[arg].val;
if (IR_IS_SIGNED_32BIT(val->i64)) {
| push val->i32
if (IR_IS_TYPE_INT(type)) {
if (IR_IS_CONST_REF(arg)) {
ir_val *val = &ctx->ir_base[arg].val;
if (IR_IS_SIGNED_32BIT(val->i64)) {
if (ir_type_size[type] <= 4) {
| mov dword [rsp+stack_offset], val->i32
} else {
IR_ASSERT(tmp_reg != IR_REG_NONE);
| mov64 Ra(tmp_reg), val->i64
| push Ra(tmp_reg)
| mov qword [rsp+stack_offset], val->i32
}
} else {
IR_ASSERT(src_reg != IR_REG_NONE);
if (src_reg & IR_REG_SPILL_LOAD) {
src_reg &= ~IR_REG_SPILL_LOAD;
ir_emit_load(ctx, type, src_reg, arg);
}
| push Ra(src_reg)
IR_ASSERT(tmp_reg != IR_REG_NONE);
| mov64 Ra(tmp_reg), val->i64
| mov [rsp+stack_offset], Ra(tmp_reg)
}
} else {
if (IR_IS_CONST_REF(arg)) {
ir_emit_load(ctx, type, tmp_fp_reg, arg);
src_reg = tmp_fp_reg;
} else {
IR_ASSERT(src_reg != IR_REG_NONE);
if (src_reg & IR_REG_SPILL_LOAD) {
src_reg &= ~IR_REG_SPILL_LOAD;
ir_emit_load(ctx, type, src_reg, arg);
}
IR_ASSERT(src_reg != IR_REG_NONE);
if (src_reg & IR_REG_SPILL_LOAD) {
src_reg &= ~IR_REG_SPILL_LOAD;
ir_emit_load(ctx, type, src_reg, arg);
}
| sub rsp, sizeof(void*)
| ASM_FP_MEM_REG_OP movss, movsd, vmovss, vmovsd, type, [rsp], src_reg
| ASM_MEM_REG_OP, mov, type, [rsp+stack_offset], src_reg
}
} else {
if (IR_IS_CONST_REF(arg)) {
ir_emit_load(ctx, type, tmp_fp_reg, arg);
src_reg = tmp_fp_reg;
} else {
IR_ASSERT(src_reg != IR_REG_NONE);
if (src_reg & IR_REG_SPILL_LOAD) {
src_reg &= ~IR_REG_SPILL_LOAD;
ir_emit_load(ctx, type, src_reg, arg);
}
}
| ASM_FP_MEM_REG_OP movss, movsd, vmovss, vmovsd, type, [rsp+stack_offset], src_reg
}
stack_offset += sizeof(void*);
}
}
if (count) {
@ -3691,6 +3736,9 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg
}
if (dst_reg != IR_REG_NONE && (IR_IS_CONST_REF(arg) || src_reg == IR_REG_NONE)) {
if (IR_IS_TYPE_INT(type)) {
if (IR_IS_CONST_REF(arg) && ir_type_size[type] == 1) {
type = IR_ADDR;
}
ir_emit_load(ctx, type, dst_reg, arg);
} else {
ir_emit_load(ctx, type, dst_reg, arg);
@ -3735,8 +3783,7 @@ static void ir_emit_call(ir_ctx *ctx, ir_ref def, ir_insn *insn)
}
if (used_stack) {
// TODO: support for preallocated stack
| add rsp, used_stack
| lea rsp, [rsp+used_stack]
}
if (insn->type != IR_VOID) {

47
tests/debug/args_001.irt Normal file
View File

@ -0,0 +1,47 @@
--TEST--
001: Argument Passing
--ARGS--
-S --run
--CODE--
{
int8_t c_1 = 1;
int16_t c_2 = 2;
int32_t c_3 = 3;
int64_t c_4 = 4;
int64_t c_5 = 0x100000000;
uint8_t c_6 = 6;
uint16_t c_7 = 7;
uint32_t c_8 = 8;
int64_t c_9 = 9;
int64_t c_10 = 0x100000000;
uintptr_t f = func(printf);
uintptr_t fmt = "%d %d %d %lld 0x%llx %d %d %d %lld 0x%llx\n";
l_1 = START(l_3);
int32_t d_2, l_2 = CALL/11(l_1, f, fmt, c_1, c_2, c_3, c_4, c_5, c_6, c_7, c_8, c_9, c_10);
l_3 = RETURN(l_2, d_2);
}
--EXPECT--
test:
subq $8, %rsp
leaq -0x30(%rsp), %rsp
movl $6, (%rsp)
movl $7, 8(%rsp)
movl $8, 0x10(%rsp)
movq $9, 0x18(%rsp)
movabsq $0x100000000, %rax
movq %rax, 0x20(%rsp)
leaq 0x39(%rip), %rdi
movq $1, %rsi
movw $2, %dx
movl $3, %ecx
movq $4, %r8
movabsq $0x100000000, %r9
movabsq $_IO_printf, %rax
callq *%rax
leaq 0x30(%rsp), %rsp
addq $8, %rsp
retq
1 2 3 4 0x100000000 6 7 8 9 0x100000000
exit code = 40

48
tests/debug/args_002.irt Normal file
View File

@ -0,0 +1,48 @@
--TEST--
002: Argument Passing
--ARGS--
-S --run
--CODE--
{
double c_1 = 0.1;
double c_2 = 0.2;
double c_3 = 0.3;
double c_4 = 0.4;
double c_5 = 0.5;
double c_6 = 0.6;
double c_7 = 0.7;
double c_8 = 0.8;
double c_9 = 0.9;
double c_10 = 0.0;
uintptr_t f = func(printf);
uintptr_t fmt = "%g %g %g %g %g %g %g %g %g %g\n";
l_1 = START(l_3);
int32_t d_2, l_2 = CALL/11(l_1, f, fmt, c_1, c_2, c_3, c_4, c_5, c_6, c_7, c_8, c_9, c_10);
l_3 = RETURN(l_2, d_2);
}
--EXPECT--
test:
subq $8, %rsp
leaq -0x10(%rsp), %rsp
movsd 0xb6(%rip), %xmm15
movsd %xmm15, (%rsp)
xorpd %xmm15, %xmm15
movsd %xmm15, 8(%rsp)
leaq 0xa5(%rip), %rdi
movsd 0x55(%rip), %xmm0
movsd 0x55(%rip), %xmm1
movsd 0x55(%rip), %xmm2
movsd 0x55(%rip), %xmm3
movsd 0x55(%rip), %xmm4
movsd 0x55(%rip), %xmm5
movsd 0x55(%rip), %xmm6
movsd 0x55(%rip), %xmm7
movabsq $_IO_printf, %rax
callq *%rax
leaq 0x10(%rsp), %rsp
addq $8, %rsp
retq
0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 0
exit code = 38