diff options
-rw-r--r-- | src/jit/codegencommon.cpp | 28 | ||||
-rw-r--r-- | src/jit/emitxarch.cpp | 8 |
2 files changed, 26 insertions, 10 deletions
diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp index bb81361d9b..34be5f7de7 100644 --- a/src/jit/codegencommon.cpp +++ b/src/jit/codegencommon.cpp @@ -8905,24 +8905,40 @@ void CodeGen::genFnEpilog(BasicBlock* block) NO_WAY("Unsupported JMP indirection"); } - const emitter::EmitCallType callType = - (addrInfo.accessType == IAT_VALUE) ? emitter::EC_FUNC_TOKEN : emitter::EC_FUNC_TOKEN_INDIR; + // If we have IAT_PVALUE, jump via register indirect, as sometimes the + // indirection cell can't be reached by the jump. - // Simply emit a jump to the methodHnd. This is similar to a call so we can use - // the same descriptor with some minor adjustments. + emitter::EmitCallType callType; + void* addr; + regNumber indCallReg; + + if (addrInfo.accessType == IAT_PVALUE) + { + callType = emitter::EC_INDIR_ARD; + indCallReg = REG_RAX; + addr = nullptr; + instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, indCallReg, (ssize_t)addrInfo.addr); + regSet.verifyRegUsed(indCallReg); + } + else + { + callType = emitter::EC_FUNC_TOKEN; + addr = addrInfo.addr; + indCallReg = REG_NA; + } // clang-format off getEmitter()->emitIns_Call(callType, methHnd, INDEBUG_LDISASM_COMMA(nullptr) - addrInfo.addr, + addr, 0, // argSize EA_UNKNOWN // retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(EA_UNKNOWN), // secondRetSize gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur, - BAD_IL_OFFSET, REG_NA, REG_NA, 0, 0, /* iloffset, ireg, xreg, xmul, disp */ + BAD_IL_OFFSET, indCallReg, REG_NA, 0, 0, /* iloffset, ireg, xreg, xmul, disp */ true /* isJump */ ); // clang-format on diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp index 157a57e432..1f529ff694 100644 --- a/src/jit/emitxarch.cpp +++ b/src/jit/emitxarch.cpp @@ -7057,7 +7057,7 @@ void emitter::emitIns_Call(EmitCallType callType, if (isJump) { - assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_TOKEN_INDIR); + assert(callType == EC_FUNC_TOKEN || callType == EC_INDIR_ARD); if (callType == EC_FUNC_TOKEN) { ins = INS_l_jmp; @@ -7853,9 +7853,9 @@ void emitter::emitDispAddrMode(instrDesc* id, bool noDetail) printf("reloc "); } printf("J_M%03u_DS%02u", Compiler::s_compMethodsCount, id->idDebugOnlyInfo()->idMemCookie); - } - disp -= id->idDebugOnlyInfo()->idMemCookie; + disp -= id->idDebugOnlyInfo()->idMemCookie; + } } bool frameRef = false; @@ -8351,7 +8351,7 @@ void emitter::emitDispIns( emitDispAddrMode(id, isNew); emitDispShift(ins); - if (ins == INS_call) + if ((ins == INS_call) || (ins == INS_i_jmp)) { assert(id->idInsFmt() == IF_ARD); |