mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge branch 'main' into mpokhylets/isolated-deinit
This commit is contained in:
@@ -543,10 +543,37 @@ public:
|
||||
RangeIterationHelpers::MapFunctor());
|
||||
}
|
||||
|
||||
void visitUsers(llvm::function_ref<void(SILInstruction *, LifetimeEnding)>
|
||||
visitor) const {
|
||||
for (auto &pair : users) {
|
||||
visitor(pair.first, pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
void print(llvm::raw_ostream &OS) const;
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
/// Recording liveness boundary at some level of detail; see concrete subclasses
|
||||
/// PrunedLivenessBoundary and PrunedLivenessBlockBoundary.
|
||||
struct AnyPrunedLivenessBoundary {
|
||||
virtual ~AnyPrunedLivenessBoundary() {}
|
||||
/// Targets whose single predecessor has at least one non-boundary successor.
|
||||
SmallVector<SILBasicBlock *, 8> boundaryEdges;
|
||||
|
||||
friend class SSAPrunedLiveness;
|
||||
friend class MultiDefPrunedLiveness;
|
||||
|
||||
private:
|
||||
virtual void findBoundaryInSSADefBlock(SILNode *ssaDef,
|
||||
const PrunedLiveness &liveness) = 0;
|
||||
virtual void
|
||||
findBoundaryInMultiDefBlock(SILBasicBlock *block, bool isLiveOut,
|
||||
const MultiDefPrunedLiveness &liveness) = 0;
|
||||
virtual void findBoundaryInNonDefBlock(SILBasicBlock *block,
|
||||
const PrunedLiveness &liveness) = 0;
|
||||
};
|
||||
|
||||
/// Record the last use points and CFG edges that form the boundary of
|
||||
/// PrunedLiveness.
|
||||
///
|
||||
@@ -558,9 +585,8 @@ public:
|
||||
/// Each boundary edge is identified by its target block. The source of the edge
|
||||
/// is the target block's single predecessor which must have at least one other
|
||||
/// non-boundary successor.
|
||||
struct PrunedLivenessBoundary {
|
||||
struct PrunedLivenessBoundary : AnyPrunedLivenessBoundary {
|
||||
SmallVector<SILInstruction *, 8> lastUsers;
|
||||
SmallVector<SILBasicBlock *, 8> boundaryEdges;
|
||||
SmallVector<SILNode *, 1> deadDefs;
|
||||
|
||||
void clear() {
|
||||
@@ -579,6 +605,39 @@ struct PrunedLivenessBoundary {
|
||||
|
||||
void print(llvm::raw_ostream &OS) const;
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
void findBoundaryInSSADefBlock(SILNode *ssaDef,
|
||||
const PrunedLiveness &liveness) override;
|
||||
void
|
||||
findBoundaryInMultiDefBlock(SILBasicBlock *block, bool isLiveOut,
|
||||
const MultiDefPrunedLiveness &liveness) override;
|
||||
void findBoundaryInNonDefBlock(SILBasicBlock *block,
|
||||
const PrunedLiveness &liveness) override;
|
||||
};
|
||||
|
||||
/// Record the blocks which either contain last use points or are boundary edge
|
||||
/// targets.
|
||||
///
|
||||
/// Enables clients only interested in block-level details to avoid expensive
|
||||
/// and for-them wasteful instruction list iteration.
|
||||
struct PrunedLivenessBlockBoundary : AnyPrunedLivenessBoundary {
|
||||
/// Blocks containing last users or dead defs.
|
||||
SmallVector<SILBasicBlock *, 8> endBlocks;
|
||||
|
||||
void clear() {
|
||||
endBlocks.clear();
|
||||
boundaryEdges.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
void findBoundaryInSSADefBlock(SILNode *ssaDef,
|
||||
const PrunedLiveness &liveness) override;
|
||||
void
|
||||
findBoundaryInMultiDefBlock(SILBasicBlock *block, bool isLiveOut,
|
||||
const MultiDefPrunedLiveness &liveness) override;
|
||||
void findBoundaryInNonDefBlock(SILBasicBlock *block,
|
||||
const PrunedLiveness &liveness) override;
|
||||
};
|
||||
|
||||
/// PrunedLiveness with information about defs for computing the live range
|
||||
@@ -689,7 +748,7 @@ public:
|
||||
/// The computed boundary will completely post-dominate, including dead end
|
||||
/// paths. The client should query DeadEndBlocks to ignore those dead end
|
||||
/// paths.
|
||||
void computeBoundary(PrunedLivenessBoundary &boundary) const;
|
||||
void computeBoundary(AnyPrunedLivenessBoundary &boundary) const;
|
||||
|
||||
/// Compute the boundary from a backward CFG traversal from a known set of
|
||||
/// jointly post-dominating blocks. Avoids the need to record an ordered list
|
||||
@@ -765,7 +824,7 @@ public:
|
||||
|
||||
/// SSA implementation of computeBoundary.
|
||||
void findBoundariesInBlock(SILBasicBlock *block, bool isLiveOut,
|
||||
PrunedLivenessBoundary &boundary) const;
|
||||
AnyPrunedLivenessBoundary &boundary) const;
|
||||
|
||||
/// Compute liveness for a single SSA definition. The lifetime-ending uses are
|
||||
/// also recorded--destroy_value or end_borrow.
|
||||
@@ -853,9 +912,9 @@ public:
|
||||
|
||||
/// Multi-Def implementation of computeBoundary.
|
||||
void findBoundariesInBlock(SILBasicBlock *block, bool isLiveOut,
|
||||
PrunedLivenessBoundary &boundary) const;
|
||||
AnyPrunedLivenessBoundary &boundary) const;
|
||||
|
||||
/// Compute liveness for a all currently initialized definitions. The
|
||||
/// Compute liveness for all currently initialized definitions. The
|
||||
/// lifetime-ending uses are also recorded--destroy_value or
|
||||
/// end_borrow. However destroy_values might not jointly-post dominate if
|
||||
/// dead-end blocks are present.
|
||||
@@ -872,6 +931,9 @@ public:
|
||||
/// also lack scope-ending instructions, so the liveness of their nested uses
|
||||
/// may be ignored.
|
||||
LiveRangeSummary computeSimple();
|
||||
|
||||
friend struct PrunedLivenessBoundary;
|
||||
friend struct PrunedLivenessBlockBoundary;
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -60,9 +60,8 @@ struct SubstitutionMapWithLocalArchetypes {
|
||||
|
||||
// Map the local archetype to an interface type in the new generic
|
||||
// signature.
|
||||
MapLocalArchetypesOutOfContext mapOutOfContext(BaseGenericSig,
|
||||
CapturedEnvs);
|
||||
auto interfaceTy = mapOutOfContext(local);
|
||||
auto interfaceTy = mapLocalArchetypesOutOfContext(
|
||||
local, BaseGenericSig, CapturedEnvs);
|
||||
|
||||
// Map this interface type into the new generic environment to get
|
||||
// a primary archetype.
|
||||
|
||||
@@ -56,7 +56,8 @@ enum IsThunk_t {
|
||||
IsNotThunk,
|
||||
IsThunk,
|
||||
IsReabstractionThunk,
|
||||
IsSignatureOptimizedThunk
|
||||
IsSignatureOptimizedThunk,
|
||||
IsBackDeployedThunk,
|
||||
};
|
||||
enum IsDynamicallyReplaceable_t {
|
||||
IsNotDynamic,
|
||||
@@ -368,7 +369,7 @@ private:
|
||||
///
|
||||
/// The inliner uses this information to avoid inlining (non-trivial)
|
||||
/// functions into the thunk.
|
||||
unsigned Thunk : 2;
|
||||
unsigned Thunk : 3;
|
||||
|
||||
/// The scope in which the parent class can be subclassed, if this is a method
|
||||
/// which is contained in the vtable of that class.
|
||||
@@ -486,6 +487,7 @@ private:
|
||||
break;
|
||||
case IsThunk:
|
||||
case IsReabstractionThunk:
|
||||
case IsBackDeployedThunk:
|
||||
thunkCanHaveSubclassScope = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -722,8 +722,8 @@ public:
|
||||
/// Run the given function for each local archetype this instruction
|
||||
/// defines, passing the value that should be used to record the
|
||||
/// dependency.
|
||||
void forEachDefinedLocalArchetype(
|
||||
llvm::function_ref<void(CanLocalArchetypeType archetype,
|
||||
void forEachDefinedLocalEnvironment(
|
||||
llvm::function_ref<void(GenericEnvironment *genericEnv,
|
||||
SILValue typeDependency)> function) const;
|
||||
bool definesLocalArchetypes() const;
|
||||
|
||||
@@ -8194,8 +8194,8 @@ class OpenPackElementInst final
|
||||
public:
|
||||
/// Call the given function for each element archetype that this
|
||||
/// instruction opens.
|
||||
void forEachDefinedLocalArchetype(
|
||||
llvm::function_ref<void(CanLocalArchetypeType, SILValue)> fn) const;
|
||||
void forEachDefinedLocalEnvironment(
|
||||
llvm::function_ref<void(GenericEnvironment *, SILValue)> fn) const;
|
||||
|
||||
GenericEnvironment *getOpenedGenericEnvironment() const {
|
||||
return Env;
|
||||
|
||||
@@ -343,7 +343,7 @@ private:
|
||||
/// projections, shared between all functions in the module.
|
||||
std::unique_ptr<IndexTrieNode> indexTrieRoot;
|
||||
|
||||
/// A mapping from root local archetypes to the instructions which define
|
||||
/// A mapping from local generic environments to the instructions which define
|
||||
/// them.
|
||||
///
|
||||
/// The value is either a SingleValueInstruction or a PlaceholderValue,
|
||||
@@ -351,10 +351,10 @@ private:
|
||||
/// deserializing SIL, where local archetypes can be forward referenced.
|
||||
///
|
||||
/// In theory we wouldn't need to have the SILFunction in the key, because
|
||||
/// local archetypes \em should be unique across the module. But currently
|
||||
/// local environments should be unique across the module. But currently
|
||||
/// in some rare cases SILGen re-uses the same local archetype for multiple
|
||||
/// functions.
|
||||
using LocalArchetypeKey = std::pair<LocalArchetypeType *, SILFunction *>;
|
||||
using LocalArchetypeKey = std::pair<GenericEnvironment *, SILFunction *>;
|
||||
llvm::DenseMap<LocalArchetypeKey, SILValue> RootLocalArchetypeDefs;
|
||||
|
||||
/// The number of PlaceholderValues in RootLocalArchetypeDefs.
|
||||
@@ -451,6 +451,27 @@ public:
|
||||
hasAccessMarkerHandler = true;
|
||||
}
|
||||
|
||||
/// Returns the instruction which defines the given local generic environment,
|
||||
/// e.g. an open_existential_addr.
|
||||
///
|
||||
/// In case the generic environment is not defined yet (e.g. during parsing or
|
||||
/// deserialization), a PlaceholderValue is returned. This should not be the
|
||||
/// case outside of parsing or deserialization.
|
||||
SILValue getLocalGenericEnvironmentDef(GenericEnvironment *genericEnv,
|
||||
SILFunction *inFunction);
|
||||
|
||||
/// Returns the instruction which defines the given local generic environment,
|
||||
/// e.g. an open_existential_addr.
|
||||
///
|
||||
/// In contrast to getLocalGenericEnvironmentDef, it is required that all local
|
||||
/// generic environments are resolved.
|
||||
SingleValueInstruction *
|
||||
getLocalGenericEnvironmentDefInst(GenericEnvironment *genericEnv,
|
||||
SILFunction *inFunction) {
|
||||
return dyn_cast<SingleValueInstruction>(
|
||||
getLocalGenericEnvironmentDef(genericEnv, inFunction));
|
||||
}
|
||||
|
||||
/// Returns the instruction which defines the given root local archetype,
|
||||
/// e.g. an open_existential_addr.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user