@@ -2118,7 +2118,8 @@ void HIRBuilder::emitCallEx(
21182118 CallFlags flags) {
21192119 Register* dst = temps_.AllocateStack ();
21202120 OperandStack& stack = tc.frame .stack ;
2121- bool has_kwargs = bc_instr.oparg () & 0x1 ;
2121+ // In 3.14+ we always have kwargs on the stack but it may be null.
2122+ bool has_kwargs = (PY_VERSION_HEX >= 0x030E0000 ) || bc_instr.oparg () & 0x1 ;
21222123 Register* kwargs = nullptr ;
21232124 if (has_kwargs) {
21242125 kwargs = stack.pop ();
@@ -2129,17 +2130,18 @@ void HIRBuilder::emitCallEx(
21292130 kwargs = nullp;
21302131 }
21312132 Register* pargs = stack.pop ();
2132- Register* func = stack.pop ();
2133- #if PY_VERSION_HEX >= 0x030D0000
2134- JIT_ABORT (" Unused stack slot in CALL_FUNCTION_EX needs reviewing" );
2135- #endif
2136- #if PY_VERSION_HEX >= 0x030C0000
2137- // This isn't obviously explained by code, docs, or comments but
2138- // CALL_FUNCTION_EX in 3.12 has an "unused" value on the stack.
2139- // I guess this had something to do with simplifying the bytecode
2140- // compiler? This has already changed in upstream main.
2141- stack.pop ();
2142- #endif
2133+ Register* func;
2134+ // CALL_FUNCTION_EX has an unused value on the stack, starting with 3.12.
2135+ // In 3.14 this swapped location.
2136+ if constexpr (PY_VERSION_HEX >= 0x030E0000 ) {
2137+ stack.pop ();
2138+ func = stack.pop ();
2139+ } else if constexpr (PY_VERSION_HEX >= 0x030C0000 ) {
2140+ func = stack.pop ();
2141+ stack.pop ();
2142+ } else {
2143+ func = stack.pop ();
2144+ }
21432145 tc.emit <CallEx>(dst, func, pargs, kwargs, flags, tc.frame );
21442146 stack.push (dst);
21452147}
@@ -3431,7 +3433,7 @@ void HIRBuilder::emitLoadGlobal(
34313433 int name_idx = loadGlobalIndex (bc_instr.oparg ());
34323434 Register* result = temps_.AllocateStack ();
34333435
3434- if constexpr (PY_VERSION_HEX >= 0x030B0000 ) {
3436+ if constexpr (PY_VERSION_HEX >= 0x030B0000 && PY_VERSION_HEX < 0x030E0000 ) {
34353437 if (bc_instr.oparg () & 1 ) {
34363438 emitPushNull (tc);
34373439 }
@@ -3458,6 +3460,12 @@ void HIRBuilder::emitLoadGlobal(
34583460 }
34593461
34603462 tc.frame .stack .push (result);
3463+
3464+ if constexpr (PY_VERSION_HEX >= 0x030E0000 ) {
3465+ if (bc_instr.oparg () & 1 ) {
3466+ emitPushNull (tc);
3467+ }
3468+ }
34613469}
34623470
34633471void HIRBuilder::emitMakeFunction (
@@ -4623,8 +4631,25 @@ void HIRBuilder::emitDictMerge(
46234631 TranslationContext& tc,
46244632 const BytecodeInstruction& bc_instr) {
46254633 auto & stack = tc.frame .stack ;
4626- Register* dict = stack.top (bc_instr.oparg ());
4627- Register* func = stack.top (bc_instr.oparg () + 2 );
4634+ Register *dict, *func;
4635+ if constexpr (PY_VERSION_HEX < 0x030E0000 ) {
4636+ dict = stack.top (bc_instr.oparg ());
4637+ func = stack.top (bc_instr.oparg () + 2 );
4638+ } else {
4639+ // According to bytecodes.c, at this point on the stack we have:
4640+ // update (top of the stack)
4641+ // [unused if oparg is 0]
4642+ // dict
4643+ // unused
4644+ // unused
4645+ // callable
4646+ // Looking at codegen.c for 3.14, oparg is only ever 1 so the optional
4647+ // "unused" slot is never present. So the 1 and 4 offsets skip to "dict" and
4648+ // "callable" respectively.
4649+ JIT_CHECK (bc_instr.oparg () == 1 , " oparg must be 1" );
4650+ dict = stack.top (1 );
4651+ func = stack.top (4 );
4652+ }
46284653 Register* update = stack.pop ();
46294654 Register* out = temps_.AllocateStack ();
46304655 tc.emit <DictMerge>(out, dict, update, func, tc.frame );
0 commit comments