// a single indirection.
GenTree* cellAddr = AddrGen(addr);
GenTree* indir = Ind(cellAddr);
-
-#ifdef FEATURE_READYTORUN_COMPILER
-#if defined(_TARGET_ARMARCH_)
- // For arm64, we dispatch code same as VSD using X11 for indirection cell address,
- // which ZapIndirectHelperThunk expects.
- if (call->IsR2RRelativeIndir())
- {
- cellAddr->gtRegNum = REG_R2R_INDIRECT_PARAM;
- indir->gtRegNum = REG_JUMP_THUNK_PARAM;
- }
-#endif
-#endif
- result = indir;
+ result = indir;
break;
}
call->gtCallType = CT_HELPER;
call->gtCallMethHnd = eeFindHelper(CORINFO_HELP_PINVOKE_CALLI);
}
-#endif // !defined(LEGACY_BACKEND)
+#if defined(FEATURE_READYTORUN_COMPILER) && defined(_TARGET_ARMARCH_)
+ // For arm, we dispatch code same as VSD using virtualStubParamInfo->GetReg()
+ // for indirection cell address, which ZapIndirectHelperThunk expects.
+ if (call->IsR2RRelativeIndir())
+ {
+ assert(call->gtEntryPoint.addr != nullptr);
+
+ size_t addrValue = (size_t)call->gtEntryPoint.addr;
+ GenTree* indirectCellAddress = gtNewIconHandleNode(addrValue, GTF_ICON_FTN_ADDR);
+ indirectCellAddress->gtRegNum = REG_R2R_INDIRECT_PARAM;
+
+ // Push the stub address onto the list of arguments.
+ call->gtCallArgs = gtNewListNode(indirectCellAddress, call->gtCallArgs);
+
+ numArgs++;
+ nonStandardArgs.Add(indirectCellAddress, indirectCellAddress->gtRegNum);
+ }
+
+#endif // FEATURE_READYTORUN_COMPILER && _TARGET_ARMARCH_
+#endif // !LEGACY_BACKEND
// Allocate the fgArgInfo for the call node;
//
assert(JITtype2varType(sig.retType) == tree->gtType);
#endif // DEBUG
- call = comp->fgMorphArgs(call);
- // Determine if this call has changed any codegen requirements.
- comp->fgCheckArgCnt();
-
#ifdef FEATURE_READYTORUN_COMPILER
call->gtCall.setEntryPoint(entryPoint);
#endif
+ call = comp->fgMorphArgs(call);
+ // Determine if this call has changed any codegen requirements.
+ comp->fgCheckArgCnt();
+
// Replace "tree" with "call"
if (parents.Height() > 1)
{
vnpUniq.SetBoth(vnStore->VNForExpr(compCurBB, call->TypeGet()));
}
+#if defined(FEATURE_READYTORUN_COMPILER) && defined(_TARGET_ARMARCH_)
+ if (call->IsR2RRelativeIndir())
+ {
+#ifdef DEBUG
+ assert(args->Current()->OperGet() == GT_ARGPLACE);
+
+ // Find the corresponding late arg.
+ GenTree* indirectCellAddress = call->fgArgInfo->GetLateArg(0);
+ assert(indirectCellAddress->IsCnsIntOrI() && indirectCellAddress->gtRegNum == REG_R2R_INDIRECT_PARAM);
+#endif // DEBUG
+ // For ARM indirectCellAddress is consumed by the call itself, so it should have added as an implicit argument
+ // in morph. So we do not need to use EntryPointAddrAsArg0, because arg0 is already an entry point addr.
+ useEntryPointAddrAsArg0 = false;
+ }
+#endif // FEATURE_READYTORUN_COMPILER && _TARGET_ARMARCH_
+
if (nArgs == 0)
{
if (generateUniqueVN)
vnp0 = ValueNumPair(callAddrVN, callAddrVN);
}
else
-#endif
+#endif // FEATURE_READYTORUN_COMPILER
{
assert(!useEntryPointAddrAsArg0);
ValueNumPair vnp0wx = getCurrentArg(0)->gtVNPair;