summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Ayers <andya@microsoft.com>2019-06-24 11:19:58 -0700
committerJan Kotas <jkotas@microsoft.com>2019-06-24 11:19:58 -0700
commitbad8d915c267057bf74cb819c9e027d68cd1fa35 (patch)
tree0e4ce8df894b0b2e303539da9f2a374bcef4840b
parent6c9deb470b1d4f704127979552a94126285e02d7 (diff)
downloadcoreclr-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.cpp24
-rw-r--r--src/jit/emit.cpp5
-rw-r--r--src/jit/emitxarch.cpp2
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;