mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #23190 from atrick/cleanup-accessopts
Cleanup/fix AccessEnforcementOpts
This commit is contained in:
@@ -122,8 +122,8 @@ template <> struct DenseMapInfo<swift::StorageAccessInfo> {
|
||||
}
|
||||
|
||||
namespace swift {
|
||||
/// The per-function result of AccessedStorageAnalysis.
|
||||
///
|
||||
using AccessedStorageSet = llvm::SmallDenseSet<StorageAccessInfo, 8>;
|
||||
|
||||
/// Records each unique AccessedStorage in a set of StorageAccessInfo
|
||||
/// objects. Hashing and equality only sees the AccesedStorage data. The
|
||||
/// additional StorageAccessInfo bits are recorded as results of this analysis.
|
||||
@@ -133,28 +133,32 @@ namespace swift {
|
||||
/// results, either because the call graph is unknown or the access sets are too
|
||||
/// large. It does not imply that all accesses have Unidentified
|
||||
/// AccessedStorage, which is never allowed for class or global access.
|
||||
class FunctionAccessedStorage {
|
||||
using AccessedStorageSet = llvm::SmallDenseSet<StorageAccessInfo, 8>;
|
||||
|
||||
class AccessedStorageResult {
|
||||
AccessedStorageSet storageAccessSet;
|
||||
Optional<SILAccessKind> unidentifiedAccess;
|
||||
|
||||
public:
|
||||
FunctionAccessedStorage() {}
|
||||
AccessedStorageResult() {}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Accessing the results.
|
||||
|
||||
const AccessedStorageSet &getStorageSet() const { return storageAccessSet; }
|
||||
|
||||
bool isEmpty() const {
|
||||
return storageAccessSet.empty() && !unidentifiedAccess;
|
||||
}
|
||||
|
||||
bool hasUnidentifiedAccess() const { return unidentifiedAccess != None; }
|
||||
|
||||
/// Return true if the analysis has determined all accesses of otherStorage
|
||||
/// have the [no_nested_conflict] flag set.
|
||||
///
|
||||
/// Only call this if there is no unidentifiedAccess in the function and the
|
||||
/// Only call this if there is no unidentifiedAccess in the region and the
|
||||
/// given storage is uniquely identified.
|
||||
bool hasNoNestedConflict(const AccessedStorage &otherStorage) const;
|
||||
|
||||
/// Does any of the accesses represented by this FunctionAccessedStorage
|
||||
/// Does any of the accesses represented by this AccessedStorageResult
|
||||
/// object conflict with the given access kind and storage.
|
||||
bool mayConflictWith(SILAccessKind otherAccessKind,
|
||||
const AccessedStorage &otherStorage) const;
|
||||
@@ -181,6 +185,97 @@ public:
|
||||
unidentifiedAccess = SILAccessKind::Modify;
|
||||
}
|
||||
|
||||
void setUnidentifiedAccess(SILAccessKind kind) { unidentifiedAccess = kind; }
|
||||
|
||||
/// Merge effects directly from \p RHS.
|
||||
bool mergeFrom(const AccessedStorageResult &other);
|
||||
|
||||
/// Merge the effects represented in calleeAccess into this
|
||||
/// FunctionAccessedStorage object. calleeAccess must correspond to at least
|
||||
/// one callee at the apply site `fullApply`. Merging drops any local effects,
|
||||
/// and translates parameter effects into effects on the caller-side
|
||||
/// arguments.
|
||||
///
|
||||
/// The full caller-side effects at a call site can be obtained with
|
||||
/// AccessedStorageAnalysis::getCallSiteEffects().
|
||||
bool mergeFromApply(const AccessedStorageResult &calleeAccess,
|
||||
FullApplySite fullApply);
|
||||
|
||||
/// Record any access scopes entered by the given single SIL instruction. 'I'
|
||||
/// must not be a FullApply; use mergeFromApply instead.
|
||||
void analyzeInstruction(SILInstruction *I);
|
||||
|
||||
void print(raw_ostream &os) const;
|
||||
void dump() const;
|
||||
|
||||
protected:
|
||||
std::pair<AccessedStorageSet::iterator, bool>
|
||||
insertStorageAccess(StorageAccessInfo storageAccess) {
|
||||
storageAccess.setStorageIndex(storageAccessSet.size());
|
||||
return storageAccessSet.insert(storageAccess);
|
||||
}
|
||||
|
||||
bool updateUnidentifiedAccess(SILAccessKind accessKind);
|
||||
|
||||
bool mergeAccesses(const AccessedStorageResult &other,
|
||||
std::function<StorageAccessInfo(const StorageAccessInfo &)>
|
||||
transformStorage);
|
||||
|
||||
template <typename B> void visitBeginAccess(B *beginAccess);
|
||||
};
|
||||
} // namespace swift
|
||||
|
||||
namespace swift {
|
||||
/// The per-function result of AccessedStorageAnalysis.
|
||||
class FunctionAccessedStorage {
|
||||
AccessedStorageResult accessResult;
|
||||
|
||||
public:
|
||||
FunctionAccessedStorage() {}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Accessing the results.
|
||||
|
||||
const AccessedStorageResult &getResult() const { return accessResult; }
|
||||
|
||||
bool hasUnidentifiedAccess() const {
|
||||
return accessResult.hasUnidentifiedAccess();
|
||||
}
|
||||
|
||||
/// Return true if the analysis has determined all accesses of otherStorage
|
||||
/// have the [no_nested_conflict] flag set.
|
||||
///
|
||||
/// Only call this if there is no unidentifiedAccess in the function and the
|
||||
/// given storage is uniquely identified.
|
||||
bool hasNoNestedConflict(const AccessedStorage &otherStorage) const {
|
||||
return accessResult.hasNoNestedConflict(otherStorage);
|
||||
}
|
||||
|
||||
/// Does any of the accesses represented by this FunctionAccessedStorage
|
||||
/// object conflict with the given access kind and storage.
|
||||
bool mayConflictWith(SILAccessKind otherAccessKind,
|
||||
const AccessedStorage &otherStorage) const {
|
||||
return accessResult.mayConflictWith(otherAccessKind, otherStorage);
|
||||
}
|
||||
|
||||
/// Raw access to the result for a given AccessedStorage location.
|
||||
StorageAccessInfo
|
||||
getStorageAccessInfo(const AccessedStorage &otherStorage) const {
|
||||
return accessResult.getStorageAccessInfo(otherStorage);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Constructing the results.
|
||||
|
||||
void clear() { accessResult.clear(); }
|
||||
|
||||
/// Return true if these effects are fully conservative.
|
||||
bool hasWorstEffects() { return accessResult.hasWorstEffects(); }
|
||||
|
||||
/// Sets the most conservative effects, if we don't know anything about the
|
||||
/// function.
|
||||
void setWorstEffects() { accessResult.setWorstEffects(); }
|
||||
|
||||
/// Summarize the given function's effects using this FunctionAccessedStorage
|
||||
/// object.
|
||||
//
|
||||
@@ -201,12 +296,14 @@ public:
|
||||
///
|
||||
/// TODO: Summarize ArraySemanticsCall accesses.
|
||||
bool summarizeCall(FullApplySite fullApply) {
|
||||
assert(storageAccessSet.empty() && "expected uninitialized results.");
|
||||
assert(accessResult.isEmpty() && "expected uninitialized results.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Merge effects directly from \p RHS.
|
||||
bool mergeFrom(const FunctionAccessedStorage &RHS);
|
||||
bool mergeFrom(const FunctionAccessedStorage &RHS) {
|
||||
return accessResult.mergeFrom(RHS.accessResult);
|
||||
}
|
||||
|
||||
/// Merge the effects represented in calleeAccess into this
|
||||
/// FunctionAccessedStorage object. calleeAccess must correspond to at least
|
||||
@@ -217,31 +314,19 @@ public:
|
||||
/// The full caller-side effects at a call site can be obtained with
|
||||
/// AccessedStorageAnalysis::getCallSiteEffects().
|
||||
bool mergeFromApply(const FunctionAccessedStorage &calleeAccess,
|
||||
FullApplySite fullApply);
|
||||
FullApplySite fullApply) {
|
||||
return accessResult.mergeFromApply(calleeAccess.accessResult, fullApply);
|
||||
}
|
||||
|
||||
/// Analyze the side-effects of a single SIL instruction \p I.
|
||||
/// Visited callees are added to \p BottomUpOrder until \p RecursionDepth
|
||||
/// reaches MaxRecursionDepth.
|
||||
void analyzeInstruction(SILInstruction *I);
|
||||
|
||||
void print(raw_ostream &os) const;
|
||||
void dump() const;
|
||||
|
||||
protected:
|
||||
std::pair<AccessedStorageSet::iterator, bool>
|
||||
insertStorageAccess(StorageAccessInfo storageAccess) {
|
||||
storageAccess.setStorageIndex(storageAccessSet.size());
|
||||
return storageAccessSet.insert(storageAccess);
|
||||
void analyzeInstruction(SILInstruction *I) {
|
||||
accessResult.analyzeInstruction(I);
|
||||
}
|
||||
|
||||
bool updateUnidentifiedAccess(SILAccessKind accessKind);
|
||||
|
||||
bool mergeAccesses(
|
||||
const FunctionAccessedStorage &other,
|
||||
std::function<StorageAccessInfo(const StorageAccessInfo &)>
|
||||
transformStorage);
|
||||
|
||||
template <typename B> void visitBeginAccess(B *beginAccess);
|
||||
void print(raw_ostream &os) const { accessResult.print(os); }
|
||||
void dump() const { accessResult.dump(); }
|
||||
};
|
||||
|
||||
/// Summarizes the dynamic accesses performed within a function and its
|
||||
|
||||
Reference in New Issue
Block a user