Skip to content

Commit 99dd60d

Browse files
authored
JIT: Check more invariants on ABI info and fix some arm32 bugs (#101372)
- Implicit byref parameters should be passed as a single pointer sized segment - Segments should not point outside the local size - Segments should not overlap each other - Segments should have size > 0 - Segments should be ordered by offset - Fix a bug in the arm32 classifier when structs are split - Fix a bug in the arm32 classifier for odd-sized structs with 8 byte alignment. For example ```csharp [StructLayout(LayoutKind.Sequential, Size = 12)] struct S { public double X; public float Y; } ``` would be considered to take 4 slots before. - Fix a bug in the Swift classifier that would cause the tail segments to have an out-of-bounds size
1 parent aec52ab commit 99dd60d

File tree

4 files changed

+48
-5
lines changed

4 files changed

+48
-5
lines changed

src/coreclr/jit/abi.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,9 @@ ABIPassingInformation SwiftABIClassifier::Classify(Compiler* comp,
415415
{
416416
ABIPassingSegment newSegment = elemInfo.Segments[j];
417417
newSegment.Offset += lowering->offsets[i];
418+
// Adjust the tail size if necessary; the lowered sequence can
419+
// pass the tail as a larger type than the tail size.
420+
newSegment.Size = min(newSegment.Size, structLayout->GetSize() - newSegment.Offset);
418421
segments.Push(newSegment);
419422
}
420423
}

src/coreclr/jit/codegencommon.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -4185,9 +4185,13 @@ void CodeGen::genHomeSwiftStructParameters(bool handleStack)
41854185
case 2:
41864186
loadType = TYP_USHORT;
41874187
break;
4188+
case 3:
41884189
case 4:
41894190
loadType = TYP_INT;
41904191
break;
4192+
case 5:
4193+
case 6:
4194+
case 7:
41914195
case 8:
41924196
loadType = TYP_LONG;
41934197
break;

src/coreclr/jit/lclvars.cpp

+36
Original file line numberDiff line numberDiff line change
@@ -1885,6 +1885,42 @@ void Compiler::lvaClassifyParameterABI()
18851885
}
18861886
}
18871887
}
1888+
1889+
for (unsigned lclNum = 0; lclNum < info.compArgsCount; lclNum++)
1890+
{
1891+
const ABIPassingInformation& abiInfo = lvaGetParameterABIInfo(lclNum);
1892+
1893+
if (lvaIsImplicitByRefLocal(lclNum))
1894+
{
1895+
assert((abiInfo.NumSegments == 1) && (abiInfo.Segments[0].Size == TARGET_POINTER_SIZE));
1896+
}
1897+
else
1898+
{
1899+
for (unsigned i = 0; i < abiInfo.NumSegments; i++)
1900+
{
1901+
const ABIPassingSegment& segment = abiInfo.Segments[i];
1902+
assert(segment.Size > 0);
1903+
assert(segment.Offset + segment.Size <= lvaLclExactSize(lclNum));
1904+
1905+
if (i > 0)
1906+
{
1907+
assert(segment.Offset > abiInfo.Segments[i - 1].Offset);
1908+
}
1909+
1910+
for (unsigned j = 0; j < abiInfo.NumSegments; j++)
1911+
{
1912+
if (i == j)
1913+
{
1914+
continue;
1915+
}
1916+
1917+
const ABIPassingSegment& otherSegment = abiInfo.Segments[j];
1918+
assert((segment.Offset + segment.Size <= otherSegment.Offset) ||
1919+
(segment.Offset >= otherSegment.Offset + otherSegment.Size));
1920+
}
1921+
}
1922+
}
1923+
}
18881924
#endif // DEBUG
18891925
}
18901926

src/coreclr/jit/targetarm.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,11 @@ ABIPassingInformation Arm32Classifier::Classify(Compiler* comp,
8585
m_nextIntReg = roundUp(m_nextIntReg, 2);
8686
}
8787

88-
unsigned size = type == TYP_STRUCT ? structLayout->GetSize() : genTypeSize(type);
89-
unsigned alignedSize = roundUp(size, alignment);
88+
unsigned size = type == TYP_STRUCT ? structLayout->GetSize() : genTypeSize(type);
89+
unsigned numSlots = (size + 3) / 4;
9090

91-
unsigned numInRegs = min(alignedSize / 4, 4 - m_nextIntReg);
92-
bool anyOnStack = numInRegs < (alignedSize / 4);
91+
unsigned numInRegs = min(numSlots, 4 - m_nextIntReg);
92+
bool anyOnStack = numInRegs < numSlots;
9393

9494
// If we already passed anything on stack (due to float args) then we
9595
// cannot split an arg.
@@ -116,7 +116,7 @@ ABIPassingInformation Arm32Classifier::Classify(Compiler* comp,
116116
{
117117
m_stackArgSize = roundUp(m_stackArgSize, alignment);
118118
unsigned stackSize = size - (numInRegs * 4);
119-
info.Segments[numInRegs] = ABIPassingSegment::OnStack(m_stackArgSize, 0, stackSize);
119+
info.Segments[numInRegs] = ABIPassingSegment::OnStack(m_stackArgSize, numInRegs * 4, stackSize);
120120
m_stackArgSize += roundUp(stackSize, 4);
121121

122122
// As soon as any int arg goes on stack we cannot put anything else in

0 commit comments

Comments
 (0)