@@ -1437,6 +1437,114 @@ namespace {
1437
1437
AccessorDecl *getAccessorDecl () const {
1438
1438
return cast<AccessorDecl>(Accessor.getFuncDecl ());
1439
1439
}
1440
+
1441
+ ManagedValue emitValue (SILGenFunction &SGF, SILLocation loc, VarDecl *field,
1442
+ Type fieldType, ArgumentSource &&value,
1443
+ CanSILFunctionType accessorTy) {
1444
+ SILFunctionConventions accessorConv (accessorTy, SGF.SGM .M );
1445
+
1446
+ // FIXME: This should use CallEmission instead of doing everything
1447
+ // manually.
1448
+ assert (value.isRValue ());
1449
+ ManagedValue Mval =
1450
+ std::move (value).asKnownRValue (SGF).getAsSingleValue (SGF, loc);
1451
+ auto param = accessorTy->getParameters ()[0 ];
1452
+ SILType loweredSubstArgType = Mval.getType ();
1453
+ if (param.isIndirectInOut ()) {
1454
+ loweredSubstArgType =
1455
+ SILType::getPrimitiveAddressType (loweredSubstArgType.getASTType ());
1456
+ }
1457
+ auto loweredSubstParamTy = SILType::getPrimitiveType (
1458
+ param.getArgumentType (SGF.SGM .M , accessorTy,
1459
+ SGF.getTypeExpansionContext ()),
1460
+ loweredSubstArgType.getCategory ());
1461
+ // Handle reabstraction differences.
1462
+ if (Mval.getType () != loweredSubstParamTy) {
1463
+ Mval = SGF.emitSubstToOrigValue (
1464
+ loc, Mval, SGF.SGM .Types .getAbstractionPattern (field),
1465
+ fieldType->getCanonicalType ());
1466
+ }
1467
+
1468
+ // If we need the argument in memory, materialize an address.
1469
+ if (accessorConv.getSILArgumentConvention (0 ).isIndirectConvention () &&
1470
+ !Mval.getType ().isAddress ()) {
1471
+ Mval = Mval.materialize (SGF, loc);
1472
+ }
1473
+
1474
+ return Mval;
1475
+ }
1476
+
1477
+ std::pair<SILValue, CanSILFunctionType>
1478
+ applySetterToBase (SILGenFunction &SGF, SILLocation loc, SILDeclRef setter,
1479
+ ManagedValue base) const {
1480
+ auto setterFRef = [&]() -> SILValue {
1481
+ auto setterInfo =
1482
+ SGF.getConstantInfo (SGF.getTypeExpansionContext (), setter);
1483
+ if (setter.hasDecl () && setter.getDecl ()->shouldUseObjCDispatch ()) {
1484
+ // Emit a thunk we might have to bridge arguments.
1485
+ auto foreignSetterThunk = setter.asForeign (false );
1486
+ return SGF
1487
+ .emitDynamicMethodRef (
1488
+ loc, foreignSetterThunk,
1489
+ SGF.SGM .Types
1490
+ .getConstantInfo (SGF.getTypeExpansionContext (),
1491
+ foreignSetterThunk)
1492
+ .SILFnType )
1493
+ .getValue ();
1494
+ }
1495
+
1496
+ return SGF.emitGlobalFunctionRef (loc, setter, setterInfo);
1497
+ }();
1498
+
1499
+ auto getSetterType = [&](SILValue setterFRef) {
1500
+ CanSILFunctionType setterTy =
1501
+ setterFRef->getType ().castTo <SILFunctionType>();
1502
+ return setterTy->substGenericArgs (SGF.SGM .M , Substitutions,
1503
+ SGF.getTypeExpansionContext ());
1504
+ };
1505
+
1506
+ auto setterTy = getSetterType (setterFRef);
1507
+ SILFunctionConventions setterConv (setterTy, SGF.SGM .M );
1508
+
1509
+ // Emit captures for the setter
1510
+ SmallVector<SILValue, 4 > capturedArgs;
1511
+ auto captureInfo = SGF.SGM .Types .getLoweredLocalCaptures (setter);
1512
+ if (!captureInfo.getCaptures ().empty ()) {
1513
+ SmallVector<ManagedValue, 4 > captures;
1514
+ SGF.emitCaptures (loc, setter, CaptureEmission::AssignByWrapper,
1515
+ captures);
1516
+
1517
+ for (auto capture : captures)
1518
+ capturedArgs.push_back (capture.forward (SGF));
1519
+ } else {
1520
+ assert (base);
1521
+
1522
+ SILValue capturedBase;
1523
+ unsigned argIdx = setterConv.getNumSILArguments () - 1 ;
1524
+
1525
+ if (setterConv.getSILArgumentConvention (argIdx).isInoutConvention ()) {
1526
+ capturedBase = base.getValue ();
1527
+ } else if (base.getType ().isAddress () &&
1528
+ base.getType ().getObjectType () ==
1529
+ setterConv.getSILArgumentType (
1530
+ argIdx, SGF.getTypeExpansionContext ())) {
1531
+ // If the base is a reference and the setter expects a value, emit a
1532
+ // load. This pattern is emitted for property wrappers with a
1533
+ // nonmutating setter, for example.
1534
+ capturedBase = SGF.B .createTrivialLoadOr (
1535
+ loc, base.getValue (), LoadOwnershipQualifier::Copy);
1536
+ } else {
1537
+ capturedBase = base.copy (SGF, loc).forward (SGF);
1538
+ }
1539
+
1540
+ capturedArgs.push_back (capturedBase);
1541
+ }
1542
+
1543
+ PartialApplyInst *setterPAI =
1544
+ SGF.B .createPartialApply (loc, setterFRef, Substitutions, capturedArgs,
1545
+ ParameterConvention::Direct_Guaranteed);
1546
+ return {SGF.emitManagedRValueWithCleanup (setterPAI).getValue (), setterTy};
1547
+ }
1440
1548
};
1441
1549
1442
1550
class GetterSetterComponent
@@ -1592,32 +1700,6 @@ namespace {
1592
1700
assert (!ActorIso && " no support for cross-actor set operations" );
1593
1701
SILDeclRef setter = Accessor;
1594
1702
1595
- auto getSetterFRef = [&]() -> SILValue {
1596
- auto setterInfo =
1597
- SGF.getConstantInfo (SGF.getTypeExpansionContext (), setter);
1598
- if (setter.hasDecl () && setter.getDecl ()->shouldUseObjCDispatch ()) {
1599
- // Emit a thunk we might have to bridge arguments.
1600
- auto foreignSetterThunk = setter.asForeign (false );
1601
- return SGF
1602
- .emitDynamicMethodRef (
1603
- loc, foreignSetterThunk,
1604
- SGF.SGM .Types
1605
- .getConstantInfo (SGF.getTypeExpansionContext (),
1606
- foreignSetterThunk)
1607
- .SILFnType )
1608
- .getValue ();
1609
- }
1610
-
1611
- return SGF.emitGlobalFunctionRef (loc, setter, setterInfo);
1612
- };
1613
-
1614
- auto getSetterType = [&](SILValue setterFRef) {
1615
- CanSILFunctionType setterTy =
1616
- setterFRef->getType ().castTo <SILFunctionType>();
1617
- return setterTy->substGenericArgs (SGF.SGM .M , Substitutions,
1618
- SGF.getTypeExpansionContext ());
1619
- };
1620
-
1621
1703
auto emitPartialInitAccessorApply =
1622
1704
[&](AccessorDecl *initAccessor) -> SILValue {
1623
1705
assert (initAccessor->isInitAccessor ());
@@ -1637,83 +1719,6 @@ namespace {
1637
1719
return SGF.emitManagedRValueWithCleanup (initPAI).getValue ();
1638
1720
};
1639
1721
1640
- auto emitPartialSetterApply =
1641
- [&](SILValue setterFRef,
1642
- const SILFunctionConventions &setterConv) -> ManagedValue {
1643
- // Emit captures for thI e setter
1644
- SmallVector<SILValue, 4 > capturedArgs;
1645
- auto captureInfo = SGF.SGM .Types .getLoweredLocalCaptures (setter);
1646
- if (!captureInfo.getCaptures ().empty ()) {
1647
- SmallVector<ManagedValue, 4 > captures;
1648
- SGF.emitCaptures (loc, setter, CaptureEmission::AssignByWrapper,
1649
- captures);
1650
-
1651
- for (auto capture : captures)
1652
- capturedArgs.push_back (capture.forward (SGF));
1653
- } else {
1654
- assert (base);
1655
-
1656
- SILValue capturedBase;
1657
- unsigned argIdx = setterConv.getNumSILArguments () - 1 ;
1658
-
1659
- if (setterConv.getSILArgumentConvention (argIdx).isInoutConvention ()) {
1660
- capturedBase = base.getValue ();
1661
- } else if (base.getType ().isAddress () &&
1662
- base.getType ().getObjectType () ==
1663
- setterConv.getSILArgumentType (
1664
- argIdx, SGF.getTypeExpansionContext ())) {
1665
- // If the base is a reference and the setter expects a value, emit a
1666
- // load. This pattern is emitted for property wrappers with a
1667
- // nonmutating setter, for example.
1668
- capturedBase = SGF.B .createTrivialLoadOr (
1669
- loc, base.getValue (), LoadOwnershipQualifier::Copy);
1670
- } else {
1671
- capturedBase = base.copy (SGF, loc).forward (SGF);
1672
- }
1673
-
1674
- capturedArgs.push_back (capturedBase);
1675
- }
1676
-
1677
- PartialApplyInst *setterPAI = SGF.B .createPartialApply (
1678
- loc, setterFRef, Substitutions, capturedArgs,
1679
- ParameterConvention::Direct_Guaranteed);
1680
- return SGF.emitManagedRValueWithCleanup (setterPAI);
1681
- };
1682
-
1683
- auto emitValue =
1684
- [&](VarDecl *field, Type fieldType, CanSILFunctionType setterTy,
1685
- const SILFunctionConventions &setterConv) -> ManagedValue {
1686
- // FIXME: This should use CallEmission instead of doing everything
1687
- // manually.
1688
- assert (value.isRValue ());
1689
- ManagedValue Mval =
1690
- std::move (value).asKnownRValue (SGF).getAsSingleValue (SGF, loc);
1691
- auto param = setterTy->getParameters ()[0 ];
1692
- SILType loweredSubstArgType = Mval.getType ();
1693
- if (param.isIndirectInOut ()) {
1694
- loweredSubstArgType = SILType::getPrimitiveAddressType (
1695
- loweredSubstArgType.getASTType ());
1696
- }
1697
- auto loweredSubstParamTy = SILType::getPrimitiveType (
1698
- param.getArgumentType (SGF.SGM .M , setterTy,
1699
- SGF.getTypeExpansionContext ()),
1700
- loweredSubstArgType.getCategory ());
1701
- // Handle reabstraction differences.
1702
- if (Mval.getType () != loweredSubstParamTy) {
1703
- Mval = SGF.emitSubstToOrigValue (
1704
- loc, Mval, SGF.SGM .Types .getAbstractionPattern (field),
1705
- fieldType->getCanonicalType ());
1706
- }
1707
-
1708
- // If we need the argument in memory, materialize an address.
1709
- if (setterConv.getSILArgumentConvention (0 ).isIndirectConvention () &&
1710
- !Mval.getType ().isAddress ()) {
1711
- Mval = Mval.materialize (SGF, loc);
1712
- }
1713
-
1714
- return Mval;
1715
- };
1716
-
1717
1722
if (canRewriteSetAsInitAccessor (SGF)) {
1718
1723
// Emit an assign_or_init with the allocating initializer function and the
1719
1724
// setter function as arguments. DefiniteInitialization will then decide
@@ -1730,16 +1735,16 @@ namespace {
1730
1735
field->getOpaqueAccessor (AccessorKind::Init));
1731
1736
1732
1737
// Emit the set accessor function partially applied to the base.
1733
- auto setterFRef = getSetterFRef () ;
1734
- auto setterTy = getSetterType (setterFRef) ;
1735
- SILFunctionConventions setterConv (setterTy, SGF. SGM . M );
1736
- auto setterFn = emitPartialSetterApply (setterFRef, setterConv );
1738
+ SILValue setterFn ;
1739
+ CanSILFunctionType setterTy;
1740
+ std::tie (setterFn, setterTy) =
1741
+ applySetterToBase (SGF, loc, Accessor, base );
1737
1742
1738
1743
// Create the assign_or_init with the initializer and setter.
1739
- auto value = emitValue (field, FieldType, setterTy, setterConv);
1740
- SGF. B . createAssignOrInit ( loc, base. getValue (), value. forward (SGF),
1741
- initFn, setterFn .getValue (),
1742
- AssignOrInitInst::Unknown);
1744
+ auto Mval =
1745
+ emitValue (SGF, loc, field, FieldType, std::move (value), setterTy);
1746
+ SGF. B . createAssignOrInit (loc, base .getValue (), Mval. forward (SGF ),
1747
+ initFn, setterFn, AssignOrInitInst::Unknown);
1743
1748
return ;
1744
1749
}
1745
1750
@@ -1802,19 +1807,19 @@ namespace {
1802
1807
ManagedValue initFn = SGF.emitManagedRValueWithCleanup (initPAI);
1803
1808
1804
1809
// Create the allocating setter function. It captures the base address.
1805
- auto setterFRef = getSetterFRef () ;
1806
- auto setterTy = getSetterType (setterFRef) ;
1807
- SILFunctionConventions setterConv (setterTy, SGF. SGM . M );
1808
- auto setterFn = emitPartialSetterApply (setterFRef, setterConv );
1810
+ SILValue setterFn ;
1811
+ CanSILFunctionType setterTy;
1812
+ std::tie (setterFn, setterTy) =
1813
+ applySetterToBase (SGF, loc, Accessor, base );
1809
1814
1810
1815
// Create the assign_by_wrapper with the initializer and setter.
1811
1816
1812
- auto Mval = emitValue (field, FieldType, setterTy, setterConv);
1813
-
1814
- SGF.B .createAssignByWrapper (
1815
- loc, Mval.forward (SGF), proj.forward (SGF), initFn.getValue (),
1816
- setterFn.getValue (), AssignByWrapperInst::Unknown);
1817
+ auto Mval =
1818
+ emitValue (SGF, loc, field, FieldType, std::move (value), setterTy);
1817
1819
1820
+ SGF.B .createAssignByWrapper (loc, Mval.forward (SGF), proj.forward (SGF),
1821
+ initFn.getValue (), setterFn,
1822
+ AssignByWrapperInst::Unknown);
1818
1823
return ;
1819
1824
}
1820
1825
0 commit comments