@@ -1547,6 +1547,111 @@ namespace {
1547
1547
}
1548
1548
};
1549
1549
1550
+ class InitAccessorComponent
1551
+ : public AccessorBasedComponent<LogicalPathComponent> {
1552
+ public:
1553
+ InitAccessorComponent (AbstractStorageDecl *decl,
1554
+ SILDeclRef accessor,
1555
+ bool isSuper,
1556
+ bool isDirectAccessorUse,
1557
+ SubstitutionMap substitutions,
1558
+ CanType baseFormalType,
1559
+ LValueTypeData typeData,
1560
+ ArgumentList *subscriptArgList,
1561
+ PreparedArguments &&indices,
1562
+ bool isOnSelfParameter,
1563
+ Optional<ActorIsolation> actorIso)
1564
+ : AccessorBasedComponent(
1565
+ InitAccessorKind, decl, accessor, isSuper, isDirectAccessorUse,
1566
+ substitutions, baseFormalType, typeData, subscriptArgList,
1567
+ std::move (indices), isOnSelfParameter, actorIso) {
1568
+ assert (getAccessorDecl ()->isInitAccessor ());
1569
+ }
1570
+
1571
+ InitAccessorComponent (const InitAccessorComponent &copied,
1572
+ SILGenFunction &SGF, SILLocation loc)
1573
+ : AccessorBasedComponent(copied, SGF, loc) {}
1574
+
1575
+ void set (SILGenFunction &SGF, SILLocation loc, ArgumentSource &&value,
1576
+ ManagedValue base) &&
1577
+ override {
1578
+ VarDecl *field = cast<VarDecl>(Storage);
1579
+ auto fieldType = field->getValueInterfaceType ();
1580
+ if (!Substitutions.empty ()) {
1581
+ fieldType = fieldType.subst (Substitutions);
1582
+ }
1583
+
1584
+ // Emit the init accessor function partially applied to the base.
1585
+ SILValue initFRef =
1586
+ emitPartialInitAccessorReference (SGF, loc, getAccessorDecl ());
1587
+
1588
+ SILValue setterFRef;
1589
+ CanSILFunctionType setterTy;
1590
+ std::tie (setterFRef, setterTy) = applySetterToBase (
1591
+ SGF, loc, SILDeclRef (field->getOpaqueAccessor (AccessorKind::Set)),
1592
+ base);
1593
+
1594
+ auto Mval =
1595
+ emitValue (SGF, loc, field, fieldType, std::move (value), setterTy);
1596
+
1597
+ SGF.B .createAssignOrInit (loc, base.getValue (), Mval.forward (SGF),
1598
+ initFRef, setterFRef, AssignOrInitInst::Unknown);
1599
+ }
1600
+
1601
+ RValue get (SILGenFunction &SGF, SILLocation loc, ManagedValue base,
1602
+ SGFContext c) &&
1603
+ override {
1604
+ llvm_unreachable (" called get on an init accessor component" );
1605
+ }
1606
+
1607
+ std::unique_ptr<LogicalPathComponent>
1608
+ clone (SILGenFunction &SGF, SILLocation loc) const override {
1609
+ LogicalPathComponent *clone = new InitAccessorComponent (*this , SGF, loc);
1610
+ return std::unique_ptr<LogicalPathComponent>(clone);
1611
+ }
1612
+
1613
+ void dump (raw_ostream &OS, unsigned indent) const override {
1614
+ printBase (OS, indent, " InitAccessorComponent" );
1615
+ }
1616
+
1617
+ // / Compare 'this' lvalue and the 'rhs' lvalue (which is guaranteed to have
1618
+ // / the same dynamic PathComponent type as the receiver) to see if they are
1619
+ // / identical. If so, there is a conflicting writeback happening, so emit a
1620
+ // / diagnostic.
1621
+ Optional<AccessStorage> getAccessStorage () const override {
1622
+ return AccessStorage{Storage, IsSuper,
1623
+ Indices.isNull () ? nullptr : &Indices,
1624
+ ArgListForDiagnostics};
1625
+ }
1626
+
1627
+ private:
1628
+ SILValue emitPartialInitAccessorReference (SILGenFunction &SGF,
1629
+ SILLocation loc,
1630
+ AccessorDecl *initAccessor) {
1631
+ assert (initAccessor->isInitAccessor ());
1632
+ auto initConstant = SGF.getAccessorDeclRef (initAccessor);
1633
+ SILValue initFRef = SGF.emitGlobalFunctionRef (loc, initConstant);
1634
+
1635
+ // If there are no substitutions there is no need to emit partial
1636
+ // apply.
1637
+ if (Substitutions.empty ())
1638
+ return initFRef;
1639
+
1640
+ CanSILFunctionType initTy =
1641
+ initFRef->getType ().castTo <SILFunctionType>()->substGenericArgs (
1642
+ SGF.SGM .M , Substitutions, SGF.getTypeExpansionContext ());
1643
+
1644
+ SILFunctionConventions setterConv (initTy, SGF.SGM .M );
1645
+
1646
+ // Emit partial apply without argument to produce a substituted
1647
+ // init accessor reference.
1648
+ PartialApplyInst *initPAI = SGF.B .createPartialApply (
1649
+ loc, initFRef, Substitutions, ArrayRef<SILValue>(),
1650
+ ParameterConvention::Direct_Guaranteed);
1651
+ return SGF.emitManagedRValueWithCleanup (initPAI).getValue ();
1652
+ }
1653
+ };
1654
+
1550
1655
class GetterSetterComponent
1551
1656
: public AccessorBasedComponent<LogicalPathComponent> {
1552
1657
public:
@@ -1700,51 +1805,24 @@ namespace {
1700
1805
assert (!ActorIso && " no support for cross-actor set operations" );
1701
1806
SILDeclRef setter = Accessor;
1702
1807
1703
- auto emitPartialInitAccessorApply =
1704
- [&](AccessorDecl *initAccessor) -> SILValue {
1705
- assert (initAccessor->isInitAccessor ());
1706
- auto initConstant = SGF.getAccessorDeclRef (initAccessor);
1707
- SILValue initFRef = SGF.emitGlobalFunctionRef (loc, initConstant);
1708
-
1709
- // If there are no substitutions there is no need to emit partial
1710
- // apply.
1711
- if (Substitutions.empty ())
1712
- return initFRef;
1713
-
1714
- // Emit partial apply without argument to produce a substituted
1715
- // init accessor reference.
1716
- PartialApplyInst *initPAI = SGF.B .createPartialApply (
1717
- loc, initFRef, Substitutions, ArrayRef<SILValue>(),
1718
- ParameterConvention::Direct_Guaranteed);
1719
- return SGF.emitManagedRValueWithCleanup (initPAI).getValue ();
1720
- };
1721
-
1722
1808
if (canRewriteSetAsInitAccessor (SGF)) {
1723
1809
// Emit an assign_or_init with the allocating initializer function and the
1724
1810
// setter function as arguments. DefiniteInitialization will then decide
1725
1811
// between the two functions, depending if it's an init call or a
1726
1812
// set call.
1727
- VarDecl *field = cast<VarDecl>(Storage);
1728
- auto FieldType = field->getValueInterfaceType ();
1729
- if (!Substitutions.empty ()) {
1730
- FieldType = FieldType.subst (Substitutions);
1731
- }
1732
-
1733
- // Emit the init accessor function partially applied to the base.
1734
- auto initFn = emitPartialInitAccessorApply (
1735
- field->getOpaqueAccessor (AccessorKind::Init));
1736
-
1737
- // Emit the set accessor function partially applied to the base.
1738
- SILValue setterFn;
1739
- CanSILFunctionType setterTy;
1740
- std::tie (setterFn, setterTy) =
1741
- applySetterToBase (SGF, loc, Accessor, base);
1742
-
1743
- // Create the assign_or_init with the initializer and setter.
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);
1813
+ SILDeclRef initAccessorRef (Storage->getAccessor (AccessorKind::Init));
1814
+ InitAccessorComponent IAC (Storage,
1815
+ initAccessorRef,
1816
+ IsSuper,
1817
+ IsDirectAccessorUse,
1818
+ Substitutions,
1819
+ BaseFormalType,
1820
+ getTypeData (),
1821
+ ArgListForDiagnostics,
1822
+ std::move (Indices),
1823
+ IsOnSelfParameter,
1824
+ ActorIso);
1825
+ std::move (IAC).set (SGF, loc, std::move (value), base);
1748
1826
return ;
1749
1827
}
1750
1828
0 commit comments