diff --git a/TODO b/TODO index d660ee2..6aab298 100644 --- a/TODO +++ b/TODO @@ -66,7 +66,7 @@ - CAST + TAILCALL + VLOAD, VSTORE, VADDR - ? ALLOCA, LOAD, STORE + + ALLOCA, LOAD, STORE + SWITCH ? ir_last_use + binop_int $imm, mem diff --git a/ir_x86.dasc b/ir_x86.dasc index 702681e..42e0054 100644 --- a/ir_x86.dasc +++ b/ir_x86.dasc @@ -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) diff --git a/tests/debug/call_alloca.irt b/tests/debug/call_alloca.irt new file mode 100644 index 0000000..cf8fa13 --- /dev/null +++ b/tests/debug/call_alloca.irt @@ -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 diff --git a/tests/debug/test_mem.irt b/tests/debug/test_mem.irt index 98a0be9..7873b2b 100644 --- a/tests/debug/test_mem.irt +++ b/tests/debug/test_mem.irt @@ -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: