Fix stack frame and assign all spill slots before code genearatin

This commit is contained in:
Dmitry Stogov 2023-06-21 19:04:22 +03:00
parent 4124ef5150
commit ebaefd376a
8 changed files with 133 additions and 299 deletions

38
ir.c
View File

@ -2105,3 +2105,41 @@ check_aliasing:
}
ctx->control = ir_emit3(ctx, IR_STORE, ctx->control, addr, val);
}
ir_type ir_get_return_type(ir_ctx *ctx)
{
ir_ref ref;
ir_insn *insn;
uint8_t ret_type = 255;
/* Check all RETURN nodes */
ref = ctx->ir_base[1].op1;
while (ref) {
insn = &ctx->ir_base[ref];
if (insn->op == IR_RETURN) {
if (ret_type == 255) {
if (insn->op2) {
ret_type = ctx->ir_base[insn->op2].type;
} else {
ret_type = IR_VOID;
}
} else if (insn->op2) {
if (ret_type != ctx->ir_base[insn->op2].type) {
IR_ASSERT(0 && "conflicting return types");
return IR_VOID;
}
} else {
if (ret_type != IR_VOID) {
IR_ASSERT(0 && "conflicting return types");
return IR_VOID;
}
}
}
ref = ctx->ir_base[ref].op3;
}
if (ret_type == 255) {
ret_type = IR_VOID;
}
return (ir_type)ret_type;
}

5
ir.h
View File

