mirror of
https://github.com/danog/ir.git
synced 2024-12-02 09:38:29 +01:00
Fix stack frame and assign all spill slots before code genearatin
This commit is contained in:
parent
4124ef5150
commit
ebaefd376a
38
ir.c
38
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;
|
||||
}
|
||||
|
5
ir.h
5
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;
|
||||
|
119
ir_aarch64.dasc
119
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;
|
||||
}
|
||||
|
||||
|
48
ir_emit_c.c
48
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;
|
||||
|
@ -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
20
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)
|
||||
|
195
ir_x86.dasc
195
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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user