|
19 | 19 | #include "swift/Basic/LLVM.h"
|
20 | 20 | #include "swift/SIL/SILFunction.h"
|
21 | 21 | #include "swift/SIL/SILInstruction.h"
|
| 22 | +#include "swift/SILOptimizer/Utils/SILIsolationInfo.h" |
22 | 23 |
|
23 | 24 | #include "llvm/ADT/MapVector.h"
|
24 | 25 | #include "llvm/ADT/STLExtras.h"
|
@@ -95,311 +96,6 @@ struct DenseMapInfo<swift::PartitionPrimitives::Region> {
|
95 | 96 |
|
96 | 97 | namespace swift {
|
97 | 98 |
|
98 |
| -class ActorInstance { |
99 |
| -public: |
100 |
| - enum class Kind : uint8_t { |
101 |
| - Value, |
102 |
| - ActorAccessorInit = 0x1, |
103 |
| - }; |
104 |
| - |
105 |
| - llvm::PointerIntPair<SILValue, 1> value; |
106 |
| - |
107 |
| - ActorInstance(SILValue value, Kind kind) |
108 |
| - : value(value, std::underlying_type<Kind>::type(kind)) {} |
109 |
| - |
110 |
| -public: |
111 |
| - ActorInstance() : ActorInstance(SILValue(), Kind::Value) {} |
112 |
| - |
113 |
| - static ActorInstance getForValue(SILValue value) { |
114 |
| - return ActorInstance(value, Kind::Value); |
115 |
| - } |
116 |
| - |
117 |
| - static ActorInstance getForActorAccessorInit() { |
118 |
| - return ActorInstance(SILValue(), Kind::ActorAccessorInit); |
119 |
| - } |
120 |
| - |
121 |
| - explicit operator bool() const { return bool(value.getOpaqueValue()); } |
122 |
| - |
123 |
| - Kind getKind() const { return Kind(value.getInt()); } |
124 |
| - |
125 |
| - SILValue getValue() const { |
126 |
| - assert(getKind() == Kind::Value); |
127 |
| - return value.getPointer(); |
128 |
| - } |
129 |
| - |
130 |
| - bool isValue() const { return getKind() == Kind::Value; } |
131 |
| - |
132 |
| - bool isAccessorInit() const { return getKind() == Kind::ActorAccessorInit; } |
133 |
| - |
134 |
| - bool operator==(const ActorInstance &other) const { |
135 |
| - // If both are null, return true. |
136 |
| - if (!bool(*this) && !bool(other)) |
137 |
| - return true; |
138 |
| - |
139 |
| - // Otherwise, check if the kinds match. |
140 |
| - if (getKind() != other.getKind()) |
141 |
| - return false; |
142 |
| - |
143 |
| - // Now that we know that the kinds match, perform the kind specific check. |
144 |
| - switch (getKind()) { |
145 |
| - case Kind::Value: |
146 |
| - return getValue() == other.getValue(); |
147 |
| - case Kind::ActorAccessorInit: |
148 |
| - return true; |
149 |
| - } |
150 |
| - } |
151 |
| - |
152 |
| - bool operator!=(const ActorInstance &other) const { |
153 |
| - return !(*this == other); |
154 |
| - } |
155 |
| -}; |
156 |
| - |
157 |
| -class SILIsolationInfo { |
158 |
| -public: |
159 |
| - /// The lattice is: |
160 |
| - /// |
161 |
| - /// Unknown -> Disconnected -> TransferringParameter -> Task -> Actor. |
162 |
| - /// |
163 |
| - /// Unknown means no information. We error when merging on it. |
164 |
| - enum Kind { |
165 |
| - Unknown, |
166 |
| - Disconnected, |
167 |
| - Task, |
168 |
| - Actor, |
169 |
| - }; |
170 |
| - |
171 |
| -private: |
172 |
| - Kind kind; |
173 |
| - |
174 |
| - /// The actor isolation if this value has one. The default unspecified case |
175 |
| - /// otherwise. |
176 |
| - ActorIsolation actorIsolation; |
177 |
| - |
178 |
| - /// This is the value that we got isolation from if we were able to find |
179 |
| - /// one. Used for isolation history. |
180 |
| - SILValue isolatedValue; |
181 |
| - |
182 |
| - /// If set this is the SILValue that represents the actor instance that we |
183 |
| - /// derived isolatedValue from. |
184 |
| - /// |
185 |
| - /// If set to (SILValue(), 1), then we are in an |
186 |
| - ActorInstance actorInstance; |
187 |
| - |
188 |
| - SILIsolationInfo(SILValue isolatedValue, SILValue actorInstance, |
189 |
| - ActorIsolation actorIsolation) |
190 |
| - : kind(Actor), actorIsolation(actorIsolation), |
191 |
| - isolatedValue(isolatedValue), |
192 |
| - actorInstance(ActorInstance::getForValue(actorInstance)) { |
193 |
| - assert((!actorInstance || |
194 |
| - (actorIsolation.getKind() == ActorIsolation::ActorInstance && |
195 |
| - actorInstance->getType() |
196 |
| - .getASTType() |
197 |
| - ->lookThroughAllOptionalTypes() |
198 |
| - ->getAnyActor())) && |
199 |
| - "actorInstance must be an actor if it is non-empty"); |
200 |
| - } |
201 |
| - |
202 |
| - SILIsolationInfo(SILValue isolatedValue, ActorInstance actorInstance, |
203 |
| - ActorIsolation actorIsolation) |
204 |
| - : kind(Actor), actorIsolation(actorIsolation), |
205 |
| - isolatedValue(isolatedValue), actorInstance(actorInstance) { |
206 |
| - assert(actorInstance); |
207 |
| - assert(actorIsolation.getKind() == ActorIsolation::ActorInstance); |
208 |
| - } |
209 |
| - |
210 |
| - SILIsolationInfo(Kind kind, SILValue isolatedValue) |
211 |
| - : kind(kind), actorIsolation(), isolatedValue(isolatedValue) {} |
212 |
| - |
213 |
| - SILIsolationInfo(Kind kind) : kind(kind), actorIsolation() {} |
214 |
| - |
215 |
| -public: |
216 |
| - SILIsolationInfo() : kind(Kind::Unknown), actorIsolation() {} |
217 |
| - |
218 |
| - operator bool() const { return kind != Kind::Unknown; } |
219 |
| - |
220 |
| - operator Kind() const { return kind; } |
221 |
| - |
222 |
| - Kind getKind() const { return kind; } |
223 |
| - |
224 |
| - bool isDisconnected() const { return kind == Kind::Disconnected; } |
225 |
| - bool isActorIsolated() const { return kind == Kind::Actor; } |
226 |
| - bool isTaskIsolated() const { return kind == Kind::Task; } |
227 |
| - |
228 |
| - void print(llvm::raw_ostream &os) const; |
229 |
| - |
230 |
| - SWIFT_DEBUG_DUMP { |
231 |
| - print(llvm::dbgs()); |
232 |
| - llvm::dbgs() << '\n'; |
233 |
| - } |
234 |
| - |
235 |
| - void printForDiagnostics(llvm::raw_ostream &os) const; |
236 |
| - |
237 |
| - SWIFT_DEBUG_DUMPER(dumpForDiagnostics()) { |
238 |
| - printForDiagnostics(llvm::dbgs()); |
239 |
| - llvm::dbgs() << '\n'; |
240 |
| - } |
241 |
| - |
242 |
| - ActorIsolation getActorIsolation() const { |
243 |
| - assert(kind == Actor); |
244 |
| - return actorIsolation; |
245 |
| - } |
246 |
| - |
247 |
| - /// If we are actor or task isolated and could find a specific value that |
248 |
| - /// caused the isolation, put it here. Used for isolation history. |
249 |
| - SILValue getIsolatedValue() const { |
250 |
| - assert(kind == Task || kind == Actor); |
251 |
| - return isolatedValue; |
252 |
| - } |
253 |
| - |
254 |
| - /// Return the specific SILValue for the actor that our isolated value is |
255 |
| - /// isolated to if one exists. |
256 |
| - ActorInstance getActorInstance() const { |
257 |
| - assert(kind == Actor); |
258 |
| - return actorInstance; |
259 |
| - } |
260 |
| - |
261 |
| - bool hasActorIsolation() const { return kind == Actor; } |
262 |
| - |
263 |
| - bool hasIsolatedValue() const { |
264 |
| - return (kind == Task || kind == Actor) && bool(isolatedValue); |
265 |
| - } |
266 |
| - |
267 |
| - [[nodiscard]] SILIsolationInfo merge(SILIsolationInfo other) const; |
268 |
| - |
269 |
| - static SILIsolationInfo getDisconnected() { return {Kind::Disconnected}; } |
270 |
| - |
271 |
| - /// Create an actor isolation for a value that we know is actor isolated to a |
272 |
| - /// specific actor, but we do not know the specific instance yet. |
273 |
| - /// |
274 |
| - /// This can occur when closing over a closure with an isolated parameter or |
275 |
| - /// if we are determining isolation of a function_ref that takes an isolated |
276 |
| - /// parameter. In both cases, we cannot know what the actual isolation is |
277 |
| - /// until we invoke the closure or function. |
278 |
| - /// |
279 |
| - /// TODO: This is just a stub currently until I implement the flow sensitive |
280 |
| - /// part. We just treat all instances the same. There are tests that validate |
281 |
| - /// this behavior. |
282 |
| - static SILIsolationInfo |
283 |
| - getFlowSensitiveActorIsolated(SILValue isolatedValue, |
284 |
| - ActorIsolation actorIsolation) { |
285 |
| - return {isolatedValue, SILValue(), actorIsolation}; |
286 |
| - } |
287 |
| - |
288 |
| - /// Only use this as a fallback if we cannot find better information. |
289 |
| - static SILIsolationInfo |
290 |
| - getWithIsolationCrossing(ApplyIsolationCrossing crossing) { |
291 |
| - if (crossing.getCalleeIsolation().isActorIsolated()) { |
292 |
| - // SIL level, just let it through |
293 |
| - return SILIsolationInfo(SILValue(), SILValue(), |
294 |
| - crossing.getCalleeIsolation()); |
295 |
| - } |
296 |
| - |
297 |
| - return {}; |
298 |
| - } |
299 |
| - |
300 |
| - static SILIsolationInfo getActorInstanceIsolated(SILValue isolatedValue, |
301 |
| - SILValue actorInstance, |
302 |
| - NominalTypeDecl *typeDecl) { |
303 |
| - assert(actorInstance); |
304 |
| - if (!typeDecl->isAnyActor()) { |
305 |
| - assert(!swift::getActorIsolation(typeDecl).isGlobalActor() && |
306 |
| - "Should have called getGlobalActorIsolated"); |
307 |
| - return {}; |
308 |
| - } |
309 |
| - return {isolatedValue, actorInstance, |
310 |
| - ActorIsolation::forActorInstanceSelf(typeDecl)}; |
311 |
| - } |
312 |
| - |
313 |
| - static SILIsolationInfo getActorInstanceIsolated(SILValue isolatedValue, |
314 |
| - ActorInstance actorInstance, |
315 |
| - NominalTypeDecl *typeDecl) { |
316 |
| - assert(actorInstance); |
317 |
| - if (!typeDecl->isAnyActor()) { |
318 |
| - assert(!swift::getActorIsolation(typeDecl).isGlobalActor() && |
319 |
| - "Should have called getGlobalActorIsolated"); |
320 |
| - return {}; |
321 |
| - } |
322 |
| - return {isolatedValue, actorInstance, |
323 |
| - ActorIsolation::forActorInstanceSelf(typeDecl)}; |
324 |
| - } |
325 |
| - |
326 |
| - /// A special actor instance isolated for partial apply cases where we do not |
327 |
| - /// close over the isolated parameter and thus do not know the actual actor |
328 |
| - /// instance that we are going to use. |
329 |
| - static SILIsolationInfo |
330 |
| - getPartialApplyActorInstanceIsolated(SILValue isolatedValue, |
331 |
| - NominalTypeDecl *typeDecl) { |
332 |
| - if (!typeDecl->isAnyActor()) { |
333 |
| - assert(!swift::getActorIsolation(typeDecl).isGlobalActor() && |
334 |
| - "Should have called getGlobalActorIsolated"); |
335 |
| - return {}; |
336 |
| - } |
337 |
| - return {isolatedValue, SILValue(), |
338 |
| - ActorIsolation::forActorInstanceSelf(typeDecl)}; |
339 |
| - } |
340 |
| - |
341 |
| - static SILIsolationInfo getGlobalActorIsolated(SILValue value, |
342 |
| - Type globalActorType) { |
343 |
| - return {value, SILValue() /*no actor instance*/, |
344 |
| - ActorIsolation::forGlobalActor(globalActorType)}; |
345 |
| - } |
346 |
| - |
347 |
| - static SILIsolationInfo getGlobalActorIsolated(SILValue value, |
348 |
| - ValueDecl *decl) { |
349 |
| - auto isolation = swift::getActorIsolation(decl); |
350 |
| - if (!isolation.isGlobalActor()) |
351 |
| - return {}; |
352 |
| - return SILIsolationInfo::getGlobalActorIsolated(value, |
353 |
| - isolation.getGlobalActor()); |
354 |
| - } |
355 |
| - |
356 |
| - static SILIsolationInfo getTaskIsolated(SILValue value) { |
357 |
| - return {Kind::Task, value}; |
358 |
| - } |
359 |
| - |
360 |
| - /// Attempt to infer the isolation region info for \p inst. |
361 |
| - static SILIsolationInfo get(SILInstruction *inst); |
362 |
| - |
363 |
| - /// Attempt to infer the isolation region info for \p arg. |
364 |
| - static SILIsolationInfo get(SILArgument *arg); |
365 |
| - |
366 |
| - static SILIsolationInfo get(SILValue value) { |
367 |
| - if (auto *arg = dyn_cast<SILArgument>(value)) |
368 |
| - return get(arg); |
369 |
| - if (auto *inst = dyn_cast<SingleValueInstruction>(value)) |
370 |
| - return get(inst); |
371 |
| - return {}; |
372 |
| - } |
373 |
| - |
374 |
| - /// A helper that is used to ensure that we treat certain builtin values as |
375 |
| - /// non-Sendable that the AST level otherwise thinks are non-Sendable. |
376 |
| - /// |
377 |
| - /// E.x.: Builtin.RawPointer and Builtin.NativeObject |
378 |
| - /// |
379 |
| - /// TODO: Fix the type checker. |
380 |
| - static bool isNonSendableType(SILType type, SILFunction *fn); |
381 |
| - |
382 |
| - static bool isNonSendableType(SILValue value) { |
383 |
| - return isNonSendableType(value->getType(), value->getFunction()); |
384 |
| - } |
385 |
| - |
386 |
| - bool hasSameIsolation(ActorIsolation actorIsolation) const; |
387 |
| - |
388 |
| - /// Returns true if \p this and \p other have the same isolation. It allows |
389 |
| - /// for the isolated values if any to not match. |
390 |
| - /// |
391 |
| - /// This is useful if one has two non-Sendable values projected from the same |
392 |
| - /// actor or global actor isolated value. E.x.: two different ref_element_addr |
393 |
| - /// from the same actor. |
394 |
| - bool hasSameIsolation(const SILIsolationInfo &other) const; |
395 |
| - |
396 |
| - /// Returns true if this SILIsolationInfo is deeply equal to other. This means |
397 |
| - /// that the isolation and the isolated value match. |
398 |
| - bool isEqual(const SILIsolationInfo &other) const; |
399 |
| - |
400 |
| - void Profile(llvm::FoldingSetNodeID &id) const; |
401 |
| -}; |
402 |
| - |
403 | 99 | class Partition;
|
404 | 100 | class TransferringOperandToStateMap;
|
405 | 101 |
|
|
0 commit comments