diff --git a/ir_aarch64.dasc b/ir_aarch64.dasc index 4f0ac2e..f7e5299 100644 --- a/ir_aarch64.dasc +++ b/ir_aarch64.dasc @@ -518,6 +518,9 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co insn = &ctx->ir_base[insn->op3]; constraints->tmp_regs[0] = IR_TMP_REG(3, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); n = 1; + } else if (ir_rule(ctx, insn->op3) == IR_STATIC_ALLOCA) { + constraints->tmp_regs[0] = IR_TMP_REG(3, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n = 1; } break; case IR_LOAD_FP: @@ -919,6 +922,7 @@ binop_fp: return insn->op; } case IR_CALL: + ctx->flags |= IR_USE_FRAME_POINTER; ctx->flags2 |= IR_HAS_CALLS | IR_16B_FRAME_ALIGNMENT; return IR_CALL; case IR_VAR: @@ -935,7 +939,7 @@ binop_fp: } } ctx->flags |= IR_USE_FRAME_POINTER; - ctx->flags2 |= IR_HAS_ALLOCA; + ctx->flags2 |= IR_HAS_ALLOCA | IR_16B_FRAME_ALIGNMENT; } return IR_ALLOCA; case IR_LOAD: @@ -3755,7 +3759,10 @@ static void ir_emit_vstore(ir_ctx *ctx, ir_ref ref, ir_insn *insn) fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; offset = IR_SPILL_POS_TO_OFFSET(var_insn->op3); IR_ASSERT(op3_reg != IR_REG_NONE); - if (IR_REG_SPILLED(op3_reg) && ir_is_same_mem_var(ctx, insn->op3, var_insn->op3)) { + if (IR_REG_SPILLED(op3_reg) + && !IR_IS_CONST_REF(insn->op3) + && ir_rule(ctx, insn->op3) != IR_STATIC_ALLOCA + && ir_is_same_mem_var(ctx, insn->op3, var_insn->op3)) { return; // fake store } if (IR_REG_SPILLED(op3_reg)) { @@ -4041,12 +4048,8 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn) IR_ASSERT(!IR_IS_SYM_CONST(val->op)); IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 >= 0); - if (ctx->flags2 & IR_16B_FRAME_ALIGNMENT) { - /* Stack must be 16 byte aligned */ - size = IR_ALIGNED_SIZE(size, 16); - } else { - size = IR_ALIGNED_SIZE(size, 8); - } + /* Stack must be 16 byte aligned */ + size = IR_ALIGNED_SIZE(size, 16); if (aarch64_may_encode_imm12(size)) { | sub sp, sp, #size } else { @@ -4057,7 +4060,7 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn) ctx->call_stack_size += size; } } else { - int32_t alignment = (ctx->flags2 & IR_16B_FRAME_ALIGNMENT) ? 16 : 8; + int32_t alignment = 16; ir_reg op2_reg = ctx->regs[def][2]; ir_type type = ctx->ir_base[insn->op2].type; @@ -4095,18 +4098,14 @@ static void ir_emit_afree(ir_ctx *ctx, ir_ref def, ir_insn *insn) IR_ASSERT(!IR_IS_SYM_CONST(val->op)); IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0); - if (ctx->flags2 & IR_16B_FRAME_ALIGNMENT) { - /* Stack must be 16 byte aligned */ - size = IR_ALIGNED_SIZE(size, 16); - } else { - size = IR_ALIGNED_SIZE(size, 8); - } + /* Stack must be 16 byte aligned */ + size = IR_ALIGNED_SIZE(size, 16); | add sp, sp, #size if (!(ctx->flags & IR_USE_FRAME_POINTER)) { ctx->call_stack_size -= size; } } else { -// int32_t alignment = (ctx->flags2 & IR_16B_FRAME_ALIGNMENT) ? 16 : 8; +// int32_t alignment = 16; ir_reg op2_reg = ctx->regs[def][2]; ir_type type = ctx->ir_base[insn->op2].type; @@ -5766,7 +5765,6 @@ void ir_fix_stack_frame(ir_ctx *ctx) ctx->stack_frame_alignment += sizeof(void*); } } else if (ctx->flags2 & IR_16B_FRAME_ALIGNMENT) { - ctx->flags |= IR_USE_FRAME_POINTER; /* Stack must be 16 byte aligned */ if (!(ctx->flags & IR_FUNCTION)) { while (IR_ALIGNED_SIZE(ctx->stack_frame_size, 16) != ctx->stack_frame_size) { diff --git a/ir_ra.c b/ir_ra.c index a7c0403..12ba723 100644 --- a/ir_ra.c +++ b/ir_ra.c @@ -2609,14 +2609,11 @@ static int32_t ir_allocate_big_spill_slot(ir_ctx *ctx, int32_t size, ir_reg_allo return ir_allocate_small_spill_slot(ctx, size, data); } - if (ctx->flags2 & IR_16B_FRAME_ALIGNMENT) { - /* Stack must be 16 byte aligned */ - size = IR_ALIGNED_SIZE(size, 16); - } else { - size = IR_ALIGNED_SIZE(size, 8); - } - ret = ctx->stack_frame_size; - ctx->stack_frame_size += size; + /* Align stack allocated data to 16 byte */ + ctx->flags2 |= IR_16B_FRAME_ALIGNMENT; + ret = IR_ALIGNED_SIZE(ctx->stack_frame_size, 16); + size = IR_ALIGNED_SIZE(size, 8); + ctx->stack_frame_size = ret + size; return ret; } diff --git a/ir_x86.dasc b/ir_x86.dasc index a975392..e5822d8 100644 --- a/ir_x86.dasc +++ b/ir_x86.dasc @@ -1285,6 +1285,9 @@ op2_const: insn = &ctx->ir_base[ref]; if (IR_IS_CONST_REF(insn->op3)) { n = ir_add_const_tmp_reg(ctx, insn->op3, 3, n, constraints); + } else if (ir_rule(ctx, insn->op3) == IR_STATIC_ALLOCA) { + constraints->tmp_regs[n] = IR_TMP_REG(3, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n++; } break; case IR_STORE_INT: @@ -2281,7 +2284,7 @@ binop_fp: } } ctx->flags |= IR_USE_FRAME_POINTER; - ctx->flags2 |= IR_HAS_ALLOCA; + ctx->flags2 |= IR_HAS_ALLOCA | IR_16B_FRAME_ALIGNMENT; } return IR_ALLOCA; case IR_VSTORE: @@ -7431,7 +7434,9 @@ static void ir_emit_vstore_int(ir_ctx *ctx, ir_ref ref, ir_insn *insn) fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; mem = IR_MEM_BO(fp, IR_SPILL_POS_TO_OFFSET(var_insn->op3)); if ((op3_reg == IR_REG_NONE || IR_REG_SPILLED(op3_reg)) - && !IR_IS_CONST_REF(insn->op3) && ir_is_same_mem_var(ctx, insn->op3, var_insn->op3)) { + && !IR_IS_CONST_REF(insn->op3) + && ir_rule(ctx, insn->op3) != IR_STATIC_ALLOCA + && ir_is_same_mem_var(ctx, insn->op3, var_insn->op3)) { return; // fake store } if (IR_IS_CONST_REF(insn->op3)) { @@ -7458,7 +7463,9 @@ static void ir_emit_vstore_fp(ir_ctx *ctx, ir_ref ref, ir_insn *insn) fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; mem = IR_MEM_BO(fp, IR_SPILL_POS_TO_OFFSET(var_insn->op3)); if ((op3_reg == IR_REG_NONE || IR_REG_SPILLED(op3_reg)) - && !IR_IS_CONST_REF(insn->op3) && ir_is_same_mem_var(ctx, insn->op3, var_insn->op3)) { + && !IR_IS_CONST_REF(insn->op3) + && ir_rule(ctx, insn->op3) != IR_STATIC_ALLOCA + && ir_is_same_mem_var(ctx, insn->op3, var_insn->op3)) { return; // fake store } if (IR_IS_CONST_REF(insn->op3)) { @@ -7763,18 +7770,14 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn) IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 >= 0); IR_ASSERT(IR_IS_SIGNED_32BIT(val->val.i64)); - if (ctx->flags2 & IR_16B_FRAME_ALIGNMENT) { - /* Stack must be 16 byte aligned */ - size = IR_ALIGNED_SIZE(size, 16); - } else { - size = IR_ALIGNED_SIZE(size, 8); - } + /* Stack must be 16 byte aligned */ + size = IR_ALIGNED_SIZE(size, 16); | ASM_REG_IMM_OP sub, IR_ADDR, IR_REG_RSP, size if (!(ctx->flags & IR_USE_FRAME_POINTER)) { ctx->call_stack_size += size; } } else { - int32_t alignment = (ctx->flags2 & IR_16B_FRAME_ALIGNMENT) ? 16 : 8; + int32_t alignment = 16; ir_reg op2_reg = ctx->regs[def][2]; ir_type type = ctx->ir_base[insn->op2].type; @@ -7821,18 +7824,14 @@ static void ir_emit_afree(ir_ctx *ctx, ir_ref def, ir_insn *insn) IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0); IR_ASSERT(IR_IS_SIGNED_32BIT(val->val.i64)); - if (ctx->flags2 & IR_16B_FRAME_ALIGNMENT) { - /* Stack must be 16 byte aligned */ - size = IR_ALIGNED_SIZE(size, 16); - } else { - size = IR_ALIGNED_SIZE(size, 8); - } + /* Stack must be 16 byte aligned */ + size = IR_ALIGNED_SIZE(size, 16); | ASM_REG_IMM_OP add, IR_ADDR, IR_REG_RSP, size if (!(ctx->flags & IR_USE_FRAME_POINTER)) { ctx->call_stack_size -= size; } } else { -// int32_t alignment = (ctx->flags2 & IR_16B_FRAME_ALIGNMENT) ? 16 : 8; +// int32_t alignment = 16; ir_reg op2_reg = ctx->regs[def][2]; ir_type type = ctx->ir_base[insn->op2].type; diff --git a/tests/aarch64/alloca_002.irt b/tests/aarch64/alloca_002.irt index 1f93666..a1d7382 100644 --- a/tests/aarch64/alloca_002.irt +++ b/tests/aarch64/alloca_002.irt @@ -15,8 +15,8 @@ aarch64 test: stp x29, x30, [sp, #-0x10]! mov x29, sp - add x0, x0, #7 - and x0, x0, #0xfffffffffffffff8 + add x0, x0, #0xf + and x0, x0, #0xfffffffffffffff0 sub sp, sp, x0 mov x0, sp mov sp, x29 diff --git a/tests/x86/alloca_001.irt b/tests/x86/alloca_001.irt index 4bf81b6..67b6d1d 100644 --- a/tests/x86/alloca_001.irt +++ b/tests/x86/alloca_001.irt @@ -13,7 +13,7 @@ x86 } --EXPECT-- test: - subl $0x10, %esp + subl $0x1c, %esp movl %esp, %eax - addl $0x10, %esp + addl $0x1c, %esp retl diff --git a/tests/x86/alloca_002.irt b/tests/x86/alloca_002.irt index 65b005e..fd0718e 100644 --- a/tests/x86/alloca_002.irt +++ b/tests/x86/alloca_002.irt @@ -15,9 +15,10 @@ x86 test: pushl %ebp movl %esp, %ebp + subl $8, %esp movl 8(%ebp), %eax - addl $7, %eax - andl $0xfffffff8, %eax + addl $0xf, %eax + andl $0xfffffff0, %eax subl %eax, %esp movl %esp, %eax movl %ebp, %esp diff --git a/tests/x86_64/alloca_001.irt b/tests/x86_64/alloca_001.irt index ed5fd8e..e2231a9 100644 --- a/tests/x86_64/alloca_001.irt +++ b/tests/x86_64/alloca_001.irt @@ -13,7 +13,7 @@ x86_64 } --EXPECT-- test: - subq $0x10, %rsp + subq $0x18, %rsp movq %rsp, %rax - addq $0x10, %rsp + addq $0x18, %rsp retq diff --git a/tests/x86_64/alloca_002.irt b/tests/x86_64/alloca_002.irt index c2243d6..5361598 100644 --- a/tests/x86_64/alloca_002.irt +++ b/tests/x86_64/alloca_002.irt @@ -16,8 +16,8 @@ test: pushq %rbp movq %rsp, %rbp movl %edi, %eax - addq $7, %rax - andq $0xfffffffffffffff8, %rax + addq $0xf, %rax + andq $0xfffffffffffffff0, %rax subq %rax, %rsp movq %rsp, %rax movq %rbp, %rsp