2222#include "jit/ir/ir_builder.h"
2323#include "jit/tls/zend_jit_tls.h"
2424
25+ #if ZEND_VM_KIND == ZEND_VM_KIND_CALL && defined(HAVE_PRESERVE_NONE) && defined(_WIN32)
26+ # define IR_OPCODE_HANDLER_CC IR_CC_PRESERVE_NONE
27+ #else
28+ # define IR_OPCODE_HANDLER_CC IR_FASTCALL_FUNC
29+ #endif
30+
31+ /* Whether args arrive directly in ZREG registers (don't need IR_PARAM) */
32+ #define ZEND_JIT_ARGS_IN_ZREG (ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL || IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC)
33+
2534#if defined(IR_TARGET_X86)
2635# define IR_REG_SP 4 /* IR_REG_RSP */
2736# define IR_REG_FP 5 /* IR_REG_RBP */
4049 * https://github.com/llvm/llvm-project/blob/68bfe91b5a34f80dbcc4f0a7fa5d7aa1cdf959c2/llvm/lib/Target/X86/X86CallingConv.td#L1029 */
4150# define ZREG_FP 12 /* IR_REG_R12 */
4251# define ZREG_IP 13 /* IR_REG_R13 */
52+ # elif IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC
53+ # define ZREG_FP 13 /* IR_REG_R13 = MSVC preserve_none arg1 */
54+ # define ZREG_IP 14 /* IR_REG_R14 = MSVC preserve_none arg2 */
4355# else
4456# define ZREG_FP 14 /* IR_REG_R14 */
4557# define ZREG_IP 15 /* IR_REG_R15 */
99111# define ir_CONST_OPCODE_HANDLER_FUNC(_addr) \
100112 jit_CONST_OPCODE_HANDLER_FUNC(jit, _addr)
101113# define ir_CAST_OPCODE_HANDLER_FUNC(_addr) ir_fold2(_ir_CTX, IR_OPT(IR_PROTO, IR_ADDR), (_addr), \
102- ir_proto_0(_ir_CTX, IR_FASTCALL_FUNC , IR_OPCODE_HANDLER_RET))
114+ ir_proto_0(_ir_CTX, IR_OPCODE_HANDLER_CC , IR_OPCODE_HANDLER_RET))
103115
104116#define ir_CONST_FUNC_PROTO(_addr, _proto) \
105117 jit_CONST_FUNC_PROTO(jit, (uintptr_t)(_addr), (_proto))
@@ -573,15 +585,15 @@ static ir_ref jit_CONST_FUNC(zend_jit_ctx *jit, uintptr_t addr, uint16_t flags)
573585 /* TODO: dummy prototype (only flags matter) ??? */
574586 ir_ref proto = flags ? ir_proto_0(&jit->ctx, flags, IR_I32) : 0;
575587#else
576- ir_ref proto = 0;
588+ ir_ref proto = (flags == IR_CC_PRESERVE_NONE) ? ir_proto_0(&jit->ctx, flags, IR_ADDR) : 0;
577589#endif
578590
579591 return jit_CONST_FUNC_PROTO(jit, addr, proto);
580592}
581593
582594static ir_ref jit_CONST_OPCODE_HANDLER_FUNC(zend_jit_ctx *jit, zend_vm_opcode_handler_t handler)
583595{
584- return jit_CONST_FUNC(jit, (uintptr_t)handler, IR_FASTCALL_FUNC );
596+ return jit_CONST_FUNC(jit, (uintptr_t)handler, IR_OPCODE_HANDLER_CC );
585597}
586598
587599static ir_ref jit_ADD_OFFSET(zend_jit_ctx *jit, ir_ref addr, uintptr_t offset)
@@ -1958,15 +1970,19 @@ static void zend_jit_vm_leave(zend_jit_ctx *jit, ir_ref to_opline)
19581970
19591971static void zend_jit_tailcall_handler(zend_jit_ctx *jit, ir_ref handler)
19601972{
1961- #if defined(IR_TARGET_X86)
1973+ #if defined(IR_TARGET_X86) || IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC
19621974 if (!IR_IS_CONST_REF(handler)) {
19631975 handler = ir_CAST_OPCODE_HANDLER_FUNC(handler);
19641976 }
19651977#endif
19661978 if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) {
19671979 ir_TAILCALL(IR_OPCODE_HANDLER_RET, handler);
19681980 } else {
1981+ #if IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC
1982+ ir_RETURN(ir_CALL_2(IR_ADDR, handler, jit_FP(jit), jit_IP(jit)));
1983+ #else
19691984 ir_TAILCALL_2(IR_ADDR, handler, jit_FP(jit), jit_IP(jit));
1985+ #endif
19701986 }
19711987}
19721988
@@ -2535,7 +2551,7 @@ static int zend_jit_trace_exit_stub(zend_jit_ctx *jit)
25352551 if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) {
25362552 zend_jit_tailcall_handler(jit, addr);
25372553 } else {
2538- #if defined(IR_TARGET_X86)
2554+ #if defined(IR_TARGET_X86) || IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC
25392555 addr = ir_CAST_OPCODE_HANDLER_FUNC(addr);
25402556#endif
25412557 ref = ir_CALL_2(IR_ADDR, addr, jit_FP(jit), jit_IP(jit));
@@ -3229,7 +3245,7 @@ static void zend_jit_calc_trace_prologue_size(void)
32293245 zend_jit_init_ctx(jit, (ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) ? 0 : IR_START_BR_TARGET);
32303246
32313247 if (!GCC_GLOBAL_REGS) {
3232- if (ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL ) {
3248+ if (!ZEND_JIT_ARGS_IN_ZREG ) {
32333249 ir_ref execute_data_ref = ir_PARAM(IR_ADDR, "execute_data", 1);
32343250 ir_ref opline_ref = ir_PARAM(IR_ADDR, "opline", 2);
32353251 jit_STORE_FP(jit, execute_data_ref);
@@ -4066,7 +4082,7 @@ static void zend_jit_recv_entry(zend_jit_ctx *jit, int b)
40664082
40674083 /* Insert a MERGE block with additional ENTRY input between predecessor and this one */
40684084 ir_ENTRY(ref, bb->start);
4069- if (!GCC_GLOBAL_REGS && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL ) {
4085+ if (!GCC_GLOBAL_REGS && !ZEND_JIT_ARGS_IN_ZREG ) {
40704086 /* 2 and 3 are hardcoded reference to IR_PARAMs */
40714087 ZEND_ASSERT(jit->ctx.ir_base[2].op == IR_PARAM);
40724088 ZEND_ASSERT(jit->ctx.ir_base[2].op3 == 1);
@@ -4087,7 +4103,7 @@ static void zend_jit_osr_entry(zend_jit_ctx *jit, int b)
40874103
40884104 /* Insert a MERGE block with additional ENTRY input between predecessor and this one */
40894105 ir_ENTRY(ref, bb->start);
4090- if (!GCC_GLOBAL_REGS && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL ) {
4106+ if (!GCC_GLOBAL_REGS && !ZEND_JIT_ARGS_IN_ZREG ) {
40914107 /* 2 and 3 are hardcoded reference to IR_PARAMs */
40924108 ZEND_ASSERT(jit->ctx.ir_base[2].op == IR_PARAM);
40934109 ZEND_ASSERT(jit->ctx.ir_base[2].op3 == 1);
@@ -4103,7 +4119,7 @@ static void zend_jit_osr_entry(zend_jit_ctx *jit, int b)
41034119static ir_ref zend_jit_continue_entry(zend_jit_ctx *jit, ir_ref src, unsigned int label)
41044120{
41054121 ir_ENTRY(src, label);
4106- if (!GCC_GLOBAL_REGS && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL ) {
4122+ if (!GCC_GLOBAL_REGS && !ZEND_JIT_ARGS_IN_ZREG ) {
41074123 /* 2 and 3 are hardcoded reference to IR_PARAMs */
41084124 ZEND_ASSERT(jit->ctx.ir_base[2].op == IR_PARAM);
41094125 ZEND_ASSERT(jit->ctx.ir_base[2].op3 == 1);
@@ -4127,7 +4143,13 @@ static int zend_jit_handler(zend_jit_ctx *jit, const zend_op *opline, int may_th
41274143 jit_STORE_IP(jit, ip);
41284144 } else {
41294145 zend_vm_opcode_handler_t handler = opline->handler;
4130- ir_ref ip = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit));
4146+ #if IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC
4147+ ir_STORE(jit_EG(current_execute_data), jit_FP(jit));
4148+ #endif
4149+ ir_ref ip = ir_CALL_2(IR_ADDR, ir_CONST_OPCODE_HANDLER_FUNC(handler), jit_FP(jit), jit_IP(jit));
4150+ #if IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC
4151+ jit_STORE_FP(jit, ir_LOAD_A(jit_EG(current_execute_data)));
4152+ #endif
41314153 jit_STORE_IP(jit, ip);
41324154 }
41334155 if (may_throw) {
@@ -4151,6 +4173,9 @@ static int zend_jit_handler(zend_jit_ctx *jit, const zend_op *opline, int may_th
41514173 zend_jit_set_last_valid_opline(jit, opline + 1);
41524174 break;
41534175 }
4176+ #if IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC
4177+ zend_jit_reset_last_valid_opline(jit);
4178+ #endif
41544179 return 1;
41554180}
41564181
@@ -4189,7 +4214,11 @@ static int zend_jit_tail_handler(zend_jit_ctx *jit, const zend_op *opline)
41894214 ir_ref ip = ir_CALL_2(IR_ADDR, ir_CONST_OPCODE_HANDLER_FUNC(handler), jit_FP(jit), jit_IP(jit));
41904215 zend_jit_vm_enter(jit, ip);
41914216 } else {
4217+ #if IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC
4218+ ir_RETURN(ir_CALL_2(IR_ADDR, ir_CONST_OPCODE_HANDLER_FUNC(handler), jit_FP(jit), jit_IP(jit)));
4219+ #else
41924220 ir_TAILCALL_2(IR_ADDR, ir_CONST_OPCODE_HANDLER_FUNC(handler), jit_FP(jit), jit_IP(jit));
4221+ #endif
41934222 }
41944223 }
41954224 if (jit->b >= 0) {
@@ -7983,8 +8012,13 @@ static int zend_jit_escape_if_undef(zend_jit_ctx *jit, int var, uint32_t flags,
79838012 } else {
79848013#if defined(IR_TARGET_X86)
79858014 ref = ir_CAST_FC_FUNC(ref);
7986- #endif
79878015 ir_TAILCALL_2(IR_ADDR, ref, jit_FP(jit), jit_IP(jit));
8016+ #elif IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC
8017+ ref = ir_CAST_OPCODE_HANDLER_FUNC(ref);
8018+ ir_RETURN(ir_CALL_2(IR_ADDR, ref, jit_FP(jit), jit_IP(jit)));
8019+ #else
8020+ ir_TAILCALL_2(IR_ADDR, ref, jit_FP(jit), jit_IP(jit));
8021+ #endif
79888022 }
79898023
79908024 ir_IF_TRUE(if_def);
@@ -16719,7 +16753,7 @@ static int zend_jit_start(zend_jit_ctx *jit, const zend_op_array *op_array, zend
1671916753 jit->bb_edges = zend_arena_calloc(&CG(arena), count, sizeof(ir_ref));
1672016754
1672116755 if (!GCC_GLOBAL_REGS) {
16722- if (ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL ) {
16756+ if (!ZEND_JIT_ARGS_IN_ZREG ) {
1672316757 ir_ref execute_data_ref = ir_PARAM(IR_ADDR, "execute_data", 1);
1672416758 ir_ref opline_ref = ir_PARAM(IR_ADDR, "opline", 2);
1672516759 jit_STORE_FP(jit, execute_data_ref);
@@ -17107,7 +17141,13 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_arr
1710717141 if (GCC_GLOBAL_REGS) {
1710817142 ir_CALL(IR_VOID, ir_CONST_FUNC(handler));
1710917143 } else {
17110- ref = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit));
17144+ #if IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC
17145+ ir_STORE(jit_EG(current_execute_data), jit_FP(jit));
17146+ #endif
17147+ ref = ir_CALL_2(IR_ADDR, ir_CONST_OPCODE_HANDLER_FUNC((zend_vm_opcode_handler_t)handler), jit_FP(jit), jit_IP(jit));
17148+ #if IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC
17149+ jit_STORE_FP(jit, ir_LOAD_A(jit_EG(current_execute_data)));
17150+ #endif
1711117151 if (opline->opcode == ZEND_RETURN ||
1711217152 opline->opcode == ZEND_RETURN_BY_REF ||
1711317153 opline->opcode == ZEND_DO_UCALL ||
@@ -17120,6 +17160,9 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_arr
1712017160 } else {
1712117161 jit_STORE_IP(jit, ref);
1712217162 }
17163+ #if IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC
17164+ zend_jit_reset_last_valid_opline(jit);
17165+ #endif
1712317166 }
1712417167 if (may_throw
1712517168 && opline->opcode != ZEND_RETURN
@@ -17301,7 +17344,7 @@ static int zend_jit_trace_start(zend_jit_ctx *jit,
1730117344
1730217345 if (!GCC_GLOBAL_REGS) {
1730317346 if (!parent) {
17304- if (ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL ) {
17347+ if (!ZEND_JIT_ARGS_IN_ZREG ) {
1730517348 ir_ref execute_data_ref = ir_PARAM(IR_ADDR, "execute_data", 1);
1730617349 ir_ref opline_ref = ir_PARAM(IR_ADDR, "opline", 2);
1730717350 jit_STORE_FP(jit, execute_data_ref);
@@ -17422,6 +17465,8 @@ static int zend_jit_trace_return(zend_jit_ctx *jit, bool original_handler, const
1742217465
1742317466#if defined(IR_TARGET_X86)
1742417467 addr = ir_CAST_FC_FUNC(addr);
17468+ #elif IR_OPCODE_HANDLER_CC != IR_FASTCALL_FUNC
17469+ addr = ir_CAST_OPCODE_HANDLER_FUNC(addr);
1742517470#endif
1742617471 ref = ir_CALL_2(IR_ADDR, addr, jit_FP(jit), jit_IP(jit));
1742717472 zend_jit_vm_enter(jit, ref);
0 commit comments