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 fp_reg_params_count = IR_REG_FP_ARGS;
|
||||
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;
|
||||
for (j = 3; j <= n; j++) {
|
||||
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 (int_param >= int_reg_params_count) {
|
||||
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
|
||||
* and collect arguments that should be passed through registers */
|
||||
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);
|
||||
arg_insn = &ctx->ir_base[arg];
|
||||
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 (int_param < int_reg_params_count) {
|
||||
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);
|
||||
arg_insn = &ctx->ir_base[arg];
|
||||
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 (int_param < int_reg_params_count) {
|
||||
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;
|
||||
#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
|
||||
static const int8_t _ir_int_fc_reg_params[IR_REG_INT_FCARGS];
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
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);
|
||||
const ir_proto_t *proto = ir_call_proto(ctx, insn);
|
||||
|
||||
if (proto) {
|
||||
return (proto->flags & IR_VARARG_FUNC) != 0;
|
||||
}
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user