summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Forstall <brucefo@microsoft.com>2018-04-25 13:34:16 -0700
committerBruce Forstall <brucefo@microsoft.com>2018-05-01 16:35:44 -0700
commita92432048d8cc6fe1a9c4e773d5165dc1d4de55a (patch)
tree33eb140159041d00732ae822ebf3814523ee557c
parentfc36988f5417dc600bce75a530e4c9297ec589b2 (diff)
downloadcoreclr-a92432048d8cc6fe1a9c4e773d5165dc1d4de55a.tar.gz
coreclr-a92432048d8cc6fe1a9c4e773d5165dc1d4de55a.tar.bz2
coreclr-a92432048d8cc6fe1a9c4e773d5165dc1d4de55a.zip
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
-rw-r--r--src/jit/morph.cpp28
-rw-r--r--tests/arm/corefx_linux_test_exclusions.txt2
2 files changed, 20 insertions, 10 deletions
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp
index 7f3ea3ff68..4514bcd6a6 100644
--- a/src/jit/morph.cpp
+++ b/src/jit/morph.cpp
@@ -2999,6 +2999,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;
@@ -3519,6 +3525,8 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
// This size has now been computed
assert(size != 0);
+
+ isNonStandard = argEntry->isNonStandard;
}
else // !reMorphing
{
@@ -4148,9 +4156,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())
@@ -4206,12 +4214,19 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
if (isRegArg)
{
regNumber nextRegNum = REG_STK;
+
#if defined(UNIX_AMD64_ABI)
regNumber nextOtherRegNum = REG_STK;
unsigned int structFloatRegs = 0;
unsigned int structIntRegs = 0;
+#endif // defined(UNIX_AMD64_ABI)
- if (isStructArg && structDesc.passedInRegisters)
+ if (isNonStandard)
+ {
+ nextRegNum = nonStdRegNum;
+ }
+#if defined(UNIX_AMD64_ABI)
+ else if (isStructArg && structDesc.passedInRegisters)
{
// It is a struct passed in registers. Assign the next available register.
assert((structDesc.eightByteCount <= 2) && "Too many eightbytes.");
@@ -4230,8 +4245,8 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
}
}
}
- else
#endif // defined(UNIX_AMD64_ABI)
+ else
{
// fill in or update the argInfo table
nextRegNum = passUsingFloatRegs ? genMapFloatRegArgNumToRegNum(nextFltArgRegNum)
@@ -4252,11 +4267,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(UNIX_AMD64_ABI)
diff --git a/tests/arm/corefx_linux_test_exclusions.txt b/tests/arm/corefx_linux_test_exclusions.txt
index 99dd0a0dd1..ed84e9615c 100644
--- a/tests/arm/corefx_linux_test_exclusions.txt
+++ b/tests/arm/corefx_linux_test_exclusions.txt
@@ -5,7 +5,7 @@ System.Diagnostics.StackTrace.Tests # https://github.com/dotnet/coreclr/issues/
System.Drawing.Common.Tests # https://github.com/dotnet/coreclr/issues/16001
System.IO.FileSystem.Tests # https://github.com/dotnet/coreclr/issues/16001
System.IO.Ports.Tests # https://github.com/dotnet/coreclr/issues/16001
-System.Linq.Expressions.Tests # https://github.com/dotnet/coreclr/issues/17738
+System.Linq.Expressions.Tests # https://github.com/dotnet/corefx/issues/29421 -- timeout
System.Management.Tests # https://github.com/dotnet/coreclr/issues/16001
System.Net.Http.Functional.Tests # https://github.com/dotnet/coreclr/issues/17739
System.Net.NameResolution.Pal.Tests # https://github.com/dotnet/coreclr/issues/17740