Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 2054066

Browse files
BruceForstallRussKeldorph
authored andcommitted
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
1 parent 556228c commit 2054066

File tree

2 files changed

+34
-9
lines changed

2 files changed

+34
-9
lines changed

src/jit/morph.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3000,6 +3000,12 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
30003000
}
30013001
#endif // defined(_TARGET_X86_) || defined(_TARGET_ARM_)
30023002
#if defined(_TARGET_ARM_)
3003+
// A non-standard calling convention using secure delegate invoke is used on ARM, only, but not for secure
3004+
// delegates. It is used for VSD delegate calls where the VSD custom calling convention ABI requires passing
3005+
// R4, a callee-saved register, with a special value. Since R4 is a callee-saved register, its value needs
3006+
// to be preserved. Thus, the VM uses a secure delegate IL stub, which preserves R4 and also sets up R4
3007+
// correctly for the VSD call. The VM is simply reusing an existing mechanism (secure delegate IL stub)
3008+
// to achieve its goal for delegate VSD call. See COMDelegate::NeedsWrapperDelegate() in the VM for details.
30033009
else if (call->gtCallMoreFlags & GTF_CALL_M_SECURE_DELEGATE_INV)
30043010
{
30053011
GenTree* arg = call->gtCallObjp;
@@ -3520,6 +3526,8 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
35203526

35213527
// This size has now been computed
35223528
assert(size != 0);
3529+
3530+
isNonStandard = argEntry->isNonStandard;
35233531
}
35243532
else // !reMorphing
35253533
{
@@ -4151,9 +4159,9 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
41514159
// They should not affect the placement of any other args or stack space required.
41524160
// Example: on AMD64 R10 and R11 are used for indirect VSD (generic interface) and cookie calls.
41534161
isNonStandard = nonStandardArgs.FindReg(argx, &nonStdRegNum);
4154-
if (isNonStandard && (nonStdRegNum == REG_STK))
4162+
if (isNonStandard)
41554163
{
4156-
isRegArg = false;
4164+
isRegArg = (nonStdRegNum != REG_STK);
41574165
}
41584166
#if defined(_TARGET_X86_)
41594167
else if (call->IsTailCallViaHelper())
@@ -4209,12 +4217,19 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
42094217
if (isRegArg)
42104218
{
42114219
regNumber nextRegNum = REG_STK;
4220+
42124221
#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
42134222
regNumber nextOtherRegNum = REG_STK;
42144223
unsigned int structFloatRegs = 0;
42154224
unsigned int structIntRegs = 0;
4225+
#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
42164226

4217-
if (isStructArg && structDesc.passedInRegisters)
4227+
if (isNonStandard)
4228+
{
4229+
nextRegNum = nonStdRegNum;
4230+
}
4231+
#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
4232+
else if (isStructArg && structDesc.passedInRegisters)
42184233
{
42194234
// It is a struct passed in registers. Assign the next available register.
42204235
assert((structDesc.eightByteCount <= 2) && "Too many eightbytes.");
@@ -4233,8 +4248,8 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
42334248
}
42344249
}
42354250
}
4236-
else
42374251
#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
4252+
else
42384253
{
42394254
// fill in or update the argInfo table
42404255
nextRegNum = passUsingFloatRegs ? genMapFloatRegArgNumToRegNum(nextFltArgRegNum)
@@ -4255,11 +4270,6 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
42554270
}
42564271
else
42574272
{
4258-
if (isNonStandard)
4259-
{
4260-
nextRegNum = nonStdRegNum;
4261-
}
4262-
42634273
// This is a register argument - put it in the table
42644274
newArgEntry = call->fgArgInfo->AddRegArg(argIndex, argx, args, nextRegNum, size, argAlign
42654275
#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
System.Console.Tests
2+
System.Data.SqlClient.Tests # https://github.com/dotnet/coreclr/issues/16001
3+
System.Diagnostics.Process.Tests # https://github.com/dotnet/coreclr/issues/16001
4+
System.Diagnostics.StackTrace.Tests # https://github.com/dotnet/coreclr/issues/17557 -- JitStress=1; https://github.com/dotnet/coreclr/issues/17558 -- JitStress=2
5+
System.Drawing.Common.Tests # https://github.com/dotnet/coreclr/issues/16001
6+
System.IO.FileSystem.Tests # https://github.com/dotnet/coreclr/issues/16001
7+
System.IO.Ports.Tests # https://github.com/dotnet/coreclr/issues/16001
8+
System.Linq.Expressions.Tests # https://github.com/dotnet/corefx/issues/29421 -- timeout
9+
System.Management.Tests # https://github.com/dotnet/coreclr/issues/16001
10+
System.Net.Http.Functional.Tests # https://github.com/dotnet/coreclr/issues/17739
11+
System.Net.NameResolution.Pal.Tests # https://github.com/dotnet/coreclr/issues/17740
12+
System.Net.NetworkInformation.Functional.Tests # https://github.com/dotnet/coreclr/issues/17753 -- segmentation fault
13+
System.Net.Sockets.Tests # https://github.com/dotnet/coreclr/issues/17753 -- segmentation fault
14+
System.Text.RegularExpressions.Tests # https://github.com/dotnet/coreclr/issues/17754 -- timeout -- JitMinOpts only
15+
System.Transactions.Local.Tests # https://github.com/dotnet/coreclr/issues/17754 -- timeout

0 commit comments

Comments
 (0)