@@ -76,36 +76,53 @@ namespace {
7676 };
7777} // end anonymous namespace
7878
79- void TupleInitialization::copyOrInitValueInto (SILGenFunction &SGF,
80- SILLocation loc,
81- ManagedValue valueMV,
82- bool isInit) {
83- // A scalar value is being copied into the tuple, break it into elements
84- // and assign/init each element in turn.
85- SILValue value = valueMV.forward (SGF);
86- auto sourceType = valueMV.getType ().castTo <TupleType>();
87- auto sourceSILType = value->getType ();
79+ static void copyOrInitValueIntoHelper (
80+ SILGenFunction &SGF, SILLocation loc, ManagedValue value, bool isInit,
81+ ArrayRef<InitializationPtr> subInitializations,
82+ llvm::function_ref<ManagedValue(ManagedValue, unsigned , SILType)> func) {
83+ auto sourceType = value.getType ().castTo <TupleType>();
84+ auto sourceSILType = value.getType ();
8885 for (unsigned i = 0 , e = sourceType->getNumElements (); i != e; ++i) {
8986 SILType fieldTy = sourceSILType.getTupleElementType (i);
90- auto &fieldTL = SGF.getTypeLowering (fieldTy);
91-
92- SILValue member;
93- if (value->getType ().isAddress ()) {
94- member = SGF.B .createTupleElementAddr (loc, value, i, fieldTy);
95- if (!fieldTL.isAddressOnly ())
96- member =
97- fieldTL.emitLoad (SGF.B , loc, member, LoadOwnershipQualifier::Take);
98- } else {
99- member = SGF.B .createTupleExtract (loc, value, i, fieldTy);
100- }
101-
102- auto elt = SGF.emitManagedRValueWithCleanup (member, fieldTL);
103-
104- SubInitializations[i]->copyOrInitValueInto (SGF, loc, elt, isInit);
105- SubInitializations[i]->finishInitialization (SGF);
87+ ManagedValue elt = func (value, i, fieldTy);
88+ subInitializations[i]->copyOrInitValueInto (SGF, loc, elt, isInit);
89+ subInitializations[i]->finishInitialization (SGF);
10690 }
10791}
10892
93+ void TupleInitialization::copyOrInitValueInto (SILGenFunction &SGF,
94+ SILLocation loc,
95+ ManagedValue value, bool isInit) {
96+ // In the object case, we perform a borrow + extract + copy sequence. This is
97+ // because we do not have a destructure operation.
98+ if (value.getType ().isObject ()) {
99+ value = value.borrow (SGF, loc);
100+ return copyOrInitValueIntoHelper (
101+ SGF, loc, value, isInit, SubInitializations,
102+ [&](ManagedValue aggregate, unsigned i,
103+ SILType fieldType) -> ManagedValue {
104+ auto elt = SGF.B .createTupleExtract (loc, aggregate, i, fieldType);
105+ return SGF.B .createCopyValue (loc, elt);
106+ });
107+ }
108+
109+ // In the address case, we can support takes directly, so forward the cleanup
110+ // of the aggregate and create takes of the underlying addresses.
111+ value = ManagedValue::forUnmanaged (value.forward (SGF));
112+ return copyOrInitValueIntoHelper (
113+ SGF, loc, value, isInit, SubInitializations,
114+ [&](ManagedValue aggregate, unsigned i,
115+ SILType fieldType) -> ManagedValue {
116+ ManagedValue elt =
117+ SGF.B .createTupleElementAddr (loc, value, i, fieldType);
118+ if (!fieldType.isAddressOnly (SGF.F .getModule ())) {
119+ return SGF.B .createLoadTake (loc, elt);
120+ }
121+
122+ return SGF.emitManagedRValueWithCleanup (elt.getValue ());
123+ });
124+ }
125+
109126void TupleInitialization::finishUninitialized (SILGenFunction &gen) {
110127 for (auto &subInit : SubInitializations) {
111128 subInit->finishUninitialized (gen);
0 commit comments