11
11
// ===----------------------------------------------------------------------===//
12
12
13
13
#include " ArgumentSource.h"
14
+ #include " Conversion.h"
14
15
#include " Initialization.h"
15
16
#include " LValue.h"
16
17
#include " RValue.h"
@@ -901,72 +902,71 @@ static ManagedValue emitSelfForMemberInit(SILGenFunction &SGF, SILLocation loc,
901
902
SGFAccessKind::Write);
902
903
}
903
904
904
- static LValue emitLValueForMemberInit (SILGenFunction &SGF, SILLocation loc,
905
- VarDecl *selfDecl,
906
- VarDecl *property) {
907
- CanType selfFormalType = selfDecl->getType ()->getCanonicalType ();
908
- auto self = emitSelfForMemberInit (SGF, loc, selfDecl);
909
- return SGF.emitPropertyLValue (loc, self, selfFormalType, property,
910
- LValueOptions (), SGFAccessKind::Write,
911
- AccessSemantics::DirectToStorage);
912
- }
913
-
914
- // / Emit a member initialization for the members described in the
915
- // / given pattern from the given source value.
916
- static void emitMemberInit (SILGenFunction &SGF, VarDecl *selfDecl,
917
- Pattern *pattern, RValue &&src) {
905
+ // FIXME: Can emitMemberInit() share code with InitializationForPattern in
906
+ // SILGenDecl.cpp? Note that this version operates on stored properties of
907
+ // types, whereas the former only knows how to handle local bindings, but
908
+ // we could generalize it.
909
+ static InitializationPtr
910
+ emitMemberInit (SILGenFunction &SGF, VarDecl *selfDecl, Pattern *pattern) {
918
911
switch (pattern->getKind ()) {
919
912
case PatternKind::Paren:
920
913
return emitMemberInit (SGF, selfDecl,
921
- cast<ParenPattern>(pattern)->getSubPattern (),
922
- std::move (src));
914
+ cast<ParenPattern>(pattern)->getSubPattern ());
923
915
924
916
case PatternKind::Tuple: {
917
+ TupleInitialization *init = new TupleInitialization ();
925
918
auto tuple = cast<TuplePattern>(pattern);
926
- auto fields = tuple->getElements ();
927
-
928
- SmallVector<RValue, 4 > elements;
929
- std::move (src).extractElements (elements);
930
- for (unsigned i = 0 , n = fields.size (); i != n; ++i) {
931
- emitMemberInit (SGF, selfDecl, fields[i].getPattern (),
932
- std::move (elements[i]));
919
+ for (auto &elt : tuple->getElements ()) {
920
+ init->SubInitializations .push_back (
921
+ emitMemberInit (SGF, selfDecl, elt.getPattern ()));
933
922
}
934
- break ;
923
+ return InitializationPtr (init) ;
935
924
}
936
925
937
926
case PatternKind::Named: {
938
927
auto named = cast<NamedPattern>(pattern);
939
- // Form the lvalue referencing this member.
940
- FormalEvaluationScope scope (SGF);
941
- LValue memberRef = emitLValueForMemberInit (SGF, pattern, selfDecl,
942
- named->getDecl ());
943
928
944
- // Assign to it.
945
- SGF.emitAssignToLValue (pattern, std::move (src), std::move (memberRef));
946
- return ;
929
+ auto self = emitSelfForMemberInit (SGF, pattern, selfDecl);
930
+
931
+ auto *field = named->getDecl ();
932
+
933
+ auto selfTy = self.getType ();
934
+ auto fieldTy =
935
+ selfTy.getFieldType (field, SGF.SGM .M , SGF.getTypeExpansionContext ());
936
+ SILValue slot;
937
+
938
+ if (auto *structDecl = dyn_cast<StructDecl>(field->getDeclContext ())) {
939
+ slot = SGF.B .createStructElementAddr (pattern, self.forward (SGF), field,
940
+ fieldTy.getAddressType ());
941
+ } else {
942
+ assert (isa<ClassDecl>(field->getDeclContext ()));
943
+ slot = SGF.B .createRefElementAddr (pattern, self.forward (SGF), field,
944
+ fieldTy.getAddressType ());
945
+ }
946
+
947
+ return InitializationPtr (new KnownAddressInitialization (slot));
947
948
}
948
949
949
950
case PatternKind::Any:
950
- return ;
951
+ return InitializationPtr ( new BlackHoleInitialization ()); ;
951
952
952
953
case PatternKind::Typed:
953
954
return emitMemberInit (SGF, selfDecl,
954
- cast<TypedPattern>(pattern)->getSubPattern (),
955
- std::move (src));
955
+ cast<TypedPattern>(pattern)->getSubPattern ());
956
956
957
957
case PatternKind::Binding:
958
958
return emitMemberInit (SGF, selfDecl,
959
- cast<BindingPattern>(pattern)->getSubPattern (),
960
- std::move (src));
959
+ cast<BindingPattern>(pattern)->getSubPattern ());
961
960
962
961
#define PATTERN (Name, Parent )
963
962
#define REFUTABLE_PATTERN (Name, Parent ) case PatternKind::Name:
964
963
#include " swift/AST/PatternNodes.def"
965
- llvm_unreachable (" Refutable pattern in pattern binding" );
964
+ llvm_unreachable (" Refutable pattern in stored property pattern binding" );
966
965
}
967
966
}
968
967
969
- static Type getInitializationTypeInContext (
968
+ static std::pair<AbstractionPattern, CanType>
969
+ getInitializationTypeInContext (
970
970
DeclContext *fromDC, DeclContext *toDC,
971
971
Pattern *pattern) {
972
972
auto interfaceType = pattern->getType ()->mapTypeOutOfContext ();
@@ -981,9 +981,53 @@ static Type getInitializationTypeInContext(
981
981
}
982
982
}
983
983
984
- auto resultType = toDC->mapTypeIntoContext (interfaceType);
984
+ AbstractionPattern origType (
985
+ fromDC->getGenericSignatureOfContext ().getCanonicalSignature (),
986
+ interfaceType->getCanonicalType ());
987
+
988
+ auto substType = toDC->mapTypeIntoContext (interfaceType)->getCanonicalType ();
985
989
986
- return resultType;
990
+ return std::make_pair (origType, substType);
991
+ }
992
+
993
+ static void
994
+ emitAndStoreInitialValueInto (SILGenFunction &SGF,
995
+ SILLocation loc,
996
+ PatternBindingDecl *pbd, unsigned i,
997
+ SubstitutionMap subs,
998
+ AbstractionPattern origType,
999
+ CanType substType,
1000
+ Initialization *init) {
1001
+ bool injectIntoWrapper = false ;
1002
+ if (auto singleVar = pbd->getSingleVar ()) {
1003
+ auto originalVar = singleVar->getOriginalWrappedProperty ();
1004
+ if (originalVar &&
1005
+ originalVar->isPropertyMemberwiseInitializedWithWrappedType ()) {
1006
+ injectIntoWrapper = true ;
1007
+ }
1008
+ }
1009
+
1010
+ SGFContext C = (injectIntoWrapper ? SGFContext () : SGFContext (init));
1011
+
1012
+ RValue result = SGF.emitApplyOfStoredPropertyInitializer (
1013
+ pbd->getExecutableInit (i),
1014
+ pbd->getAnchoringVarDecl (i),
1015
+ subs, substType, origType, C);
1016
+
1017
+ // need to store result into the init if its in context
1018
+
1019
+ // If we have the backing storage for a property with an attached
1020
+ // property wrapper initialized with `=`, inject the value into an
1021
+ // instance of the wrapper.
1022
+ if (injectIntoWrapper) {
1023
+ auto *singleVar = pbd->getSingleVar ();
1024
+ result = maybeEmitPropertyWrapperInitFromValue (
1025
+ SGF, pbd->getExecutableInit (i),
1026
+ singleVar, subs, std::move (result));
1027
+ }
1028
+
1029
+ if (!result.isInContext ())
1030
+ std::move (result).forwardInto (SGF, loc, init);
987
1031
}
988
1032
989
1033
void SILGenFunction::emitMemberInitializers (DeclContext *dc,
@@ -1001,35 +1045,51 @@ void SILGenFunction::emitMemberInitializers(DeclContext *dc,
1001
1045
if (!init) continue ;
1002
1046
1003
1047
auto *varPattern = pbd->getPattern (i);
1048
+
1004
1049
// Cleanup after this initialization.
1005
1050
FullExpr scope (Cleanups, varPattern);
1006
1051
1007
1052
// Get the type of the initialization result, in terms
1008
1053
// of the constructor context's archetypes.
1009
- CanType resultType = getInitializationTypeInContext (
1010
- pbd->getDeclContext (), dc, varPattern)->getCanonicalType ();
1011
- AbstractionPattern origResultType (resultType);
1012
-
1013
- // FIXME: Can emitMemberInit() share code with
1014
- // InitializationForPattern in SILGenDecl.cpp?
1015
- RValue result = emitApplyOfStoredPropertyInitializer (
1016
- init, pbd->getAnchoringVarDecl (i), subs,
1017
- resultType, origResultType,
1018
- SGFContext ());
1019
-
1020
- // If we have the backing storage for a property with an attached
1021
- // property wrapper initialized with `=`, inject the value into an
1022
- // instance of the wrapper.
1023
- if (auto singleVar = pbd->getSingleVar ()) {
1024
- auto originalVar = singleVar->getOriginalWrappedProperty ();
1025
- if (originalVar &&
1026
- originalVar->isPropertyMemberwiseInitializedWithWrappedType ()) {
1027
- result = maybeEmitPropertyWrapperInitFromValue (
1028
- *this , init, singleVar, subs, std::move (result));
1029
- }
1054
+ auto resultType = getInitializationTypeInContext (
1055
+ pbd->getDeclContext (), dc, varPattern);
1056
+ AbstractionPattern origType = resultType.first ;
1057
+ CanType substType = resultType.second ;
1058
+
1059
+ // Figure out what we're initializing.
1060
+ auto memberInit = emitMemberInit (*this , selfDecl, varPattern);
1061
+
1062
+ // This whole conversion thing is about eliminating the
1063
+ // paired orig-to-subst subst-to-orig conversions that
1064
+ // will happen if the storage is at a different abstraction
1065
+ // level than the constructor. When emitApply() is used
1066
+ // to call the stored property initializer, it naturally
1067
+ // wants to convert the result back to the most substituted
1068
+ // abstraction level. To undo this, we use a converting
1069
+ // initialization and rely on the peephole that optimizes
1070
+ // out the redundant conversion.
1071
+ auto loweredResultTy = getLoweredType (origType, substType);
1072
+ auto loweredSubstTy = getLoweredType (substType);
1073
+
1074
+ if (loweredResultTy != loweredSubstTy) {
1075
+ Conversion conversion = Conversion::getSubstToOrig (
1076
+ origType, substType,
1077
+ loweredResultTy);
1078
+
1079
+ ConvertingInitialization convertingInit (conversion,
1080
+ SGFContext (memberInit.get ()));
1081
+
1082
+ emitAndStoreInitialValueInto (*this , varPattern, pbd, i, subs,
1083
+ origType, substType, &convertingInit);
1084
+
1085
+ auto finalValue = convertingInit.finishEmission (
1086
+ *this , varPattern, ManagedValue::forInContext ());
1087
+ if (!finalValue.isInContext ())
1088
+ finalValue.forwardInto (*this , varPattern, memberInit.get ());
1089
+ } else {
1090
+ emitAndStoreInitialValueInto (*this , varPattern, pbd, i, subs,
1091
+ origType, substType, memberInit.get ());
1030
1092
}
1031
-
1032
- emitMemberInit (*this , selfDecl, varPattern, std::move (result));
1033
1093
}
1034
1094
}
1035
1095
}
0 commit comments