mirror of
https://github.com/danog/ir.git
synced 2024-11-26 20:34:53 +01:00
Pass arguments through stack in reverse order
This commit is contained in:
parent
92ba2fb534
commit
1e7059d7e0
111
ir_x86.dasc
111
ir_x86.dasc
@ -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
47
tests/debug/args_001.irt
Normal 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
48
tests/debug/args_002.irt
Normal 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
|
Loading…
Reference in New Issue
Block a user