diff --git a/ir_aarch64.dasc b/ir_aarch64.dasc index e5b17c6..4533d71 100644 --- a/ir_aarch64.dasc +++ b/ir_aarch64.dasc @@ -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]; diff --git a/ir_emit.c b/ir_emit.c index d4e3ad0..40ddf10 100644 --- a/ir_emit.c +++ b/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;