Fix ALLOCA to align stack frame

This commit is contained in:
Dmitry Stogov 2022-04-22 12:55:38 +03:00
parent 5cb0af8cd9
commit 4a6c8d60a6
4 changed files with 102 additions and 5 deletions

2
TODO
View File

@ -66,7 +66,7 @@
- CAST
+ TAILCALL
+ VLOAD, VSTORE, VADDR
? ALLOCA, LOAD, STORE
+ ALLOCA, LOAD, STORE
+ SWITCH
? ir_last_use
+ binop_int $imm, mem

View File

@ -3241,10 +3241,40 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn)
ir_backend_data *data = ctx->data;
dasm_State **Dst = &data->dasm_state;
// TODO: alignment
| ASM_REG_REF_OP sub, IR_ADDR, IR_REG_RSP, insn->op2
if (IR_IS_CONST_REF(insn->op2)) {
ir_insn *val = &ctx->ir_base[insn->op2];
int32_t size = val->val.i32;
IR_ASSERT(IR_IS_TYPE_INT(val->type));
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0);
IR_ASSERT(IR_IS_SIGNED_32BIT(val->val.i64));
if (ctx->flags & IR_HAS_CALLS) {
/* Stack must be 16 byte aligned */
size = IR_ALIGNED_SIZE(size, 16);
} else {
size = IR_ALIGNED_SIZE(size, 8);
}
| ASM_REG_IMM_OP sub, IR_ADDR, IR_REG_RSP, size
} else {
int32_t alignment = (ctx->flags & IR_HAS_CALLS) ? 16 : 8;
ir_reg op2_reg = ir_ref_reg(ctx, insn->op2);
ir_reg reg;
if (op2_reg >=0 && ir_last_use(ctx, insn->op2, def)) {
reg = op2_reg;
} else {
reg = IR_REG_RAX; // TODO: temporary register
}
if (reg != op2_reg) {
ir_emit_load(ctx, IR_ADDR, insn->op2, reg);
}
| ASM_REG_IMM_OP add, IR_ADDR, reg, (alignment-1)
| ASM_REG_IMM_OP and, IR_ADDR, reg, ~(alignment-1)
| ASM_REG_REG_OP sub, IR_ADDR, IR_REG_RSP, reg
}
ir_emit_store(ctx, IR_ADDR, IR_REG_RSP, def);
// TODO: stack frame alignment
}
static void ir_emit_switch(ir_ctx *ctx, ir_ref def, ir_insn *insn)

View File

@ -0,0 +1,67 @@
--TEST--
Simple CALL with ALLOCA
--ARGS--
-S --run
--CODE--
{
uintptr_t c_1 = 0;
bool c_2 = 0;
bool c_3 = 1;
int32_t c_4 = 42;
char h = 'h';
char i = 'i';
char sp = ' ';
char pc = '%';
char d = 'd';
char nl = '\n';
char zero = 0;
uint32_t len = 7;
uintptr_t one = 1;
uintptr_t c_5 = func(printf);
l_1 = START(l_4);
uintptr_t a_0, s_0 = ALLOCA(l_1, len);
s_1 = STORE(s_0, a_0, h);
uintptr_t a_1 = ADD(a_0, one);
s_2 = STORE(s_1, a_1, i);
uintptr_t a_2 = ADD(a_1, one);
s_3 = STORE(s_2, a_2, sp);
uintptr_t a_3 = ADD(a_2, one);
s_4 = STORE(s_3, a_3, pc);
uintptr_t a_4 = ADD(a_3, one);
s_5 = STORE(s_4, a_4, d);
uintptr_t a_5 = ADD(a_4, one);
s_6 = STORE(s_5, a_5, nl);
uintptr_t a_6 = ADD(a_5, one);
s_7 = STORE(s_6, a_6, zero);
int32_t d_2, l_2 = CALL/2(s_7, c_5, a_0, c_4);
l_4 = RETURN(l_2, d_2);
}
--EXPECT--
test:
pushq %rbp
movq %rsp, %rbp
subq $0x10, %rsp
movq %rsp, %rdi
movb $0x68, (%rdi)
leaq 1(%rdi), %rax
movb $0x69, (%rax)
leaq 2(%rdi), %rax
movb $0x20, (%rax)
leaq 3(%rdi), %rax
movb $0x25, (%rax)
leaq 4(%rdi), %rax
movb $0x64, (%rax)
leaq 5(%rdi), %rax
movb $0xa, (%rax)
leaq 6(%rdi), %rax
movb $0, (%rax)
movl $0x2a, %esi
movabsq $_IO_printf, %rax
callq *%rax
movq %rbp, %rsp
popq %rbp
retq
hi 42
exit code = 6

View File

@ -88,7 +88,7 @@ test:
movsd %xmm7, -0x28(%rbp)
xorpd %xmm7, %xmm7
movsd %xmm7, -0x20(%rbp)
subq $4, %rsp
subq $8, %rsp
movq %rsp, %rax
movl $0, (%rax)
.L1: