summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruce Forstall <brucefo@microsoft.com>2018-04-25 20:34:16 (GMT)
committerRuss Keldorph <russ.keldorph@microsoft.com>2018-05-04 20:20:27 (GMT)
commit205406613e11da4eaaca5f7ef584b67d603750ee (patch)
tree0f8801e72240f3b83bb1a78ff2531e06a758a493 /src
parent556228c968eebbb9fce442a4974b2c3771206987 (diff)
downloadcoreclr-205406613e11da4eaaca5f7ef584b67d603750ee.zip
coreclr-205406613e11da4eaaca5f7ef584b67d603750ee.tar.gz
coreclr-205406613e11da4eaaca5f7ef584b67d603750ee.tar.bz2
Fix for ARM secure delegate non-standard register arg
For ARM, doing a secure delegate call requires adding a custom calling convention argument R4 as the address of the secure delegate invoke indirection cell. This is done using the fgMorphArgs nonStandardArgs mechanism, and the argument is added at the end. For calls with 4 or more register arguments, this didn't work: we would initially set the non-standard arg as a non-register argument, and the nonStandardArgs check didn't consider converting an argument from a stack argument back to a register argument. The fix allows nonStandardArgs to be either stack or register arguments, no matter what their place in the argument list would imply. Fixes #17738
Diffstat (limited to 'src')
-rw-r--r--src/jit/morph.cpp28
1 files changed, 19 insertions, 9 deletions
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp
index 866bd8c..2c3c280 100644
--- a/src/jit/morph.cpp
+++ b/src/jit/morph.cpp
@@ -3000,6 +3000,12 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
}
#endif // defined(_TARGET_X86_) || defined(_TARGET_ARM_)
#if defined(_TARGET_ARM_)
+ // A non-standard calling convention using secure delegate invoke is used on ARM, only, but not for secure
+ // delegates. It is used for VSD delegate calls where the VSD custom calling convention ABI requires passing
+ // R4, a callee-saved register, with a special value. Since R4 is a callee-saved register, its value needs
+ // to be preserved. Thus, the VM uses a secure delegate IL stub, which preserves R4 and also sets up R4
+ // correctly for the VSD call. The VM is simply reusing an existing mechanism (secure delegate IL stub)
+ // to achieve its goal for delegate VSD call. See COMDelegate::NeedsWrapperDelegate() in the VM for details.
else if (call->gtCallMoreFlags & GTF_CALL_M_SECURE_DELEGATE_INV)
{
GenTree* arg = call->gtCallObjp;
@@ -3520,6 +3526,8 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
// This size has now been computed
assert(size != 0);
+
+ isNonStandard = argEntry->isNonStandard;
}
else // !reMorphing
{
@@ -4151,9 +4159,9 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
// They should not affect the placement of any other args or stack space required.
// Example: on AMD64 R10 and R11 are used for indirect VSD (generic interface) and cookie calls.
isNonStandard = nonStandardArgs.FindReg(argx, &nonStdRegNum);
- if (isNonStandard && (nonStdRegNum == REG_STK))
+ if (isNonStandard)
{
- isRegArg = false;
+ isRegArg = (nonStdRegNum != REG_STK);
}
#if defined(_TARGET_X86_)
else if (call->IsTailCallViaHelper())
@@ -4209,12 +4217,19 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
if (isRegArg)
{
regNumber nextRegNum = REG_STK;
+
#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
regNumber nextOtherRegNum = REG_STK;
unsigned int structFloatRegs = 0;
unsigned int structIntRegs = 0;
+#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
- if (isStructArg && structDesc.passedInRegisters)
+ if (isNonStandard)
+ {
+ nextRegNum = nonStdRegNum;
+ }
+#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
+ else if (isStructArg && structDesc.passedInRegisters)
{
// It is a struct passed in registers. Assign the next available register.
assert((structDesc.eightByteCount <= 2) && "Too many eightbytes.");
@@ -4233,8 +4248,8 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
}
}
}
- else
#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
+ else
{
// fill in or update the argInfo table
nextRegNum = passUsingFloatRegs ? genMapFloatRegArgNumToRegNum(nextFltArgRegNum)
@@ -4255,11 +4270,6 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
}
else
{
- if (isNonStandard)
- {
- nextRegNum = nonStdRegNum;
- }
-
// This is a register argument - put it in the table
newArgEntry = call->fgArgInfo->AddRegArg(argIndex, argx, args, nextRegNum, size, argAlign
#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)