@@ -1754,3 +1754,111 @@ ParamDecl *SILGenFunction::isMappedToInitAccessorArgument(VarDecl *property) {
1754
1754
1755
1755
return arg->second ;
1756
1756
}
1757
+
1758
+ SILValue
1759
+ SILGenFunction::emitApplyOfSetterToBase (SILLocation loc, SILDeclRef setter,
1760
+ ManagedValue base,
1761
+ SubstitutionMap substitutions) {
1762
+ auto setterFRef = [&]() -> SILValue {
1763
+ auto setterInfo = getConstantInfo (getTypeExpansionContext (), setter);
1764
+ if (setter.hasDecl () && setter.getDecl ()->shouldUseObjCDispatch ()) {
1765
+ // Emit a thunk we might have to bridge arguments.
1766
+ auto foreignSetterThunk = setter.asForeign (false );
1767
+ return emitDynamicMethodRef (
1768
+ loc, foreignSetterThunk,
1769
+ SGM.Types
1770
+ .getConstantInfo (getTypeExpansionContext (),
1771
+ foreignSetterThunk)
1772
+ .SILFnType )
1773
+ .getValue ();
1774
+ }
1775
+
1776
+ return emitGlobalFunctionRef (loc, setter, setterInfo);
1777
+ }();
1778
+
1779
+ auto getSetterType = [&](SILValue setterFRef) {
1780
+ CanSILFunctionType setterTy =
1781
+ setterFRef->getType ().castTo <SILFunctionType>();
1782
+ return setterTy->substGenericArgs (SGM.M , substitutions,
1783
+ getTypeExpansionContext ());
1784
+ };
1785
+
1786
+ SILFunctionConventions setterConv (getSetterType (setterFRef), SGM.M );
1787
+
1788
+ // Emit captures for the setter
1789
+ SmallVector<SILValue, 4 > capturedArgs;
1790
+ auto captureInfo = SGM.Types .getLoweredLocalCaptures (setter);
1791
+ if (!captureInfo.getCaptures ().empty ()) {
1792
+ SmallVector<ManagedValue, 4 > captures;
1793
+ emitCaptures (loc, setter, CaptureEmission::AssignByWrapper, captures);
1794
+
1795
+ for (auto capture : captures)
1796
+ capturedArgs.push_back (capture.forward (*this ));
1797
+ } else {
1798
+ assert (base);
1799
+
1800
+ SILValue capturedBase;
1801
+ unsigned argIdx = setterConv.getNumSILArguments () - 1 ;
1802
+
1803
+ if (setterConv.getSILArgumentConvention (argIdx).isInoutConvention ()) {
1804
+ capturedBase = base.getValue ();
1805
+ } else if (base.getType ().isAddress () &&
1806
+ base.getType ().getObjectType () ==
1807
+ setterConv.getSILArgumentType (argIdx,
1808
+ getTypeExpansionContext ())) {
1809
+ // If the base is a reference and the setter expects a value, emit a
1810
+ // load. This pattern is emitted for property wrappers with a
1811
+ // nonmutating setter, for example.
1812
+ capturedBase = B.createTrivialLoadOr (loc, base.getValue (),
1813
+ LoadOwnershipQualifier::Copy);
1814
+ } else {
1815
+ capturedBase = base.copy (*this , loc).forward (*this );
1816
+ }
1817
+
1818
+ capturedArgs.push_back (capturedBase);
1819
+ }
1820
+
1821
+ PartialApplyInst *setterPAI =
1822
+ B.createPartialApply (loc, setterFRef, substitutions, capturedArgs,
1823
+ ParameterConvention::Direct_Guaranteed);
1824
+ return emitManagedRValueWithCleanup (setterPAI).getValue ();
1825
+ }
1826
+
1827
+ void SILGenFunction::emitAssignOrInit (SILLocation loc, ManagedValue selfValue,
1828
+ VarDecl *field, ManagedValue newValue,
1829
+ SubstitutionMap substitutions) {
1830
+ auto fieldTy = field->getValueInterfaceType ();
1831
+ if (!substitutions.empty ())
1832
+ fieldTy = fieldTy.subst (substitutions);
1833
+
1834
+ // Emit the init accessor function partially applied to the base.
1835
+ SILValue initFRef = emitGlobalFunctionRef (
1836
+ loc, getAccessorDeclRef (field->getOpaqueAccessor (AccessorKind::Init)));
1837
+ if (!substitutions.empty ()) {
1838
+ // If there are substitutions we need to emit partial apply to
1839
+ // apply substitutions to the init accessor reference type.
1840
+ auto initTy =
1841
+ initFRef->getType ().castTo <SILFunctionType>()->substGenericArgs (
1842
+ SGM.M , substitutions, getTypeExpansionContext ());
1843
+
1844
+ SILFunctionConventions setterConv (initTy, SGM.M );
1845
+
1846
+ // Emit partial apply without argument to produce a substituted
1847
+ // init accessor reference.
1848
+ PartialApplyInst *initPAI =
1849
+ B.createPartialApply (loc, initFRef, substitutions, ArrayRef<SILValue>(),
1850
+ ParameterConvention::Direct_Guaranteed);
1851
+ initFRef = emitManagedRValueWithCleanup (initPAI).getValue ();
1852
+ }
1853
+
1854
+ SILValue setterFRef;
1855
+ if (auto *setter = field->getOpaqueAccessor (AccessorKind::Set)) {
1856
+ setterFRef = emitApplyOfSetterToBase (loc, SILDeclRef (setter), selfValue,
1857
+ substitutions);
1858
+ } else {
1859
+ setterFRef = SILUndef::get (initFRef->getType (), F);
1860
+ }
1861
+
1862
+ B.createAssignOrInit (loc, selfValue.getValue (), newValue.forward (*this ),
1863
+ initFRef, setterFRef, AssignOrInitInst::Unknown);
1864
+ }
0 commit comments