diff --git a/ir_aarch64.dasc b/ir_aarch64.dasc index 666099e..609f376 100644 --- a/ir_aarch64.dasc +++ b/ir_aarch64.dasc @@ -3553,6 +3553,7 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg ir_copy *copies; bool do_pass3 = 0; ir_reg tmp_fp_reg = IR_REG_FP_LAST; /* Temporary register for FP loads and swap */ + int8_t *reg_ops; n = ir_input_edges_count(ctx, insn); if (n < 3) { @@ -3575,9 +3576,10 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg /* 1. move all register arguments that should be passed through stack * and collect arguments that should be passed through registers */ copies = ir_mem_malloc((n - 2) * sizeof(ir_copy)); + reg_ops = ctx->regs[def]; for (j = 3; j <= n; j++) { arg = ir_insn_op(insn, j); - src_reg = ctx->regs[def][j]; + src_reg = reg_ops[j]; arg_insn = &ctx->ir_base[arg]; type = arg_insn->type; if (IR_IS_TYPE_INT(type)) { @@ -3643,7 +3645,7 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg fp_param = 0; for (j = 3; j <= n; j++) { arg = ir_insn_op(insn, j); - src_reg = ctx->regs[def][j]; + src_reg = reg_ops[j]; arg_insn = &ctx->ir_base[arg]; type = arg_insn->type; if (IR_IS_TYPE_INT(type)) { diff --git a/ir_ra.c b/ir_ra.c index 24fd264..377a485 100644 --- a/ir_ra.c +++ b/ir_ra.c @@ -1809,8 +1809,9 @@ static ir_reg ir_try_allocate_free_reg(ir_ctx *ctx, ir_live_interval *ival, ir_l pos = freeUntilPos[i]; reg = i; } else if (freeUntilPos[i] == pos - && !IR_REGSET_IN(IR_REGSET_SCRATCH, reg) - && IR_REGSET_IN(IR_REGSET_SCRATCH, i)) { + && (reg == IR_REG_NONE + || (!IR_REGSET_IN(IR_REGSET_SCRATCH, reg) + && IR_REGSET_IN(IR_REGSET_SCRATCH, i)))) { /* prefer caller-saved registers to avoid save/restore in prologue/epilogue */ pos = freeUntilPos[i]; reg = i; @@ -2600,12 +2601,15 @@ static void assign_regs(ir_ctx *ctx) if (use_pos->flags & IR_PHI_USE) { IR_ASSERT(use_pos->hint_ref > 0); ref = use_pos->hint_ref; - IR_ASSERT(use_pos->op_num <= IR_MAX(3, ir_input_edges_count(ctx, &ctx->ir_base[ref]))); - ctx->regs[ref][use_pos->op_num] = reg; - } else { - IR_ASSERT(use_pos->op_num <= IR_MAX(3, ir_input_edges_count(ctx, &ctx->ir_base[ref]))); - ctx->regs[ref][use_pos->op_num] = reg; } + IR_ASSERT(use_pos->op_num <= IR_MAX(3, ir_input_edges_count(ctx, &ctx->ir_base[ref]))); + + /* It's allowed to write above reg_ops[4] boundary */ + /* (see the real boundaty check by the assertion above) */ + /* ctx->regs[ref][use_pos->op_num] = reg; */ + int8_t *reg_ops = ctx->regs[ref]; + reg_ops[use_pos->op_num] = reg; + use_pos = use_pos->next; } } diff --git a/ir_x86.dasc b/ir_x86.dasc index f6cb16f..2a56e75 100644 --- a/ir_x86.dasc +++ b/ir_x86.dasc @@ -5763,6 +5763,7 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg ir_copy *copies; bool do_pass3 = 0; ir_reg tmp_fp_reg = IR_REG_FP_LAST; /* Temporary register for FP loads and swap */ + int8_t *reg_ops; n = ir_input_edges_count(ctx, insn); if (n < 3) { @@ -5794,9 +5795,10 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg /* 1. move all register arguments that should be passed through stack * and collect arguments that should be passed through registers */ copies = ir_mem_malloc((n - 2) * sizeof(ir_copy)); + reg_ops = ctx->regs[def]; for (j = 3; j <= n; j++) { arg = ir_insn_op(insn, j); - src_reg = ctx->regs[def][j]; + src_reg = reg_ops[j]; arg_insn = &ctx->ir_base[arg]; type = arg_insn->type; if (IR_IS_TYPE_INT(type)) { @@ -5861,7 +5863,7 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg fp_param = 0; for (j = 3; j <= n; j++) { arg = ir_insn_op(insn, j); - src_reg = ctx->regs[def][j]; + src_reg = reg_ops[j]; arg_insn = &ctx->ir_base[arg]; type = arg_insn->type; if (IR_IS_TYPE_INT(type)) {