Add support to use an indirected address for JMP instructions to ARM64 (#19281)
authorDavid Wrighton <davidwr@microsoft.com>
Tue, 7 Aug 2018 20:49:03 +0000 (13:49 -0700)
committerGitHub <noreply@github.com>
Tue, 7 Aug 2018 20:49:03 +0000 (13:49 -0700)
* Add support to use an indirected address for JMP instructions to ARM64
- Merge logic between ARM and ARM64

src/jit/codegencommon.cpp
src/jit/instr.cpp
src/jit/lowerarmarch.cpp
src/jit/target.h

index 4968990..0f6beec 100644 (file)
@@ -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
index 057cb00..68d2355 100644 (file)
@@ -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.
index d89ae14..400776b 100644 (file)
@@ -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
 }
 
 //------------------------------------------------------------------------
index c9437f9..0d92e65 100644 (file)
@@ -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