summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Forstall <brucefo@microsoft.com>2018-04-25 13:34:16 -0700
committerRuss Keldorph <russ.keldorph@microsoft.com>2018-05-04 13:20:27 -0700
commit205406613e11da4eaaca5f7ef584b67d603750ee (patch)
tree0f8801e72240f3b83bb1a78ff2531e06a758a493
parent556228c968eebbb9fce442a4974b2c3771206987 (diff)
downloadcoreclr-205406613e11da4eaaca5f7ef584b67d603750ee.tar.gz
coreclr-205406613e11da4eaaca5f7ef584b67d603750ee.tar.bz2
coreclr-205406613e11da4eaaca5f7ef584b67d603750ee.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.txt15
2 files changed, 34 insertions, 9 deletions
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp
index 866bd8c7b2..2c3c280a11 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)
diff --git a/tests/arm/corefx_linux_test_exclusions.txt b/tests/arm/corefx_linux_test_exclusions.txt
new file mode 100644
index 0000000000..ed84e9615c
--- /dev/null
+++ b/tests/arm/corefx_linux_test_exclusions.txt
@@ -0,0 +1,15 @@
+System.Console.Tests
+System.Data.SqlClient.Tests # https://github.com/dotnet/coreclr/issues/16001
+System.Diagnostics.Process.Tests # https://github.com/dotnet/coreclr/issues/16001
+System.Diagnostics.StackTrace.Tests # https://github.com/dotnet/coreclr/issues/17557 -- JitStress=1; https://github.com/dotnet/coreclr/issues/17558 -- JitStress=2
+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/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
+System.Net.NetworkInformation.Functional.Tests # https://github.com/dotnet/coreclr/issues/17753 -- segmentation fault
+System.Net.Sockets.Tests # https://github.com/dotnet/coreclr/issues/17753 -- segmentation fault
+System.Text.RegularExpressions.Tests # https://github.com/dotnet/coreclr/issues/17754 -- timeout -- JitMinOpts only
+System.Transactions.Local.Tests # https://github.com/dotnet/coreclr/issues/17754 -- timeout