@@ -39,50 +39,42 @@ using namespace Lowering;
39
39
void Initialization::_anchor () {}
40
40
void SILDebuggerClient::anchor () {}
41
41
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
-
56
42
void TupleInitialization::copyOrInitValueInto (SILGenFunction &SGF,
57
43
SILLocation loc,
58
44
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
+
59
49
// In the object case, emit a destructure operation and return.
60
50
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
- });
67
- }
68
-
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
- assert (value.isPlusOne (SGF) && " Can not store a +0 value into memory?!" );
73
- value = ManagedValue::forUnmanaged (value.forward (SGF));
74
- return copyOrInitValueIntoHelper (
75
- SGF, loc, value, isInit, SubInitializations,
76
- [&](ManagedValue aggregate, unsigned i,
77
- SILType fieldType) -> ManagedValue {
78
- ManagedValue elt =
79
- SGF.B .createTupleElementAddr (loc, value, i, fieldType);
80
- if (!fieldType.isAddressOnly (SGF.F )) {
81
- return SGF.B .createLoadTake (loc, elt);
82
- }
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
+ }
71
+ }
83
72
84
- return SGF.emitManagedRValueWithCleanup (elt.getValue ());
85
- });
73
+ for (unsigned i : indices (destructuredValues)) {
74
+ SubInitializations[i]->copyOrInitValueInto (SGF, loc, destructuredValues[i],
75
+ isInit);
76
+ SubInitializations[i]->finishInitialization (SGF);
77
+ }
86
78
}
87
79
88
80
void TupleInitialization::finishUninitialized (SILGenFunction &SGF) {
0 commit comments