@@ -39,59 +39,42 @@ using namespace Lowering;
3939void Initialization::_anchor () {}
4040void SILDebuggerClient::anchor () {}
4141
42- static void copyOrInitValueIntoHelper (
43- SILGenFunction &SGF, SILLocation loc, ManagedValue value, bool isInit,
44- ArrayRef<InitializationPtr> subInitializations,
45- llvm::function_ref<ManagedValue(ManagedValue, unsigned , SILType)> func) {
46- auto sourceType = value.getType ().castTo <TupleType>();
47- auto sourceSILType = value.getType ();
48- for (unsigned i = 0 , e = sourceType->getNumElements (); i != e; ++i) {
49- SILType fieldTy = sourceSILType.getTupleElementType (i);
50- ManagedValue elt = func (value, i, fieldTy);
51- subInitializations[i]->copyOrInitValueInto (SGF, loc, elt, isInit);
52- subInitializations[i]->finishInitialization (SGF);
53- }
54- }
55-
5642void TupleInitialization::copyOrInitValueInto (SILGenFunction &SGF,
5743 SILLocation loc,
5844 ManagedValue value, bool isInit) {
45+ // Process all values before initialization all at once to ensure all cleanups
46+ // are setup on all tuple elements before a potential early exit.
47+ SmallVector<ManagedValue, 8 > destructuredValues;
48+
5949 // In the object case, emit a destructure operation and return.
6050 if (value.getType ().isObject ()) {
61- return SGF.B .emitDestructureValueOperation (
62- loc, value, [&](unsigned i, ManagedValue subValue) {
63- auto &subInit = SubInitializations[i];
64- subInit->copyOrInitValueInto (SGF, loc, subValue, isInit);
65- subInit->finishInitialization (SGF);
66- });
51+ SGF.B .emitDestructureValueOperation (loc, value, destructuredValues);
52+ } else {
53+ // In the address case, we forward the underlying value and store it
54+ // into memory and then create a +1 cleanup. since we assume here
55+ // that we have a +1 value since we are forwarding into memory.
56+ assert (value.isPlusOne (SGF) && " Can not store a +0 value into memory?!" );
57+ CleanupCloner cloner (SGF, value);
58+ SILValue v = value.forward (SGF);
59+
60+ auto sourceType = value.getType ().castTo <TupleType>();
61+ auto sourceSILType = value.getType ();
62+ for (unsigned i : range (sourceType->getNumElements ())) {
63+ SILType fieldTy = sourceSILType.getTupleElementType (i);
64+ SILValue elt = SGF.B .createTupleElementAddr (loc, v, i, fieldTy);
65+ if (!fieldTy.isAddressOnly (SGF.F )) {
66+ elt = SGF.B .emitLoadValueOperation (loc, elt,
67+ LoadOwnershipQualifier::Take);
68+ }
69+ destructuredValues.push_back (cloner.clone (elt));
70+ }
6771 }
6872
69- // In the address case, we forward the underlying value and store it
70- // into memory and then create a +1 cleanup. since we assume here
71- // that we have a +1 value since we are forwarding into memory.
72- //
73- // In order to ensure that we properly clean up along any failure paths, we
74- // need to mark value as being persistently active. We then unforward it once
75- // we are done.
76- assert (value.isPlusOne (SGF) && " Can not store a +0 value into memory?!" );
77- CleanupStateRestorationScope valueScope (SGF.Cleanups );
78- if (value.hasCleanup ())
79- valueScope.pushCleanupState (value.getCleanup (),
80- CleanupState::PersistentlyActive);
81- copyOrInitValueIntoHelper (
82- SGF, loc, value, isInit, SubInitializations,
83- [&](ManagedValue aggregate, unsigned i,
84- SILType fieldType) -> ManagedValue {
85- ManagedValue elt =
86- SGF.B .createTupleElementAddr (loc, value, i, fieldType);
87- if (!fieldType.isAddressOnly (SGF.F )) {
88- return SGF.B .createLoadTake (loc, elt);
89- }
90-
91- return SGF.emitManagedRValueWithCleanup (elt.getValue ());
92- });
93- std::move (valueScope).pop ();
94- value.forward (SGF);
73+ for (unsigned i : indices (destructuredValues)) {
74+ SubInitializations[i]->copyOrInitValueInto (SGF, loc, destructuredValues[i],
75+ isInit);
76+ SubInitializations[i]->finishInitialization (SGF);
77+ }
9578}
9679
9780void TupleInitialization::finishUninitialized (SILGenFunction &SGF) {
0 commit comments