mirror of
https://github.com/danog/ir.git
synced 2024-12-02 09:38:29 +01:00
On MacOS/AArch64 varargs must be passed on stack
This commit is contained in:
parent
a746ceb650
commit
c5bf8003c0
@ -4102,10 +4102,19 @@ static int32_t ir_call_used_stack(ir_ctx *ctx, ir_insn *insn)
|
|||||||
int int_reg_params_count = IR_REG_INT_ARGS;
|
int int_reg_params_count = IR_REG_INT_ARGS;
|
||||||
int fp_reg_params_count = IR_REG_FP_ARGS;
|
int fp_reg_params_count = IR_REG_FP_ARGS;
|
||||||
int32_t used_stack = 0;
|
int32_t used_stack = 0;
|
||||||
|
#ifdef __APPLE__
|
||||||
|
const ir_proto_t *proto = ir_call_proto(ctx, insn);
|
||||||
|
int last_named_input = (proto && (proto->flags & IR_VARARG_FUNC)) ? proto->params_count + 2 : insn->inputs_count;
|
||||||
|
#endif
|
||||||
|
|
||||||
n = insn->inputs_count;
|
n = insn->inputs_count;
|
||||||
for (j = 3; j <= n; j++) {
|
for (j = 3; j <= n; j++) {
|
||||||
type = ctx->ir_base[ir_insn_op(insn, j)].type;
|
type = ctx->ir_base[ir_insn_op(insn, j)].type;
|
||||||
|
#ifdef __APPLE__
|
||||||
|
if (j > last_named_input) {
|
||||||
|
used_stack += IR_MAX(sizeof(void*), ir_type_size[type]);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
if (IR_IS_TYPE_INT(type)) {
|
if (IR_IS_TYPE_INT(type)) {
|
||||||
if (int_param >= int_reg_params_count) {
|
if (int_param >= int_reg_params_count) {
|
||||||
used_stack += IR_MAX(sizeof(void*), ir_type_size[type]);
|
used_stack += IR_MAX(sizeof(void*), ir_type_size[type]);
|
||||||
@ -4171,6 +4180,11 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
const ir_proto_t *proto = ir_call_proto(ctx, insn);
|
||||||
|
int last_named_input = (proto && (proto->flags & IR_VARARG_FUNC)) ? proto->params_count + 2 : insn->inputs_count;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* 1. move all register arguments that should be passed through stack
|
/* 1. move all register arguments that should be passed through stack
|
||||||
* and collect arguments that should be passed through registers */
|
* and collect arguments that should be passed through registers */
|
||||||
copies = ir_mem_malloc((n - 2) * sizeof(ir_copy));
|
copies = ir_mem_malloc((n - 2) * sizeof(ir_copy));
|
||||||
@ -4179,6 +4193,11 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg
|
|||||||
src_reg = ir_get_alocated_reg(ctx, def, j);
|
src_reg = ir_get_alocated_reg(ctx, def, j);
|
||||||
arg_insn = &ctx->ir_base[arg];
|
arg_insn = &ctx->ir_base[arg];
|
||||||
type = arg_insn->type;
|
type = arg_insn->type;
|
||||||
|
#ifdef __APPLE__
|
||||||
|
if (j > last_named_input) {
|
||||||
|
dst_reg = IR_REG_NONE; /* pass argument through stack */
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
if (IR_IS_TYPE_INT(type)) {
|
if (IR_IS_TYPE_INT(type)) {
|
||||||
if (int_param < int_reg_params_count) {
|
if (int_param < int_reg_params_count) {
|
||||||
dst_reg = int_reg_params[int_param];
|
dst_reg = int_reg_params[int_param];
|
||||||
@ -4244,6 +4263,11 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg
|
|||||||
src_reg = ir_get_alocated_reg(ctx, def, j);
|
src_reg = ir_get_alocated_reg(ctx, def, j);
|
||||||
arg_insn = &ctx->ir_base[arg];
|
arg_insn = &ctx->ir_base[arg];
|
||||||
type = arg_insn->type;
|
type = arg_insn->type;
|
||||||
|
#ifdef __APPLE__
|
||||||
|
if (j > last_named_input) {
|
||||||
|
dst_reg = IR_REG_NONE; /* pass argument through stack */
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
if (IR_IS_TYPE_INT(type)) {
|
if (IR_IS_TYPE_INT(type)) {
|
||||||
if (int_param < int_reg_params_count) {
|
if (int_param < int_reg_params_count) {
|
||||||
dst_reg = int_reg_params[int_param];
|
dst_reg = int_reg_params[int_param];
|
||||||
|
30
ir_emit.c
30
ir_emit.c
@ -66,6 +66,22 @@ static const int8_t _ir_fp_reg_params[IR_REG_FP_ARGS];
|
|||||||
static const int8_t *_ir_fp_reg_params;
|
static const int8_t *_ir_fp_reg_params;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const ir_proto_t *ir_call_proto(const ir_ctx *ctx, ir_insn *insn)
|
||||||
|
{
|
||||||
|
if (IR_IS_CONST_REF(insn->op2)) {
|
||||||
|
const ir_insn *func = &ctx->ir_base[insn->op2];
|
||||||
|
|
||||||
|
if (func->op == IR_FUNC || func->op == IR_FUNC_ADDR) {
|
||||||
|
if (func->proto) {
|
||||||
|
return (const ir_proto_t *)ir_get_str(ctx, func->proto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ctx->ir_base[insn->op2].op == IR_PROTO) {
|
||||||
|
return (const ir_proto_t *)ir_get_str(ctx, ctx->ir_base[insn->op2].op2);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef IR_HAVE_FASTCALL
|
#ifdef IR_HAVE_FASTCALL
|
||||||
static const int8_t _ir_int_fc_reg_params[IR_REG_INT_FCARGS];
|
static const int8_t _ir_int_fc_reg_params[IR_REG_INT_FCARGS];
|
||||||
static const int8_t *_ir_fp_fc_reg_params;
|
static const int8_t *_ir_fp_fc_reg_params;
|
||||||
@ -101,19 +117,9 @@ bool ir_is_fastcall(const ir_ctx *ctx, const ir_insn *insn)
|
|||||||
|
|
||||||
bool ir_is_vararg(const ir_ctx *ctx, ir_insn *insn)
|
bool ir_is_vararg(const ir_ctx *ctx, ir_insn *insn)
|
||||||
{
|
{
|
||||||
if (IR_IS_CONST_REF(insn->op2)) {
|
const ir_proto_t *proto = ir_call_proto(ctx, insn);
|
||||||
const ir_insn *func = &ctx->ir_base[insn->op2];
|
|
||||||
|
|
||||||
if (func->op == IR_FUNC || func->op == IR_FUNC_ADDR) {
|
|
||||||
if (func->proto) {
|
|
||||||
const ir_proto_t *proto = (const ir_proto_t *)ir_get_str(ctx, func->proto);
|
|
||||||
|
|
||||||
return (proto->flags & IR_VARARG_FUNC) != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (ctx->ir_base[insn->op2].op == IR_PROTO) {
|
|
||||||
const ir_proto_t *proto = (const ir_proto_t *)ir_get_str(ctx, ctx->ir_base[insn->op2].op2);
|
|
||||||
|
|
||||||
|
if (proto) {
|
||||||
return (proto->flags & IR_VARARG_FUNC) != 0;
|
return (proto->flags & IR_VARARG_FUNC) != 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user