@@ -39,59 +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
- });
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
+ }
67
71
}
68
72
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
+ }
95
78
}
96
79
97
80
void TupleInitialization::finishUninitialized (SILGenFunction &SGF) {
0 commit comments