Skip to content

Commit e53ec62

Browse files
authored
Merge pull request #17177 from rajbarik/raj-protoconfanal
ProtocolConformanceAnalysis
2 parents 3084458 + c2aef11 commit e53ec62

File tree

5 files changed

+164
-0
lines changed

5 files changed

+164
-0
lines changed

include/swift/SILOptimizer/Analysis/Analysis.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ ANALYSIS(LoopRegion)
4040
ANALYSIS(OptimizerStats)
4141
ANALYSIS(PostDominance)
4242
ANALYSIS(PostOrder)
43+
ANALYSIS(ProtocolConformance)
4344
ANALYSIS(RCIdentity)
4445
ANALYSIS(SideEffect)
4546
ANALYSIS(TypeExpansion)
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//===--- ProtocolConformanceAnalysis.h - Protocol Conformance ---*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
// This analysis collects a set of nominal types (classes, structs, and enums)
13+
// that conform to a protocol during whole module compilation. We only track
14+
// protocols that are non-public.
15+
16+
#ifndef SWIFT_SILOPTIMIZER_ANALYSIS_PROTOCOLCONFORMANCE_H
17+
#define SWIFT_SILOPTIMIZER_ANALYSIS_PROTOCOLCONFORMANCE_H
18+
19+
#include "swift/SIL/SILArgument.h"
20+
#include "swift/SIL/SILValue.h"
21+
#include "swift/SILOptimizer/Analysis/Analysis.h"
22+
#include "llvm/ADT/DenseMap.h"
23+
#include "llvm/ADT/SmallSet.h"
24+
#include "llvm/ADT/SmallVector.h"
25+
#include "llvm/Support/Debug.h"
26+
27+
namespace swift {
28+
29+
class SILModule;
30+
class NominalTypeDecl;
31+
class ProtocolDecl;
32+
33+
class ProtocolConformanceAnalysis : public SILAnalysis {
34+
public:
35+
typedef SmallVector<NominalTypeDecl *, 8> NominalTypeList;
36+
typedef llvm::DenseMap<ProtocolDecl *, NominalTypeList>
37+
ProtocolConformanceMap;
38+
39+
ProtocolConformanceAnalysis(SILModule *Mod)
40+
: SILAnalysis(AnalysisKind::ProtocolConformance), M(Mod) {
41+
init();
42+
}
43+
44+
~ProtocolConformanceAnalysis();
45+
46+
static bool classof(const SILAnalysis *S) {
47+
return S->getKind() == AnalysisKind::ProtocolConformance;
48+
}
49+
50+
/// Invalidate all information in this analysis.
51+
virtual void invalidate() override {}
52+
53+
/// Invalidate all of the information for a specific function.
54+
virtual void invalidate(SILFunction *F, InvalidationKind K) override {}
55+
56+
/// Notify the analysis about a newly created function.
57+
virtual void notifyAddFunction(SILFunction *F) override {}
58+
59+
/// Notify the analysis about a function which will be deleted from the
60+
/// module.
61+
virtual void notifyDeleteFunction(SILFunction *F) override {}
62+
63+
/// Notify the analysis about changed witness or vtables.
64+
virtual void invalidateFunctionTables() override {}
65+
66+
/// Get the nominal types that implement a protocol.
67+
ArrayRef<NominalTypeDecl *> getConformances(const ProtocolDecl *P) const {
68+
auto ConformsListIt = ProtocolConformanceCache.find(P);
69+
return ConformsListIt != ProtocolConformanceCache.end()
70+
? ArrayRef<NominalTypeDecl *>(ConformsListIt->second.begin(),
71+
ConformsListIt->second.end())
72+
: ArrayRef<NominalTypeDecl *>();
73+
}
74+
75+
private:
76+
/// Compute inheritance properties.
77+
void init();
78+
79+
/// The module.
80+
SILModule *M;
81+
82+
/// A cache that maps a protocol to its conformances
83+
ProtocolConformanceMap ProtocolConformanceCache;
84+
};
85+
86+
} // namespace swift
87+
#endif

