@@ -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