@@ -1583,44 +1583,42 @@ GenTree* Lowering::NewPutArg(GenTreeCall* call, GenTree* arg, CallArg* callArg,
1583
1583
assert(arg != nullptr);
1584
1584
assert(callArg != nullptr);
1585
1585
1586
- GenTree* putArg = nullptr;
1587
-
1588
- bool isOnStack = (callArg->AbiInfo.GetRegNum() == REG_STK);
1586
+ GenTree* putArg = nullptr;
1587
+ const ABIPassingInformation& abiInfo = callArg->NewAbiInfo;
1589
1588
1590
1589
#if FEATURE_ARG_SPLIT
1591
1590
// Struct can be split into register(s) and stack on ARM
1592
- if (compFeatureArgSplit() && callArg->AbiInfo.IsSplit ())
1591
+ if (compFeatureArgSplit() && callArg->NewAbiInfo.IsSplitAcrossRegistersAndStack ())
1593
1592
{
1594
1593
assert(arg->OperIs(GT_BLK, GT_FIELD_LIST) || arg->OperIsLocalRead());
1595
- // TODO: Need to check correctness for FastTailCall
1596
- if (call->IsFastTailCall())
1594
+ assert(!call->IsFastTailCall());
1595
+
1596
+ #ifdef DEBUG
1597
+ for (unsigned i = 0; i < abiInfo.NumSegments; i++)
1597
1598
{
1598
- #ifdef TARGET_ARM
1599
- NYI_ARM("lower: struct argument by fast tail call");
1600
- #endif // TARGET_ARM
1599
+ assert((i < abiInfo.NumSegments - 1) == abiInfo.Segment(i).IsPassedInRegister());
1601
1600
}
1601
+ #endif
1602
1602
1603
- const unsigned slotNumber = callArg->AbiInfo.ByteOffset / TARGET_POINTER_SIZE ;
1604
- const bool putInIncomingArgArea = call->IsFastTailCall( );
1603
+ unsigned numRegs = abiInfo.NumSegments - 1 ;
1604
+ const ABIPassingSegment& stackSeg = abiInfo.Segment(abiInfo.NumSegments - 1 );
1605
1605
1606
- putArg = new (comp, GT_PUTARG_SPLIT) GenTreePutArgSplit(arg, callArg->AbiInfo.ByteOffset,
1607
- #ifdef FEATURE_PUT_STRUCT_ARG_STK
1608
- callArg->AbiInfo.GetStackByteSize(),
1609
- #endif
1610
- callArg->AbiInfo.NumRegs, call, putInIncomingArgArea);
1606
+ putArg = new (comp, GT_PUTARG_SPLIT)
1607
+ GenTreePutArgSplit(arg, stackSeg.GetStackOffset(), stackSeg.GetStackSize(), abiInfo.NumSegments - 1, call,
1608
+ /* putInIncomingArgArea */ false);
1611
1609
1612
1610
GenTreePutArgSplit* argSplit = putArg->AsPutArgSplit();
1613
- for (unsigned regIndex = 0; regIndex < callArg->AbiInfo.NumRegs ; regIndex++)
1611
+ for (unsigned regIndex = 0; regIndex < numRegs ; regIndex++)
1614
1612
{
1615
- argSplit->SetRegNumByIdx(callArg->AbiInfo.GetRegNum (regIndex), regIndex);
1613
+ argSplit->SetRegNumByIdx(abiInfo.Segment (regIndex).GetRegister( ), regIndex);
1616
1614
}
1617
1615
1618
1616
if (arg->OperIs(GT_FIELD_LIST))
1619
1617
{
1620
1618
unsigned regIndex = 0;
1621
1619
for (GenTreeFieldList::Use& use : arg->AsFieldList()->Uses())
1622
1620
{
1623
- if (regIndex >= callArg->AbiInfo.NumRegs )
1621
+ if (regIndex >= numRegs )
1624
1622
{
1625
1623
break;
1626
1624
}
@@ -1642,7 +1640,7 @@ GenTree* Lowering::NewPutArg(GenTreeCall* call, GenTree* arg, CallArg* callArg,
1642
1640
ClassLayout* layout = arg->GetLayout(comp);
1643
1641
1644
1642
// Set type of registers
1645
- for (unsigned index = 0; index < callArg->AbiInfo.NumRegs ; index++)
1643
+ for (unsigned index = 0; index < numRegs ; index++)
1646
1644
{
1647
1645
argSplit->m_regType[index] = layout->GetGCPtrType(index);
1648
1646
}
@@ -1651,15 +1649,15 @@ GenTree* Lowering::NewPutArg(GenTreeCall* call, GenTree* arg, CallArg* callArg,
1651
1649
else
1652
1650
#endif // FEATURE_ARG_SPLIT
1653
1651
{
1654
- if (!isOnStack )
1652
+ if (abiInfo.HasAnyRegisterSegment() )
1655
1653
{
1656
1654
#if FEATURE_MULTIREG_ARGS
1657
- if ((callArg->AbiInfo.NumRegs > 1) && ( arg->OperGet() == GT_FIELD_LIST))
1655
+ if ((abiInfo.NumSegments > 1) && arg->OperIs( GT_FIELD_LIST))
1658
1656
{
1659
1657
unsigned int regIndex = 0;
1660
1658
for (GenTreeFieldList::Use& use : arg->AsFieldList()->Uses())
1661
1659
{
1662
- regNumber argReg = callArg->AbiInfo.GetRegNum (regIndex);
1660
+ regNumber argReg = abiInfo.Segment (regIndex).GetRegister( );
1663
1661
GenTree* curOp = use.GetNode();
1664
1662
var_types curTyp = curOp->TypeGet();
1665
1663
@@ -1678,74 +1676,27 @@ GenTree* Lowering::NewPutArg(GenTreeCall* call, GenTree* arg, CallArg* callArg,
1678
1676
else
1679
1677
#endif // FEATURE_MULTIREG_ARGS
1680
1678
{
1681
- putArg = comp->gtNewPutArgReg(type, arg, callArg->AbiInfo.GetRegNum());
1679
+ assert(abiInfo.HasExactlyOneRegisterSegment());
1680
+ putArg = comp->gtNewPutArgReg(type, arg, abiInfo.Segment(0).GetRegister());
1682
1681
}
1683
1682
}
1684
1683
else
1685
1684
{
1686
- // Mark this one as tail call arg if it is a fast tail call.
1687
- // This provides the info to put this argument in in-coming arg area slot
1688
- // instead of in out-going arg area slot.
1689
-
1690
- #ifdef DEBUG
1691
- // Make sure state is correct. The PUTARG_STK has TYP_VOID, as it doesn't produce
1692
- // a result. So the type of its operand must be the correct type to push on the stack.
1693
- callArg->CheckIsStruct();
1685
+ #ifdef FEATURE_SIMD
1686
+ assert(arg->OperIsFieldList() || (genActualType(arg) == type) ||
1687
+ (arg->TypeIs(TYP_SIMD16) && (type == TYP_SIMD12)));
1688
+ #else
1689
+ assert(arg->OperIsFieldList() || (genActualType(arg) == type));
1694
1690
#endif
1691
+ assert(abiInfo.NumSegments == 1);
1692
+ const ABIPassingSegment& stackSeg = abiInfo.Segment(0);
1693
+ const bool putInIncomingArgArea = call->IsFastTailCall();
1695
1694
1696
- if ((arg->OperGet() != GT_FIELD_LIST))
1697
- {
1698
- #if defined(FEATURE_SIMD) && defined(FEATURE_PUT_STRUCT_ARG_STK)
1699
- if (type == TYP_SIMD12)
1700
- {
1701
- #if !defined(TARGET_64BIT)
1702
- assert(callArg->AbiInfo.ByteSize == 12);
1703
- #else // TARGET_64BIT
1704
- if (compAppleArm64Abi())
1705
- {
1706
- assert(callArg->AbiInfo.ByteSize == 12);
1707
- }
1708
- else
1709
- {
1710
- assert(callArg->AbiInfo.ByteSize == 16);
1711
- }
1712
- #endif // TARGET_64BIT
1713
- }
1714
- else
1715
- #endif // defined(FEATURE_SIMD) && defined(FEATURE_PUT_STRUCT_ARG_STK)
1716
- {
1717
- assert(genActualType(arg->TypeGet()) == type);
1718
- }
1719
- }
1720
- const unsigned slotNumber = callArg->AbiInfo.ByteOffset / TARGET_POINTER_SIZE;
1721
- const bool putInIncomingArgArea = call->IsFastTailCall();
1722
-
1723
- putArg =
1724
- new (comp, GT_PUTARG_STK) GenTreePutArgStk(GT_PUTARG_STK, TYP_VOID, arg, callArg->AbiInfo.ByteOffset,
1695
+ putArg = new (comp, GT_PUTARG_STK) GenTreePutArgStk(GT_PUTARG_STK, TYP_VOID, arg, stackSeg.GetStackOffset(),
1725
1696
#ifdef FEATURE_PUT_STRUCT_ARG_STK
1726
- callArg->AbiInfo.GetStackByteSize(),
1727
- #endif
1728
- call, putInIncomingArgArea);
1729
-
1730
- #if defined(DEBUG) && defined(FEATURE_PUT_STRUCT_ARG_STK)
1731
- if (varTypeIsStruct(callArg->GetSignatureType()))
1732
- {
1733
- // We use GT_BLK only for non-SIMD struct arguments.
1734
- if (arg->OperIs(GT_BLK))
1735
- {
1736
- assert(!varTypeIsSIMD(arg));
1737
- }
1738
- else if (!arg->TypeIs(TYP_STRUCT))
1739
- {
1740
- #ifdef TARGET_ARM
1741
- assert((callArg->AbiInfo.GetStackSlotsNumber() == 1) ||
1742
- ((arg->TypeGet() == TYP_DOUBLE) && (callArg->AbiInfo.GetStackSlotsNumber() == 2)));
1743
- #else
1744
- assert(varTypeIsSIMD(arg) || (callArg->AbiInfo.GetStackSlotsNumber() == 1));
1697
+ stackSeg.GetStackSize(),
1745
1698
#endif
1746
- }
1747
- }
1748
- #endif // defined(DEBUG) && defined(FEATURE_PUT_STRUCT_ARG_STK)
1699
+ call, putInIncomingArgArea);
1749
1700
}
1750
1701
}
1751
1702
@@ -1819,7 +1770,8 @@ void Lowering::LowerArg(GenTreeCall* call, CallArg* callArg, bool late)
1819
1770
}
1820
1771
#elif defined(TARGET_AMD64)
1821
1772
// TYP_SIMD8 parameters that are passed as longs
1822
- if (type == TYP_SIMD8 && genIsValidIntReg(callArg->AbiInfo.GetRegNum()))
1773
+ if (type == TYP_SIMD8 && callArg->NewAbiInfo.HasExactlyOneRegisterSegment() &&
1774
+ genIsValidIntReg(callArg->NewAbiInfo.Segment(0).GetRegister()))
1823
1775
{
1824
1776
GenTree* bitcast = comp->gtNewBitCastNode(TYP_LONG, arg);
1825
1777
BlockRange().InsertAfter(arg, bitcast);
0 commit comments