lib/SILOptimizer/Analysis/Analysis.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/SILOptimizer/Analysis/IVAnalysis.h"
1818
#include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h"
1919
#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h"
20+
#include "swift/SILOptimizer/Analysis/ProtocolConformanceAnalysis.h"
2021
#include "swift/AST/Module.h"
2122
#include "swift/AST/SILOptions.h"
2223
#include "swift/SIL/SILModule.h"
@@ -55,3 +56,7 @@ SILAnalysis *swift::createClassHierarchyAnalysis(SILModule *M) {
5556
SILAnalysis *swift::createBasicCalleeAnalysis(SILModule *M) {
5657
return new BasicCalleeAnalysis(M);
5758
}
59+
60+
SILAnalysis *swift::createProtocolConformanceAnalysis(SILModule *M) {
61+
return new ProtocolConformanceAnalysis(M);
62+
}

lib/SILOptimizer/Analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ set(ANALYSIS_SOURCES
1919
Analysis/LoopAnalysis.cpp
2020
Analysis/LoopRegionAnalysis.cpp
2121
Analysis/MemoryBehavior.cpp
22+
Analysis/ProtocolConformanceAnalysis.cpp
2223
Analysis/RCIdentityAnalysis.cpp
2324
Analysis/SideEffectAnalysis.cpp
2425
Analysis/SimplifyInstruction.cpp
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===-- ProtocolConformanceAnalysis.cpp - Protocol Conformance Analysis ---===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
// This analysis collects a set of nominal types (classes, structs, and enums)
13+
// that conform to a protocol during whole module compilation. We only track
14+
// protocols that are non-public.
15+
16+
#include "swift/SILOptimizer/Analysis/ProtocolConformanceAnalysis.h"
17+
#include "swift/AST/ASTContext.h"
18+
#include "swift/AST/ASTWalker.h"
19+
#include "swift/AST/Module.h"
20+
#include "swift/SIL/SILInstruction.h"
21+
#include "swift/SIL/SILModule.h"
22+
#include "swift/SIL/SILValue.h"
23+
24+
using namespace swift;
25+
26+
namespace {
27+
/// A helper class to collect all nominal type declarations.
28+
class NominalTypeWalker : public ASTWalker {
29+
ProtocolConformanceAnalysis::ProtocolConformanceMap &ProtocolConformanceCache;
30+
31+
public:
32+
NominalTypeWalker(ProtocolConformanceAnalysis::ProtocolConformanceMap
33+
&ProtocolConformanceCache)
34+
: ProtocolConformanceCache(ProtocolConformanceCache) {}
35+
36+
bool walkToDeclPre(Decl *D) override {
37+
if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
38+
auto Protocols = NTD->getAllProtocols();
39+
for (auto &Protocol : Protocols) {
40+
if (Protocol->getEffectiveAccess() <= AccessLevel::Internal) {
41+
ProtocolConformanceCache[Protocol].push_back(NTD);
42+
}
43+
}
44+
}
45+
return true;
46+
}
47+
};
48+
} // end anonymous namespace
49+
50+
void ProtocolConformanceAnalysis::init() {
51+
52+
// We only do this in Whole-Module compilation mode.
53+
if (!M->isWholeModule())
54+
return;
55+
56+
// Process all types implementing protocols.
57+
SmallVector<Decl *, 32> Decls;
58+
59+
// Find all top level declarations.
60+
M->getSwiftModule()->getTopLevelDecls(Decls);
61+
62+
/// This operation is quadratic and should only be performed
63+
/// in whole module compilation!
64+
NominalTypeWalker Walker(ProtocolConformanceCache);
65+
for (auto *D : Decls) {
66+
D->walk(Walker);
67+
}
68+
}
69+
70+
ProtocolConformanceAnalysis::~ProtocolConformanceAnalysis() {}

0 commit comments

Comments
 (0)