@@ -142,6 +142,35 @@ class FormalEvaluationContext {
142
142
void dump (SILGenFunction &SGF);
143
143
};
144
144
145
+ // / A scope associated with the beginning of the formal evaluation of an lvalue.
146
+ // /
147
+ // / A formal evaluation of an lvalue occurs when emitting:
148
+ // /
149
+ // / 1. accessors.
150
+ // / 2. getters.
151
+ // / 3. materializeForSets.
152
+ // /
153
+ // / for lvalues. The general form of such an evaluation is:
154
+ // /
155
+ // / formally evaluate the lvalue "x" into memory
156
+ // / begin formal access to "x"
157
+ // / end formal access to "x"
158
+ // / ... *more formal access*
159
+ // / begin formal access to "x"
160
+ // / end formal access to "x"
161
+ // / end formal evaluation of lvalue into memory
162
+ // /
163
+ // / *NOTE* All formal access contain a pointer to a cleanup in the normal
164
+ // / cleanup stack. This is to ensure that when SILGen calls
165
+ // / Cleanups.emitBranchAndCleanups (and other special cleanup code along error
166
+ // / edges), writebacks are properly created. What is key to notice is that all
167
+ // / of these cleanup emission types are non-destructive. Contrast this with
168
+ // / normal scope popping. In such a case, the scope pop is destructive. This
169
+ // / means that any pointers from the formal access to the cleanup stack is now
170
+ // / invalid.
171
+ // /
172
+ // / In order to avoid this issue, it is important to /never/ create a formal
173
+ // / access cleanup when the "top level" scope is not a formal evaluation scope.
145
174
class FormalEvaluationScope {
146
175
SILGenFunction &SGF;
147
176
llvm::Optional<FormalEvaluationContext::stable_iterator> savedDepth;
0 commit comments