From ebaefd376ada98dd84e85e5daa49cae73d6428a3 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 21 Jun 2023 19:04:22 +0300 Subject: [PATCH] Fix stack frame and assign all spill slots before code genearatin --- ir.c | 38 +++++++ ir.h | 5 + ir_aarch64.dasc | 119 +++++-------------- ir_emit_c.c | 48 -------- ir_private.h | 5 + ir_ra.c | 20 ++++ ir_x86.dasc | 195 ++++++-------------------------- tests/debug.x86/regset-test.irt | 2 +- 8 files changed, 133 insertions(+), 299 deletions(-) diff --git a/ir.c b/ir.c index 1d4a59c..4ade8ac 100644 --- a/ir.c +++ b/ir.c @@ -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; +} diff --git a/ir.h b/ir.h index cff113d..da8a498 100644 --- a/ir.h +++ b/ir.h @@ -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; diff --git a/ir_aarch64.dasc b/ir_aarch64.dasc index 3c1645a..8b5f911 100644 --- a/ir_aarch64.dasc +++ b/ir_aarch64.dasc @@ -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; } diff --git a/ir_emit_c.c b/ir_emit_c.c index 250b464..c7620eb 100644 --- a/ir_emit_c.c +++ b/ir_emit_c.c @@ -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; diff --git a/ir_private.h b/ir_private.h index bb666df..a8bb69f 100644 --- a/ir_private.h +++ b/ir_private.h @@ -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 */ diff --git a/ir_ra.c b/ir_ra.c index 2016083..1b05cc5 100644 --- a/ir_ra.c +++ b/ir_ra.c @@ -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) diff --git a/ir_x86.dasc b/ir_x86.dasc index 24ee5f7..01e3cbd 100644 --- a/ir_x86.dasc +++ b/ir_x86.dasc @@ -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; } diff --git a/tests/debug.x86/regset-test.irt b/tests/debug.x86/regset-test.irt index 927b4ec..4cd4c08 100644 --- a/tests/debug.x86/regset-test.irt +++ b/tests/debug.x86/regset-test.irt @@ -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)