From 47cac5561059d4f76885d013b05ef8857aac2825 Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Tue, 7 Aug 2018 13:49:03 -0700 Subject: [PATCH] Add support to use an indirected address for JMP instructions to ARM64 (dotnet/coreclr#19281) * Add support to use an indirected address for JMP instructions to ARM64 - Merge logic between ARM and ARM64 Commit migrated from https://github.com/dotnet/coreclr/commit/fde763073fcce978141bf0b31e4479df507acfb8 --- src/coreclr/src/jit/codegencommon.cpp | 39 +++++++---------------------------- src/coreclr/src/jit/instr.cpp | 11 ++++++++++ src/coreclr/src/jit/lowerarmarch.cpp | 8 ------- src/coreclr/src/jit/target.h | 6 ++++++ 4 files changed, 24 insertions(+), 40 deletions(-) diff --git a/src/coreclr/src/jit/codegencommon.cpp b/src/coreclr/src/jit/codegencommon.cpp index 4968990..0f6beec 100644 --- a/src/coreclr/src/jit/codegencommon.cpp +++ b/src/coreclr/src/jit/codegencommon.cpp @@ -8730,14 +8730,14 @@ void CodeGen::genFnEpilog(BasicBlock* block) assert(methHnd != nullptr); assert(addrInfo.addr != nullptr); -#ifdef _TARGET_ARM_ +#ifdef _TARGET_ARMARCH_ emitter::EmitCallType callType; void* addr; regNumber indCallReg; switch (addrInfo.accessType) { case IAT_VALUE: - if (arm_Valid_Imm_For_BL((ssize_t)addrInfo.addr)) + if (validImmForBL((ssize_t)addrInfo.addr)) { // Simple direct call callType = emitter::EC_FUNC_TOKEN; @@ -8754,7 +8754,7 @@ void CodeGen::genFnEpilog(BasicBlock* block) // Load the address into a register, load indirect and call through a register // We have to use R12 since we assume the argument registers are in use callType = emitter::EC_INDIR_R; - indCallReg = REG_R12; + indCallReg = REG_INDIRECT_CALL_TARGET_REG; addr = NULL; instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, indCallReg, (ssize_t)addrInfo.addr); if (addrInfo.accessType == IAT_PVALUE) @@ -8794,6 +8794,9 @@ void CodeGen::genFnEpilog(BasicBlock* block) addr, 0, // argSize EA_UNKNOWN, // retSize +#if defined(_TARGET_ARM64_) + EA_UNKNOWN, // secondRetSize +#endif gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur, @@ -8805,35 +8808,7 @@ void CodeGen::genFnEpilog(BasicBlock* block) true); // isJump // clang-format on CLANG_FORMAT_COMMENT_ANCHOR; - -#else // _TARGET_ARM64_ - if (addrInfo.accessType != IAT_VALUE) - { - NYI_ARM64("Unsupported JMP indirection"); - } - - emitter::EmitCallType callType = emitter::EC_FUNC_TOKEN; - - // Simply emit a jump to the methodHnd. This is similar to a call so we can use - // the same descriptor with some minor adjustments. - - // clang-format off - getEmitter()->emitIns_Call(callType, - methHnd, - INDEBUG_LDISASM_COMMA(nullptr) - addrInfo.addr, - 0, // argSize - EA_UNKNOWN, // retSize - EA_UNKNOWN, // secondRetSize - gcInfo.gcVarPtrSetCur, - gcInfo.gcRegGCrefSetCur, - gcInfo.gcRegByrefSetCur, - BAD_IL_OFFSET, REG_NA, REG_NA, 0, 0, /* iloffset, ireg, xreg, xmul, disp */ - true); /* isJump */ - // clang-format on - CLANG_FORMAT_COMMENT_ANCHOR; - -#endif // _TARGET_ARM64_ +#endif //_TARGET_ARMARCH_ } #if FEATURE_FASTTAILCALL else diff --git a/src/coreclr/src/jit/instr.cpp b/src/coreclr/src/jit/instr.cpp index 057cb00..68d2355 100644 --- a/src/coreclr/src/jit/instr.cpp +++ b/src/coreclr/src/jit/instr.cpp @@ -1333,6 +1333,17 @@ bool CodeGen::ins_Writes_Dest(instruction ins) } #endif // _TARGET_ARM_ +#if defined(_TARGET_ARM64_) +bool CodeGenInterface::validImmForBL(ssize_t addr) +{ + // On arm64, we always assume a call target is in range and generate a 28-bit relative + // 'bl' instruction. If this isn't sufficient range, the VM will generate a jump stub when + // we call recordRelocation(). See the IMAGE_REL_ARM64_BRANCH26 case in jitinterface.cpp + // (for JIT) or zapinfo.cpp (for NGEN). If we cannot allocate a jump stub, it is fatal. + return true; +} +#endif // _TARGET_ARM64_ + /***************************************************************************** * * Get the machine dependent instruction for performing sign/zero extension. diff --git a/src/coreclr/src/jit/lowerarmarch.cpp b/src/coreclr/src/jit/lowerarmarch.cpp index d89ae14..400776b 100644 --- a/src/coreclr/src/jit/lowerarmarch.cpp +++ b/src/coreclr/src/jit/lowerarmarch.cpp @@ -39,15 +39,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // bool Lowering::IsCallTargetInRange(void* addr) { -#ifdef _TARGET_ARM64_ - // On arm64, we always assume a call target is in range and generate a 28-bit relative - // 'bl' instruction. If this isn't sufficient range, the VM will generate a jump stub when - // we call recordRelocation(). See the IMAGE_REL_ARM64_BRANCH26 case in jitinterface.cpp - // (for JIT) or zapinfo.cpp (for NGEN). If we cannot allocate a jump stub, it is fatal. - return true; -#elif defined(_TARGET_ARM_) return comp->codeGen->validImmForBL((ssize_t)addr); -#endif } //------------------------------------------------------------------------ diff --git a/src/coreclr/src/jit/target.h b/src/coreclr/src/jit/target.h index c9437f9..0d92e65 100644 --- a/src/coreclr/src/jit/target.h +++ b/src/coreclr/src/jit/target.h @@ -1089,6 +1089,9 @@ typedef unsigned char regNumberSmall; #define REG_R2R_INDIRECT_PARAM REG_R4 #define RBM_R2R_INDIRECT_PARAM RBM_R4 + // JMP Indirect call register + #define REG_INDIRECT_CALL_TARGET_REG REG_R12 + // Registers used by PInvoke frame setup #define REG_PINVOKE_FRAME REG_R4 #define RBM_PINVOKE_FRAME RBM_R4 @@ -1402,6 +1405,9 @@ typedef unsigned char regNumberSmall; #define REG_R2R_INDIRECT_PARAM REG_R11 #define RBM_R2R_INDIRECT_PARAM RBM_R11 + // JMP Indirect call register + #define REG_INDIRECT_CALL_TARGET_REG REG_IP0 + // Registers used by PInvoke frame setup #define REG_PINVOKE_FRAME REG_R9 #define RBM_PINVOKE_FRAME RBM_R9 -- 2.7.4