Skip to content

Commit ab3d9b2

Browse files
committed
[region-isolation] Move SILIsolationInfo out of PartitionUtils into its own header/cpp file.
SILIsolationInfo is conceptually a layer that composes with PartitionUtils so it makes sense for it to be in a different file. (cherry picked from commit 3597006)
1 parent d69309e commit ab3d9b2

File tree

5 files changed

+971
-914
lines changed

5 files changed

+971
-914
lines changed

include/swift/SILOptimizer/Utils/PartitionUtils.h

Lines changed: 1 addition & 305 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/Basic/LLVM.h"
2020
#include "swift/SIL/SILFunction.h"
2121
#include "swift/SIL/SILInstruction.h"
22+
#include "swift/SILOptimizer/Utils/SILIsolationInfo.h"
2223

2324
#include "llvm/ADT/MapVector.h"
2425
#include "llvm/ADT/STLExtras.h"
@@ -95,311 +96,6 @@ struct DenseMapInfo<swift::PartitionPrimitives::Region> {
9596

9697
namespace swift {
9798

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-
40399
class Partition;
404100
class TransferringOperandToStateMap;
405101

0 commit comments

Comments
 (0)