mirror of
https://github.com/danog/ir.git
synced 2024-11-26 20:34:53 +01:00
Implement AFREE instruction to revert ALLOCA
This commit is contained in:
parent
efbc51baaa
commit
6790ebf3b5
2
TODO
2
TODO
@ -1,5 +1,5 @@
|
||||
- va_arg nodes
|
||||
- BSTART, BEND nodes (to free data allocated by ALLOCA)
|
||||
? BSTART, BEND nodes (to free data allocated by ALLOCA) (now it's possible to do this through AFREE)
|
||||
- Full support for function prototypes ???
|
||||
(now we may only set "fastcall" calling convention for constants or for variables through BITCAST)
|
||||
|
||||
|
1
ir.h
1
ir.h
@ -236,6 +236,7 @@ typedef enum _ir_type {
|
||||
\
|
||||
/* memory reference and load/store ops */ \
|
||||
_(ALLOCA, a2, src, def, ___) /* alloca(def) */ \
|
||||
_(AFREE, a2, src, def, ___) /* revert alloca(def) */ \
|
||||
_(VADDR, d1, var, ___, ___) /* load address of local var */ \
|
||||
_(VLOAD, l2, src, var, ___) /* load value of local var */ \
|
||||
_(VSTORE, s3, src, var, def) /* store value to local var */ \
|
||||
|
@ -766,8 +766,9 @@ binop_fp:
|
||||
}
|
||||
break;
|
||||
case IR_ALLOCA:
|
||||
IR_ASSERT(ctx->flags & IR_FUNCTION);
|
||||
ctx->flags |= IR_USE_FRAME_POINTER | IR_HAS_ALLOCA;
|
||||
if (ctx->flags & IR_FUNCTION) {
|
||||
ctx->flags |= IR_USE_FRAME_POINTER | IR_HAS_ALLOCA;
|
||||
}
|
||||
return IR_ALLOCA;
|
||||
case IR_LOAD:
|
||||
ir_match_fuse_addr(ctx, insn->op2, insn->type);
|
||||
@ -3172,11 +3173,15 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
size = IR_ALIGNED_SIZE(size, 8);
|
||||
}
|
||||
| sub sp, sp, #size
|
||||
if (!(ctx->flags & IR_FUNCTION)) {
|
||||
data->call_stack_size += size;
|
||||
}
|
||||
} else {
|
||||
int32_t alignment = (ctx->flags & IR_HAS_CALLS) ? 16 : 8;
|
||||
ir_reg op2_reg = ctx->regs[def][2];
|
||||
ir_type type = ctx->ir_base[insn->op2].type;
|
||||
|
||||
IR_ASSERT(ctx->flags & IR_FUNCTION);
|
||||
IR_ASSERT(def_reg != IR_REG_NONE && op2_reg != IR_REG_NONE);
|
||||
if (op2_reg & IR_REG_SPILL_LOAD) {
|
||||
op2_reg &= ~IR_REG_SPILL_LOAD;
|
||||
@ -3196,6 +3201,46 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_emit_afree(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
dasm_State **Dst = &data->dasm_state;
|
||||
|
||||
if (IR_IS_CONST_REF(insn->op2)) {
|
||||
ir_insn *val = &ctx->ir_base[insn->op2];
|
||||
int32_t size = val->val.i32;
|
||||
|
||||
IR_ASSERT(IR_IS_TYPE_INT(val->type));
|
||||
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0);
|
||||
|
||||
if (ctx->flags & IR_HAS_CALLS) {
|
||||
/* Stack must be 16 byte aligned */
|
||||
size = IR_ALIGNED_SIZE(size, 16);
|
||||
} else {
|
||||
size = IR_ALIGNED_SIZE(size, 8);
|
||||
}
|
||||
| add sp, sp, #size
|
||||
if (!(ctx->flags & IR_FUNCTION)) {
|
||||
data->call_stack_size -= size;
|
||||
}
|
||||
} else {
|
||||
// int32_t alignment = (ctx->flags & IR_HAS_CALLS) ? 16 : 8;
|
||||
ir_reg op2_reg = ctx->regs[def][2];
|
||||
ir_type type = ctx->ir_base[insn->op2].type;
|
||||
|
||||
IR_ASSERT(ctx->flags & IR_FUNCTION);
|
||||
IR_ASSERT(op2_reg != IR_REG_NONE);
|
||||
if (op2_reg & IR_REG_SPILL_LOAD) {
|
||||
op2_reg &= ~IR_REG_SPILL_LOAD;
|
||||
ir_emit_load(ctx, type, op2_reg, insn->op2);
|
||||
}
|
||||
|
||||
// TODO: alignment
|
||||
|
||||
| add sp, sp, Rx(op2_reg);
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
@ -4987,6 +5032,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
|
||||
case IR_ALLOCA:
|
||||
ir_emit_alloca(ctx, i, insn);
|
||||
break;
|
||||
case IR_AFREE:
|
||||
ir_emit_afree(ctx, i, insn);
|
||||
break;
|
||||
case IR_EXITCALL:
|
||||
ir_emit_exitcall(ctx, i, insn);
|
||||
break;
|
||||
|
52
ir_x86.dasc
52
ir_x86.dasc
@ -1344,8 +1344,9 @@ binop_fp:
|
||||
break;
|
||||
case IR_ALLOCA:
|
||||
/* alloca() may be use only in functions */
|
||||
IR_ASSERT(ctx->flags & IR_FUNCTION);
|
||||
ctx->flags |= IR_USE_FRAME_POINTER | IR_HAS_ALLOCA;
|
||||
if (ctx->flags & IR_FUNCTION) {
|
||||
ctx->flags |= IR_USE_FRAME_POINTER | IR_HAS_ALLOCA;
|
||||
}
|
||||
return IR_ALLOCA;
|
||||
case IR_VSTORE:
|
||||
if (IR_IS_TYPE_INT(ctx->ir_base[insn->op3].type)) {
|
||||
@ -5252,11 +5253,15 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
size = IR_ALIGNED_SIZE(size, 8);
|
||||
}
|
||||
| ASM_REG_IMM_OP sub, IR_ADDR, IR_REG_RSP, size
|
||||
if (!(ctx->flags & IR_FUNCTION)) {
|
||||
data->call_stack_size += size;
|
||||
}
|
||||
} else {
|
||||
int32_t alignment = (ctx->flags & IR_HAS_CALLS) ? 16 : 8;
|
||||
ir_reg op2_reg = ctx->regs[def][2];
|
||||
ir_type type = ctx->ir_base[insn->op2].type;
|
||||
|
||||
IR_ASSERT(ctx->flags & IR_FUNCTION);
|
||||
IR_ASSERT(def_reg != IR_REG_NONE);
|
||||
if (op2_reg != IR_REG_NONE && (op2_reg & IR_REG_SPILL_LOAD)) {
|
||||
op2_reg &= ~IR_REG_SPILL_LOAD;
|
||||
@ -5284,6 +5289,46 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_emit_afree(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
dasm_State **Dst = &data->dasm_state;
|
||||
|
||||
if (IR_IS_CONST_REF(insn->op2)) {
|
||||
ir_insn *val = &ctx->ir_base[insn->op2];
|
||||
int32_t size = val->val.i32;
|
||||
|
||||
IR_ASSERT(IR_IS_TYPE_INT(val->type));
|
||||
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0);
|
||||
IR_ASSERT(IR_IS_SIGNED_32BIT(val->val.i64));
|
||||
|
||||
if (ctx->flags & IR_HAS_CALLS) {
|
||||
/* Stack must be 16 byte aligned */
|
||||
size = IR_ALIGNED_SIZE(size, 16);
|
||||
} else {
|
||||
size = IR_ALIGNED_SIZE(size, 8);
|
||||
}
|
||||
| ASM_REG_IMM_OP add, IR_ADDR, IR_REG_RSP, size
|
||||
if (!(ctx->flags & IR_FUNCTION)) {
|
||||
data->call_stack_size -= size;
|
||||
}
|
||||
} else {
|
||||
// int32_t alignment = (ctx->flags & IR_HAS_CALLS) ? 16 : 8;
|
||||
ir_reg op2_reg = ctx->regs[def][2];
|
||||
ir_type type = ctx->ir_base[insn->op2].type;
|
||||
|
||||
IR_ASSERT(ctx->flags & IR_FUNCTION);
|
||||
if (op2_reg != IR_REG_NONE && (op2_reg & IR_REG_SPILL_LOAD)) {
|
||||
op2_reg &= ~IR_REG_SPILL_LOAD;
|
||||
ir_emit_load(ctx, type, op2_reg, insn->op2);
|
||||
}
|
||||
|
||||
// TODO: alignment ???
|
||||
|
||||
| ASM_REG_REG_OP add, IR_ADDR, IR_REG_RSP, op2_reg
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
@ -7858,6 +7903,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
|
||||
case IR_ALLOCA:
|
||||
ir_emit_alloca(ctx, i, insn);
|
||||
break;
|
||||
case IR_AFREE:
|
||||
ir_emit_afree(ctx, i, insn);
|
||||
break;
|
||||
case IR_EXITCALL:
|
||||
ir_emit_exitcall(ctx, i, insn);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user