diff options
author | Andy Ayers <andya@microsoft.com> | 2019-06-24 11:19:58 -0700 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2019-06-24 11:19:58 -0700 |
commit | bad8d915c267057bf74cb819c9e027d68cd1fa35 (patch) | |
tree | 0e4ce8df894b0b2e303539da9f2a374bcef4840b | |
parent | 6c9deb470b1d4f704127979552a94126285e02d7 (diff) | |
download | coreclr-bad8d915c267057bf74cb819c9e027d68cd1fa35.tar.gz coreclr-bad8d915c267057bf74cb819c9e027d68cd1fa35.tar.bz2 coreclr-bad8d915c267057bf74cb819c9e027d68cd1fa35.zip |
JIT: see if jmp offset will fit in 32 bit displacement (#25348)
On x86 we can always reach any IAT_PVALUE entry via a 32 bit indirect
jump, and proper handling of jmp epilogs depends on this. So check if the
target address is reachable in 32 bits, and if so, use the jmp [addr] form
on x86, and the jmp [rip + disp] form for x64.
Fixes #25345
Fixes #25346
Undoes the assertion change from #25302
Fixes #25286
-rw-r--r-- | src/jit/codegencommon.cpp | 24 | ||||
-rw-r--r-- | src/jit/emit.cpp | 5 | ||||
-rw-r--r-- | src/jit/emitxarch.cpp | 2 |
3 files changed, 20 insertions, 11 deletions
diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp index 34be5f7de7..8725619ceb 100644 --- a/src/jit/codegencommon.cpp +++ b/src/jit/codegencommon.cpp @@ -8905,20 +8905,30 @@ void CodeGen::genFnEpilog(BasicBlock* block) NO_WAY("Unsupported JMP indirection"); } - // If we have IAT_PVALUE, jump via register indirect, as sometimes the + // If we have IAT_PVALUE we might need to jump via register indirect, as sometimes the // indirection cell can't be reached by the jump. - 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); + if (genCodeIndirAddrCanBeEncodedAsPCRelOffset((size_t)addrInfo.addr)) + { + // 32 bit displacement will work + callType = emitter::EC_FUNC_TOKEN_INDIR; + addr = addrInfo.addr; + indCallReg = REG_NA; + } + else + { + // 32 bit displacement won't work + 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 { diff --git a/src/jit/emit.cpp b/src/jit/emit.cpp index e7c582feb9..6bad19d14e 100644 --- a/src/jit/emit.cpp +++ b/src/jit/emit.cpp @@ -2059,10 +2059,9 @@ void emitter::emitEndFnEpilog() // underestimation of the epilog size is harmless (since the EIP // can not be between instructions). assert(emitEpilogCnt == 1 || - (emitExitSeqSize - newSize) <= 6 // delta between size of various forms of jmp (size is either 6 or 5, - // or a 5 byte mov plus 2 byte jmp) + (emitExitSeqSize - newSize) <= 5 // delta between size of various forms of jmp (size is either 6 or 5), // and various forms of ret (size is either 1 or 3). The combination can - // be anything between 1 and 6. + // be anything between 1 and 5. ); emitExitSeqSize = newSize; } diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp index 1f529ff694..8a6b34b2d4 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_INDIR_ARD); + assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_TOKEN_INDIR || callType == EC_INDIR_ARD); if (callType == EC_FUNC_TOKEN) { ins = INS_l_jmp; |