-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
The compilation of the following program will noway_assert on Arm64
using System;
using System.Runtime.CompilerServices;
class Runtime_57606
{
public struct CompositeType16Bytes
{
public ulong _0;
public ulong _1;
}
public struct CompositeTypeMoreThan16Bytes
{
public ulong _0;
public ulong _1;
public byte _2;
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static CompositeTypeMoreThan16Bytes ReturnsViaBuffer(int x1, int x2, int x3, int x4, int x5, int x6, CompositeType16Bytes x7Stack, __arglist)
{
// Note that VarArgHnd is passed in register x0
// When allocating a parameter of CompositeType16Bytes to registers and stack
// NGRN = 7 and since the value can not be allocated to a single GP register
// the JIT splits the value between x7 and stack.
return default(CompositeTypeMoreThan16Bytes);
}
public static int Main()
{
ReturnsViaBuffer(1, 2, 3, 4, 5, 6, default(CompositeType16Bytes), __arglist());
return 100;
}
}Assert failure(PID 40264 [0x00009d48], Thread: 18960 [0x4a10]): Assertion failed 'regArgTab[regArgNum + i].slot == 0' in 'Runtime_57606:ReturnsViaBuffer(int,int,int,int,int,int,CompositeType16Bytes):CompositeTypeMoreThan16Bytes' during 'Generate code' (IL size 10)
File: D:\echesako\src\runtime\src\coreclr\jit\codegencommon.cpp Line: 3621
Image: D:\echesako\src\runtime\artifacts\tests\coreclr\windows.x64.Checked\Tests\Core_Root\CoreRun.exe
> clrjit_win_arm64_x64.dll!CodeGen::genFnPrologCalleeRegArgs(_regNumber_enum xtraReg, bool * pXtraRegClobbered, RegState * regState) Line 3621 C++
clrjit_win_arm64_x64.dll!CodeGen::genFnProlog() Line 7598 C++
clrjit_win_arm64_x64.dll!CodeGen::genGeneratePrologsAndEpilogs() Line 9447 C++
clrjit_win_arm64_x64.dll!CodeGen::genGenerateMachineCode() Line 2312 C++
clrjit_win_arm64_x64.dll!CodeGenPhase::DoPhase() Line 1610 C++
clrjit_win_arm64_x64.dll!Phase::Run() Line 61 C++
In the following loop
runtime/src/coreclr/jit/codegencommon.cpp
Lines 3615 to 3625 in 24971b0
| for (int i = 1; i < slots; i++) | |
| { | |
| noway_assert((regArgNum + i) < argMax); | |
| // We better not have added it already (there better not be multiple vars representing this argument | |
| // register) | |
| noway_assert(regArgTab[regArgNum + i].slot == 0); | |
| regArgTab[regArgNum + i].varNum = varNum; | |
| regArgTab[regArgNum + i].slot = (char)(i + 1); | |
| } |
we assign (varNum, slotNumber) to corresponding entries in regArgTab.
Since CompositeType16Bytes x7Stack can not be passed on a single GP register and NGRN = 7 (only one GP register is available), then according to arm64-windows-abi-conventions the argument is split between x7 and stack (this behavior is due to ReturnsViaBuffer being a variadic function). The local variable that corresponds to that parameter has two slots and the assert checks that the second slot can occupy regArgTab[8] entry (i.e. the assert is about the corresponding entry not been assigned to any other incoming argument). However, regArgTab[8] corresponds to __retbuf pointer.
If I make the function return void or int (i.e. not to use return buffer) it will be compiled fine but regArgTab[8] still will be assigned to the second of x7Stack parameter in the loop.
@dotnet/jit-contrib I believe the issue has been there for a while, so marking as 7.0.0.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status