@ -567,6 +567,11 @@ struct _ir_ctx {
int32_t stack_frame_alignment;
int32_t stack_frame_size; /* spill stack frame size (used by register allocator and code generator) */
int32_t call_stack_size; /* stack for parameter passing (used by register allocator and code generator) */
uint64_t used_preserved_regs;
#ifdef IR_TARGET_X86
int32_t param_stack_size;
int32_t ret_slot;
#endif
uint32_t rodata_offset;
uint32_t jmp_table_offset;
uint32_t entries_count;

View File

@ -148,7 +148,6 @@ static bool aarch64_may_encode_addr_offset(int64_t offset, uint32_t type_size)
typedef struct _ir_backend_data {
ir_reg_alloc_data ra_data;
ir_regset used_preserved_regs;
uint32_t dessa_from_block;
dasm_State *dasm_state;
int rodata_label, jmp_table_label;
@ -1212,11 +1211,12 @@ static void ir_emit_prologue(ir_ctx *ctx)
| sub sp, sp, #(ctx->stack_frame_size + ctx->call_stack_size)
}
}
if (data->used_preserved_regs) {
if (ctx->used_preserved_regs) {
int offset;
uint32_t i;
ir_reg prev = IR_REG_NONE;
ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
ir_regset used_preserved_regs = ctx->used_preserved_regs;
if (ctx->flags & IR_USE_FRAME_POINTER) {
offset = ctx->stack_frame_size + sizeof(void*) * 2;
@ -1224,7 +1224,7 @@ static void ir_emit_prologue(ir_ctx *ctx)
offset = ctx->stack_frame_size + ctx->call_stack_size;
}
for (i = 0; i < IR_REG_NUM; i++) {
if (IR_REGSET_IN(data->used_preserved_regs, i)) {
if (IR_REGSET_IN(used_preserved_regs, i)) {
if (prev == IR_REG_NONE) {
prev = i;
} else if (i < IR_REG_FP_FIRST) {
@ -1262,11 +1262,12 @@ static void ir_emit_epilogue(ir_ctx *ctx)
ir_backend_data *data = ctx->data;
dasm_State **Dst = &data->dasm_state;
if (data->used_preserved_regs) {
if (ctx->used_preserved_regs) {
int offset;
uint32_t i;
ir_reg prev = IR_REG_NONE;
ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
ir_regset used_preserved_regs = ctx->used_preserved_regs;
if (ctx->flags & IR_USE_FRAME_POINTER) {
offset = ctx->stack_frame_size + sizeof(void*) * 2;
@ -1274,7 +1275,7 @@ static void ir_emit_epilogue(ir_ctx *ctx)
offset = ctx->stack_frame_size + ctx->call_stack_size;
}
for (i = 0; i < IR_REG_NUM; i++) {
if (IR_REGSET_IN(data->used_preserved_regs, i)) {
if (IR_REGSET_IN(used_preserved_regs, i)) {
if (prev == IR_REG_NONE) {
prev = i;
} else if (i < IR_REG_FP_FIRST) {
@ -4652,47 +4653,12 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx)
}
}
if (ctx->fixed_save_regset) {
ir_reg reg;
(void) reg;
data->used_preserved_regs = (ir_regset)ctx->fixed_save_regset;
IR_REGSET_FOREACH(data->used_preserved_regs, reg) {
ctx->stack_frame_size += sizeof(void*);
} IR_REGSET_FOREACH_END();
}
if ((ctx->flags & IR_HAS_CALLS) && !(ctx->flags & IR_FUNCTION)) {
while (IR_ALIGNED_SIZE(ctx->stack_frame_size, 16) != ctx->stack_frame_size) {
ctx->stack_frame_size += sizeof(void*);
ctx->stack_frame_alignment += sizeof(void*);
}
} else if (ctx->flags & IR_HAS_CALLS) {
ctx->flags |= IR_USE_FRAME_POINTER;
/* Stack must be 16 byte aligned */
/* Stack must be 16 byte aligned */
if (!(ctx->flags & IR_FUNCTION)) {
while (IR_ALIGNED_SIZE(ctx->stack_frame_size, 16) != ctx->stack_frame_size) {
ctx->stack_frame_size += sizeof(void*);
ctx->stack_frame_alignment += sizeof(void*);
}
} else if (ctx->flags & IR_USE_FRAME_POINTER) {
while (IR_ALIGNED_SIZE(ctx->stack_frame_size + sizeof(void*) * 2, 16) != ctx->stack_frame_size + sizeof(void*) * 2) {
ctx->stack_frame_size += sizeof(void*);
ctx->stack_frame_alignment += sizeof(void*);
}
} else {
while (IR_ALIGNED_SIZE(ctx->stack_frame_size, 16) != ctx->stack_frame_size) {
ctx->stack_frame_size += sizeof(void*);
ctx->stack_frame_alignment += sizeof(void*);
}
}
}
ir_fix_param_spills(ctx);
ctx->used_preserved_regs = ctx->fixed_save_regset;
ctx->flags |= IR_NO_STACK_COMBINE;
ir_fix_stack_frame(ctx);
}
static void ir_preallocate_call_stack(ir_ctx *ctx, ir_backend_data *data)
static void ir_preallocate_call_stack(ir_ctx *ctx)
{
int call_stack_size, peak_call_stack_size = 0;
ir_ref i, n;
@ -4715,57 +4681,24 @@ static void ir_preallocate_call_stack(ir_ctx *ctx, ir_backend_data *data)
}
}
static void ir_calc_stack_frame_size(ir_ctx *ctx, ir_backend_data *data)
void ir_fix_stack_frame(ir_ctx *ctx)
{
int i;
ir_live_interval **p, *ival;
uint32_t additional_size = 0;
ir_regset fixed_regset = (ctx->flags & IR_FUNCTION) ? (ir_regset)ctx->fixed_regset : IR_REGSET_PRESERVED;
if (ctx->fixed_save_regset) {
if (ctx->used_preserved_regs) {
ir_regset used_preserved_regs = (ir_regset)ctx->used_preserved_regs;
ir_reg reg;
(void) reg;
data->used_preserved_regs = (ir_regset)ctx->fixed_save_regset;
IR_REGSET_FOREACH(data->used_preserved_regs, reg) {
IR_REGSET_FOREACH(used_preserved_regs, reg) {
additional_size += sizeof(void*);
} IR_REGSET_FOREACH_END();
}
for (i = 1, p = ctx->live_intervals + i; i <= ctx->vregs_count; i++, p++) {
ival = *p;
if (ival) {
if (ival->reg != IR_REG_NONE) {
if (!IR_REGSET_IN(data->used_preserved_regs, ival->reg)
&& !IR_REGSET_IN(fixed_regset, ival->reg)
&& IR_REGSET_IN(IR_REGSET_PRESERVED, ival->reg)) {
if (!ctx->fixed_save_regset) {
IR_REGSET_INCL(data->used_preserved_regs, ival->reg);
additional_size += sizeof(void*);
} else {
// TODO: Preserved reg and fixed frame conflict ???
// IR_ASSERT(!ctx->fixed_save_regset && "NIY");
}
}
}
}
}
ival = ctx->live_intervals[0];
while (ival) {
if (ival->reg != IR_REG_NONE) {
if (!IR_REGSET_IN(data->used_preserved_regs, ival->reg)
&& !IR_REGSET_IN(fixed_regset, ival->reg)
&& IR_REGSET_IN(IR_REGSET_PRESERVED, ival->reg)) {
IR_REGSET_INCL(data->used_preserved_regs, ival->reg);
additional_size += sizeof(void*);
}
}
ival = ival->next;
}
ctx->stack_frame_size = IR_ALIGNED_SIZE(ctx->stack_frame_size, sizeof(void*));
ctx->stack_frame_size += additional_size;
ctx->stack_frame_alignment = 0;
ctx->call_stack_size = 0;
if ((ctx->flags & IR_HAS_CALLS) && !(ctx->flags & IR_FUNCTION)) {
while (IR_ALIGNED_SIZE(ctx->stack_frame_size, 16) != ctx->stack_frame_size) {
@ -4787,7 +4720,7 @@ static void ir_calc_stack_frame_size(ir_ctx *ctx, ir_backend_data *data)
}
} else {
if (!(ctx->flags & IR_NO_STACK_COMBINE)) {
ir_preallocate_call_stack(ctx, data);
ir_preallocate_call_stack(ctx);
}
while (IR_ALIGNED_SIZE(ctx->stack_frame_size + ctx->call_stack_size, 16) !=
ctx->stack_frame_size + ctx->call_stack_size) {
@ -4818,23 +4751,19 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
void *entry;
size_t size;
if (!ctx->live_intervals) {
ctx->stack_frame_size = 0;
}
ctx->stack_frame_alignment = 0;
ctx->call_stack_size = 0;
data.ra_data.unused_slot_4 = 0;
data.ra_data.unused_slot_2 = 0;
data.ra_data.unused_slot_1 = 0;
data.used_preserved_regs = 0;
data.rodata_label = 0;
data.jmp_table_label = 0;
ctx->data = &data;
if (!ctx->live_intervals) {
ctx->stack_frame_size = 0;
ctx->stack_frame_alignment = 0;
ctx->call_stack_size = 0;
ctx->used_preserved_regs = 0;
ir_allocate_unique_spill_slots(ctx);
} else {
ir_calc_stack_frame_size(ctx, &data);
}
if (ctx->fixed_stack_frame_size != -1) {
@ -4847,6 +4776,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
fprintf(stderr, "IR Compilation Aborted: ctx->stack_frame_size > ctx->fixed_stack_frame_size at %s:%d\n",
__FILE__, __LINE__);
#endif
ctx->data = NULL;
return NULL;
}
ctx->stack_frame_size = ctx->fixed_stack_frame_size;
@ -5093,6 +5023,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
const void *exit_addr = ctx->get_exit_addr(i);
if (!exit_addr) {
ctx->data = NULL;
return 0;
}
| b &exit_addr
@ -5209,6 +5140,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
if (ctx->code_buffer == NULL) {
ir_mem_unmap(entry, size);
}
ctx->data = NULL;
return NULL;
}
size = *size_ptr;
@ -5216,6 +5148,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
if (ctx->code_buffer != NULL) {
if (IR_ALIGNED_SIZE(size, 16) > ctx->code_buffer_size) {
dasm_free(&data.dasm_state);
ctx->data = NULL;
return NULL;
}
entry = ctx->code_buffer;
@ -5242,6 +5175,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
if (ctx->code_buffer == NULL) {
ir_mem_unmap(entry, size);
}
ctx->data = NULL;
return NULL;
}
@ -5278,6 +5212,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
ir_mem_protect(entry, size);
}
ctx->data = NULL;
return entry;
}

View File

@ -621,54 +621,6 @@ static void ir_emit_store(ir_ctx *ctx, FILE *f, ir_insn *insn)
fprintf(f, ";\n");
}
static uint8_t ir_get_return_type(ir_ctx *ctx)
{
ir_ref ref;
ir_insn *insn;
uint8_t ret_type = 255;
/* Check all RETURN nodes */
ref = ctx->ir_base[1].op1;
while (ref) {
insn = &ctx->ir_base[ref];
if (insn->op == IR_RETURN) {
if (ret_type == 255) {
if (insn->op2) {
ret_type = ctx->ir_base[insn->op2].type;
} else {
ret_type = IR_VOID;
}
} else if (insn->op2) {
if (ret_type != ctx->ir_base[insn->op2].type) {
IR_ASSERT(0 && "conflicting return types");
return 0;
}
} else {
if (ret_type != IR_VOID) {
IR_ASSERT(0 && "conflicting return types");
return 0;
}
}
} else if (insn->op == IR_UNREACHABLE) {
ir_insn *prev = &ctx->ir_base[insn->op1];
IR_ASSERT(prev->op == IR_TAILCALL);
if (ret_type == 255) {
ret_type = prev->type;
} else if (ret_type != prev->type) {
IR_ASSERT(0 && "conflicting return types");
return 0;
}
}
ref = ctx->ir_base[ref].op3;
}
if (ret_type == 255) {
ret_type = IR_VOID;
}
return ret_type;
}
static int ir_emit_func(ir_ctx *ctx, FILE *f)
{
ir_ref i, n, *p;

View File

@ -1177,6 +1177,11 @@ typedef struct _ir_target_constraints ir_target_constraints;
int ir_get_target_constraints(const ir_ctx *ctx, ir_ref ref, ir_target_constraints *constraints);
void ir_fix_stack_frame(ir_ctx *ctx);
/* Utility */
ir_type ir_get_return_type(ir_ctx *ctx);
//#define IR_BITSET_LIVENESS
#endif /* IR_PRIVATE_H */

20
ir_ra.c
View File

@ -3501,6 +3501,16 @@ static int ir_linear_scan(ir_ctx *ctx)
}
}
#ifdef IR_TARGET_X86
ir_type ret_type = ir_get_return_type(ctx);
if (ret_type == IR_FLOAT || ret_type == IR_DOUBLE) {
ctx->ret_slot = ir_allocate_spill_slot(ctx, ret_type, &data);
} else {
ctx->ret_slot = -1;
}
#endif
#ifdef IR_DEBUG
if (ctx->flags & IR_DEBUG_RA) {
fprintf(stderr, "---- Finish LSRA\n");
@ -3519,6 +3529,7 @@ static void assign_regs(ir_ctx *ctx)
ir_use_pos *use_pos;
int8_t reg;
ir_ref ref;
ir_regset used_regs = 0;
if (!ctx->regs) {
ctx->regs = ir_mem_malloc(sizeof(ir_regs) * ctx->insns_count);
@ -3532,6 +3543,7 @@ static void assign_regs(ir_ctx *ctx)
do {
if (ival->reg != IR_REG_NONE) {
reg = ival->reg;
IR_REGSET_INCL(used_regs, reg);
use_pos = ival->use_pos;
while (use_pos) {
ref = (use_pos->hint_ref < 0) ? -use_pos->hint_ref : IR_LIVE_POS_TO_REF(use_pos->pos);
@ -3549,6 +3561,7 @@ static void assign_regs(ir_ctx *ctx)
if (ival) {
do {
if (ival->reg != IR_REG_NONE) {
IR_REGSET_INCL(used_regs, ival->reg);
use_pos = ival->use_pos;
while (use_pos) {
reg = ival->reg;
@ -3632,10 +3645,17 @@ static void assign_regs(ir_ctx *ctx)
if (ival) {
do {
IR_ASSERT(ival->reg != IR_REG_NONE);
IR_REGSET_INCL(used_regs, ival->reg);
ir_set_alocated_reg(ctx, ival->tmp_ref, ival->tmp_op_num, ival->reg);
ival = ival->next;
} while (ival);
}
ctx->used_preserved_regs = IR_REGSET_UNION((ir_regset)ctx->fixed_save_regset,
IR_REGSET_DIFFERENCE(IR_REGSET_INTERSECTION(used_regs, IR_REGSET_PRESERVED),
(ctx->flags & IR_FUNCTION) ? (ir_regset)ctx->fixed_regset : IR_REGSET_PRESERVED));
ir_fix_stack_frame(ctx);
}
int ir_reg_alloc(ir_ctx *ctx)

View File

@ -320,12 +320,6 @@
typedef struct _ir_backend_data {
ir_reg_alloc_data ra_data;
int32_t param_stack_size;
#ifndef IR_REG_FP_RET1
int32_t float_ret_slot;
int32_t double_ret_slot;
#endif
ir_regset used_preserved_regs;
uint32_t dessa_from_block;
dasm_State *dasm_state;
int rodata_label, jmp_table_label;
@ -2136,9 +2130,10 @@ static void ir_emit_prologue(ir_ctx *ctx)
| sub Ra(IR_REG_RSP), (ctx->stack_frame_size + ctx->call_stack_size)
}
}
if (data->used_preserved_regs) {
if (ctx->used_preserved_regs) {
int offset;
uint32_t i;
ir_regset used_preserved_regs = ctx->used_preserved_regs;
if (ctx->flags & IR_USE_FRAME_POINTER) {
offset = 0;
@ -2146,7 +2141,7 @@ static void ir_emit_prologue(ir_ctx *ctx)
offset = ctx->stack_frame_size + ctx->call_stack_size;
}
for (i = 0; i < IR_REG_NUM; i++) {
if (IR_REGSET_IN(data->used_preserved_regs, i)) {
if (IR_REGSET_IN(used_preserved_regs, i)) {
if (i < IR_REG_FP_FIRST) {
ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
@ -2172,9 +2167,10 @@ static void ir_emit_epilogue(ir_ctx *ctx)
ir_backend_data *data = ctx->data;
dasm_State **Dst = &data->dasm_state;
if (data->used_preserved_regs) {
if (ctx->used_preserved_regs) {
int offset;
uint32_t i;
ir_regset used_preserved_regs = ctx->used_preserved_regs;
if (ctx->flags & IR_USE_FRAME_POINTER) {
offset = 0;
@ -2182,7 +2178,7 @@ static void ir_emit_epilogue(ir_ctx *ctx)
offset = ctx->stack_frame_size + ctx->call_stack_size;
}
for (i = 0; i < IR_REG_NUM; i++) {
if (IR_REGSET_IN(data->used_preserved_regs, i)) {
if (IR_REGSET_IN(used_preserved_regs, i)) {
if (i < IR_REG_FP_FIRST) {
ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
@ -4321,8 +4317,8 @@ static void ir_emit_return_void(ir_ctx *ctx)
ir_emit_epilogue(ctx);
#ifdef IR_TARGET_X86
if (sizeof(void*) == 4 && (ctx->flags & IR_FASTCALL_FUNC) && data->param_stack_size) {
| ret data->param_stack_size
if (sizeof(void*) == 4 && (ctx->flags & IR_FASTCALL_FUNC) && ctx->param_stack_size) {
| ret ctx->param_stack_size
return;
}
#endif
@ -4374,7 +4370,7 @@ static void ir_emit_return_fp(ir_ctx *ctx, ir_ref ref, ir_insn *insn)
| fld dword [Ra(fp)+offset]
}
} else {
int32_t offset = (type == IR_FLOAT) ? data->float_ret_slot : data->double_ret_slot;
int32_t offset = ctx->ret_slot;
ir_reg fp;
IR_ASSERT(offset != -1);
@ -7458,7 +7454,6 @@ static int ir_fix_dessa_tmps(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to)
static void ir_fix_param_spills(ir_ctx *ctx)
{
ir_backend_data *data = ctx->data;
ir_use_list *use_list = &ctx->use_lists[1];
ir_insn *insn;
ir_ref i, n, *p, use;
@ -7535,48 +7530,13 @@ static void ir_fix_param_spills(ir_ctx *ctx)
}
}
}
data->param_stack_size = stack_offset;
}
#ifndef IR_REG_FP_RET1
static uint8_t ir_get_return_type(ir_ctx *ctx)
{
ir_ref ref;
ir_insn *insn;
uint8_t ret_type = 255;
/* Check all RETURN nodes */
ref = ctx->ir_base[1].op1;
while (ref) {
insn = &ctx->ir_base[ref];
if (insn->op == IR_RETURN) {
if (ret_type == 255) {
if (insn->op2) {
ret_type = ctx->ir_base[insn->op2].type;
} else {
ret_type = IR_VOID;
}
} else if (insn->op2) {
if (ret_type != ctx->ir_base[insn->op2].type) {
IR_ASSERT(0 && "conflicting return types");
return 0;
}
} else {
if (ret_type != IR_VOID) {
IR_ASSERT(0 && "conflicting return types");
return 0;
}
}
}
ref = ctx->ir_base[ref].op3;
#ifdef IR_TARGET_X86
if (sizeof(void*) == 4 && (ctx->flags & IR_FASTCALL_FUNC)) {
ctx->param_stack_size = stack_offset;
}
if (ret_type == 255) {
ret_type = IR_VOID;
}
return ret_type;
}
#endif
}
static void ir_allocate_unique_spill_slots(ir_ctx *ctx)
{
@ -7593,14 +7553,10 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx)
#ifndef IR_REG_FP_RET1
ir_type ret_type = ir_get_return_type(ctx);
if (ret_type == IR_FLOAT) {
if (data->float_ret_slot == -1) {
data->float_ret_slot = ir_allocate_spill_slot(ctx, ret_type, &data->ra_data);
}
} else if (ret_type == IR_DOUBLE) {
if (data->double_ret_slot == -1) {
data->double_ret_slot = ir_allocate_spill_slot(ctx, ret_type, &data->ra_data);
}
if (ret_type == IR_FLOAT || ret_type == IR_DOUBLE) {
ctx->ret_slot = ir_allocate_spill_slot(ctx, ret_type, &data->ra_data);
} else {
ctx->ret_slot = -1;
}
#endif
@ -7765,40 +7721,12 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx)
}
}
if (ctx->fixed_save_regset) {
ir_reg reg;
(void) reg;
data->used_preserved_regs = (ir_regset)ctx->fixed_save_regset;
IR_REGSET_FOREACH(data->used_preserved_regs, reg) {
ctx->stack_frame_size += sizeof(void*);
} IR_REGSET_FOREACH_END();
}
if (ctx->flags & IR_HAS_CALLS) {
/* Stack must be 16 byte aligned */
if (!(ctx->flags & IR_FUNCTION)) {
while (IR_ALIGNED_SIZE(ctx->stack_frame_size, 16) != ctx->stack_frame_size) {
ctx->stack_frame_size += sizeof(void*);
ctx->stack_frame_alignment += sizeof(void*);
}
} else if (ctx->flags & IR_USE_FRAME_POINTER) {
while (IR_ALIGNED_SIZE(ctx->stack_frame_size + sizeof(void*) * 2, 16) != ctx->stack_frame_size + sizeof(void*) * 2) {
ctx->stack_frame_size += sizeof(void*);
ctx->stack_frame_alignment += sizeof(void*);
}
} else {
while (IR_ALIGNED_SIZE(ctx->stack_frame_size + sizeof(void*), 16) != ctx->stack_frame_size + sizeof(void*)) {
ctx->stack_frame_size += sizeof(void*);
ctx->stack_frame_alignment += sizeof(void*);
}
}
}
ir_fix_param_spills(ctx);
ctx->used_preserved_regs = ctx->fixed_save_regset;
ctx->flags |= IR_NO_STACK_COMBINE;
ir_fix_stack_frame(ctx);
}
static void ir_preallocate_call_stack(ir_ctx *ctx, ir_backend_data *data)
static void ir_preallocate_call_stack(ir_ctx *ctx)
{
int call_stack_size, peak_call_stack_size = 0;
ir_ref i, n;
@ -7825,70 +7753,24 @@ static void ir_preallocate_call_stack(ir_ctx *ctx, ir_backend_data *data)
}
}
static void ir_calc_stack_frame_size(ir_ctx *ctx, ir_backend_data *data)
void ir_fix_stack_frame(ir_ctx *ctx)
{
int i;
ir_live_interval **p, *ival;
uint32_t additional_size = 0;
ir_regset fixed_regset = (ctx->flags & IR_FUNCTION) ? (ir_regset)ctx->fixed_regset : IR_REGSET_PRESERVED;
if (ctx->fixed_save_regset) {
if (ctx->used_preserved_regs) {
ir_regset used_preserved_regs = (ir_regset)ctx->used_preserved_regs;
ir_reg reg;
(void) reg;
data->used_preserved_regs = (ir_regset)ctx->fixed_save_regset;
IR_REGSET_FOREACH(data->used_preserved_regs, reg) {
IR_REGSET_FOREACH(used_preserved_regs, reg) {
additional_size += sizeof(void*);
} IR_REGSET_FOREACH_END();
}
for (i = 1, p = ctx->live_intervals + i; i <= ctx->vregs_count; i++, p++) {
ival = *p;
if (ival) {
if (ival->reg != IR_REG_NONE) {
if (!IR_REGSET_IN(data->used_preserved_regs, ival->reg)
&& !IR_REGSET_IN(fixed_regset, ival->reg)
&& IR_REGSET_IN(IR_REGSET_PRESERVED, ival->reg)) {
if (!ctx->fixed_save_regset) {
IR_REGSET_INCL(data->used_preserved_regs, ival->reg);
additional_size += sizeof(void*);
} else {
// TODO: Preserved reg and fixed frame conflict ???
// IR_ASSERT(!ctx->fixed_save_regset && "NIY");
}
}
}
}
}
ival = ctx->live_intervals[0];
while (ival) {
if (ival->reg != IR_REG_NONE) {
if (!IR_REGSET_IN(data->used_preserved_regs, ival->reg)
&& !IR_REGSET_IN(fixed_regset, ival->reg)
&& IR_REGSET_IN(IR_REGSET_PRESERVED, ival->reg)) {
IR_REGSET_INCL(data->used_preserved_regs, ival->reg);
additional_size += sizeof(void*);
}
}
ival = ival->next;
}
#ifndef IR_REG_FP_RET1
ir_type ret_type = ir_get_return_type(ctx);
if (ret_type == IR_FLOAT) {
if (data->float_ret_slot == -1) {
data->float_ret_slot = ir_allocate_spill_slot(ctx, ret_type, &data->ra_data);
}
} else if (ret_type == IR_DOUBLE) {
if (data->double_ret_slot == -1) {
data->double_ret_slot = ir_allocate_spill_slot(ctx, ret_type, &data->ra_data);
}
}
#endif
ctx->stack_frame_size = IR_ALIGNED_SIZE(ctx->stack_frame_size, sizeof(void*));
ctx->stack_frame_size += additional_size;
ctx->stack_frame_alignment = 0;
ctx->call_stack_size = 0;
if (ctx->flags & IR_HAS_CALLS) {
/* Stack must be 16 byte aligned */
@ -7904,7 +7786,7 @@ static void ir_calc_stack_frame_size(ir_ctx *ctx, ir_backend_data *data)
}
} else {
if (!(ctx->flags & IR_NO_STACK_COMBINE)) {
ir_preallocate_call_stack(ctx, data);
ir_preallocate_call_stack(ctx);
}
while (IR_ALIGNED_SIZE(ctx->stack_frame_size + ctx->call_stack_size + sizeof(void*), 16) !=
ctx->stack_frame_size + ctx->call_stack_size + sizeof(void*)) {
@ -7932,19 +7814,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
void *entry;
size_t size;
if (!ctx->live_intervals) {
ctx->stack_frame_size = 0;
}
ctx->stack_frame_alignment = 0;
ctx->call_stack_size = 0;
data.ra_data.unused_slot_4 = 0;
data.ra_data.unused_slot_2 = 0;
data.ra_data.unused_slot_1 = 0;
#ifndef IR_REG_FP_RET1
data.float_ret_slot = -1;
data.double_ret_slot = -1;
#endif
data.used_preserved_regs = 0;
data.rodata_label = 0;
data.jmp_table_label = 0;
data.double_neg_const = 0;
@ -7954,9 +7826,11 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
ctx->data = &data;
if (!ctx->live_intervals) {
ctx->stack_frame_size = 0;
ctx->stack_frame_alignment = 0;
ctx->call_stack_size = 0;
ctx->used_preserved_regs = 0;
ir_allocate_unique_spill_slots(ctx);
} else {
ir_calc_stack_frame_size(ctx, &data);
}
if (ctx->fixed_stack_frame_size != -1) {
@ -7969,6 +7843,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
fprintf(stderr, "IR Compilation Aborted: ctx->stack_frame_size > ctx->fixed_stack_frame_size at %s:%d\n",
__FILE__, __LINE__);
#endif
ctx->data = NULL;
return NULL;
}
ctx->stack_frame_size = ctx->fixed_stack_frame_size;
@ -8663,6 +8538,7 @@ next_block:;
if (ret != DASM_S_OK) {
IR_ASSERT(0);
dasm_free(&data.dasm_state);
ctx->data = NULL;
return NULL;
}
size = *size_ptr;
@ -8670,6 +8546,7 @@ next_block:;
if (ctx->code_buffer != NULL) {
if (IR_ALIGNED_SIZE(size, 16) > ctx->code_buffer_size) {
dasm_free(&data.dasm_state);
ctx->data = NULL;
return NULL;
}
entry = ctx->code_buffer;
@ -8686,6 +8563,7 @@ next_block:;
if (ctx->code_buffer == NULL) {
ir_mem_unmap(entry, size);
}
ctx->data = NULL;
return NULL;
}
@ -8720,6 +8598,7 @@ next_block:;
ir_mem_protect(entry, size);
}
ctx->data = NULL;
return entry;
}

View File

@ -106,7 +106,7 @@ x86
TMP
[%xmm0]: [10.2-10.3)/1
[%eax]: [10.2-10.3)/0
R1 (d_2)
R1 (d_2) [SPILL=0x24]
[%xmm0]: [2.2-10.2), DEF(2.2)
: [10.2-24.0), [26.0-29.0), [31.0-36.0)
: [36.0-38.0), USE(36.1/2)