Skip to content

Assertion failed 'regArgTab[regArgNum + i].slot == 0' #57606

@echesakov

Description

@echesakov

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

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

arch-arm64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIbug

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions