3030#include " swift/SIL/SILInstruction.h"
3131#include " swift/SIL/SILUndef.h"
3232#include " swift/SIL/TypeLowering.h"
33+ #include < map>
3334
3435using namespace swift ;
3536using namespace Lowering ;
@@ -271,6 +272,47 @@ static RValue maybeEmitPropertyWrapperInitFromValue(
271272 subs, std::move (arg));
272273}
273274
275+ static void emitApplyOfInitAccessor (SILGenFunction &SGF, SILLocation loc,
276+ AccessorDecl *accessor, SILValue selfValue,
277+ SILType selfTy, RValue &&initialValue) {
278+ SmallVector<SILValue> arguments;
279+
280+ auto emitFieldReference = [&](VarDecl *field) {
281+ auto fieldTy =
282+ selfTy.getFieldType (field, SGF.SGM .M , SGF.getTypeExpansionContext ());
283+ return SGF.B .createStructElementAddr (loc, selfValue, field,
284+ fieldTy.getAddressType ());
285+ };
286+
287+ // First, let's emit all of the indirect results.
288+ if (auto *initAttr = accessor->getAttrs ().getAttribute <InitializesAttr>()) {
289+ for (auto *property : initAttr->getPropertyDecls (accessor)) {
290+ arguments.push_back (emitFieldReference (property));
291+ }
292+ }
293+
294+ // `initialValue`
295+ std::move (initialValue).forwardAll (SGF, arguments);
296+
297+ // And finally, all of the properties in `accesses(...)` list which are
298+ // `inout` arguments.
299+ if (auto *accessAttr = accessor->getAttrs ().getAttribute <AccessesAttr>()) {
300+ for (auto *property : accessAttr->getPropertyDecls (accessor)) {
301+ arguments.push_back (emitFieldReference (property));
302+ }
303+ }
304+
305+ SubstitutionMap subs;
306+ if (auto *env =
307+ accessor->getDeclContext ()->getGenericEnvironmentOfContext ()) {
308+ subs = env->getForwardingSubstitutionMap ();
309+ }
310+
311+ SILValue accessorRef =
312+ SGF.emitGlobalFunctionRef (loc, SGF.getAccessorDeclRef (accessor));
313+ (void )SGF.B .createApply (loc, accessorRef, subs, arguments, ApplyOptions ());
314+ }
315+
274316static SubstitutionMap getSubstitutionsForPropertyInitializer (
275317 DeclContext *dc,
276318 NominalTypeDecl *nominal) {
@@ -312,6 +354,12 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
312354 auto selfIfaceTy = selfDecl->getInterfaceType ();
313355 SILType selfTy = SGF.getSILTypeInContext (selfResultInfo, loweredFunctionTy);
314356
357+ auto *decl = selfTy.getStructOrBoundGenericStruct ();
358+ assert (decl && " not a struct?!" );
359+
360+ std::multimap<VarDecl *, VarDecl *> initializedViaAccessor;
361+ decl->collectPropertiesInitializableByInitAccessors (initializedViaAccessor);
362+
315363 // Emit the indirect return argument, if any.
316364 SILValue resultSlot;
317365 if (selfTy.isAddress ()) {
@@ -324,6 +372,10 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
324372 VD->setSpecifier (ParamSpecifier::InOut);
325373 VD->setInterfaceType (selfIfaceTy);
326374 resultSlot = SGF.F .begin ()->createFunctionArgument (selfTy, VD);
375+ } else if (!initializedViaAccessor.empty ()) {
376+ // Allocate "self" on stack which we are going to use to
377+ // reference/init fields and then load to return.
378+ resultSlot = SGF.emitTemporaryAllocation (Loc, selfTy);
327379 }
328380
329381 LoweredParamsInContextGenerator loweredParams (SGF);
@@ -343,15 +395,34 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
343395 (void ) loweredParams.claimNext ();
344396 loweredParams.finish ();
345397
346- auto *decl = selfTy.getStructOrBoundGenericStruct ();
347- assert (decl && " not a struct?!" );
348-
349398 auto subs = getSubstitutionsForPropertyInitializer (decl, decl);
350399
351400 // If we have an indirect return slot, initialize it in-place.
352401 if (resultSlot) {
402+ // Tracks all the init accessors we have emitted
403+ // because they can initialize more than one property.
404+ llvm::SmallPtrSet<AccessorDecl *, 2 > emittedInitAccessors;
405+
353406 auto elti = elements.begin (), eltEnd = elements.end ();
354407 for (VarDecl *field : decl->getStoredProperties ()) {
408+
409+ // Handle situations where this stored propery is initialized
410+ // via a call to an init accessor on some other property.
411+ if (initializedViaAccessor.count (field)) {
412+ auto *initProperty = initializedViaAccessor.find (field)->second ;
413+ auto *initAccessor = initProperty->getAccessor (AccessorKind::Init);
414+
415+ if (emittedInitAccessors.count (initAccessor))
416+ continue ;
417+
418+ emitApplyOfInitAccessor (SGF, Loc, initAccessor, resultSlot, selfTy,
419+ std::move (*elti));
420+
421+ emittedInitAccessors.insert (initAccessor);
422+ ++elti;
423+ continue ;
424+ }
425+
355426 auto fieldTy =
356427 selfTy.getFieldType (field, SGF.SGM .M , SGF.getTypeExpansionContext ());
357428 SILValue slot =
@@ -423,6 +494,16 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
423494 }
424495 }
425496
497+ // Load as "take" from our stack allocation and return.
498+ if (!selfTy.isAddress () && !initializedViaAccessor.empty ()) {
499+ auto resultValue = SGF.B .emitLoadValueOperation (
500+ Loc, resultSlot, LoadOwnershipQualifier::Take);
501+
502+ SGF.B .createReturn (ImplicitReturnLocation (Loc), resultValue,
503+ std::move (functionLevelScope));
504+ return ;
505+ }
506+
426507 SGF.B .createReturn (ImplicitReturnLocation (Loc),
427508 SGF.emitEmptyTuple (Loc), std::move (functionLevelScope));
428509 return ;
0 commit comments