14
14
15
15
#include " swift/SIL/SILModule.h"
16
16
#include " swift/SILOptimizer/Utils/Local.h"
17
+ #include " llvm/Support/FileSystem.h"
18
+ #include " llvm/Support/YAMLTraits.h"
17
19
18
20
using namespace swift ;
19
21
22
+ // ===----------------------------------------------------------------------===//
23
+ // Actual Analysis
24
+ // ===----------------------------------------------------------------------===//
25
+
20
26
void CallerAnalysis::processFunctionCallSites (SILFunction *F) {
21
27
// Scan the whole module and search Apply sites.
22
28
for (auto &BB : *F) {
@@ -53,8 +59,8 @@ void CallerAnalysis::processFunctionCallSites(SILFunction *F) {
53
59
}
54
60
continue ;
55
61
}
56
- }
57
- }
62
+ }
63
+ }
58
64
}
59
65
60
66
void CallerAnalysis::invalidateExistingCalleeRelation (SILFunction *F) {
@@ -66,9 +72,107 @@ void CallerAnalysis::invalidateExistingCalleeRelation(SILFunction *F) {
66
72
}
67
73
}
68
74
75
+ // ===----------------------------------------------------------------------===//
76
+ // CallerAnalysis YAML Dumper
77
+ // ===----------------------------------------------------------------------===//
78
+
79
+ namespace {
80
+
81
+ using llvm::yaml::IO;
82
+ using llvm::yaml::MappingTraits;
83
+ using llvm::yaml::Output;
84
+ using llvm::yaml::ScalarEnumerationTraits;
85
+ using llvm::yaml::SequenceTraits;
86
+
87
+ // / A special struct that marshals call graph state into a form that is easy for
88
+ // / llvm's yaml i/o to dump. Its structure is meant to correspond to how the
89
+ // / data should be shown by the printer, so naturally it is slightly redundant.
90
+ struct YAMLCallGraphNode {
91
+ StringRef calleeName;
92
+ bool hasCaller;
93
+ unsigned minPartialAppliedArgs;
94
+ std::vector<StringRef> partialAppliers;
95
+ std::vector<StringRef> fullAppliers;
96
+
97
+ YAMLCallGraphNode () = delete ;
98
+ ~YAMLCallGraphNode () = default ;
99
+
100
+ // This is a data structure that can not be copied or moved.
101
+ YAMLCallGraphNode (const YAMLCallGraphNode &) = delete ;
102
+ YAMLCallGraphNode (YAMLCallGraphNode &&) = delete ;
103
+ YAMLCallGraphNode &operator =(const YAMLCallGraphNode &) = delete ;
104
+ YAMLCallGraphNode &operator =(YAMLCallGraphNode &&) = delete ;
105
+
106
+ YAMLCallGraphNode (StringRef calleeName, bool hasCaller,
107
+ unsigned minPartialAppliedArgs,
108
+ std::vector<StringRef> &&partialAppliers,
109
+ std::vector<StringRef> &&fullAppliers)
110
+ : calleeName(calleeName), hasCaller(hasCaller),
111
+ minPartialAppliedArgs (minPartialAppliedArgs),
112
+ partialAppliers(std::move(partialAppliers)),
113
+ fullAppliers(std::move(fullAppliers)) {}
114
+ };
115
+
116
+ } // end anonymous namespace
117
+
118
+ namespace llvm {
119
+ namespace yaml {
120
+
121
+ template <> struct MappingTraits <YAMLCallGraphNode> {
122
+ static void mapping (IO &io, YAMLCallGraphNode &func) {
123
+ io.mapRequired (" calleeName" , func.calleeName );
124
+ io.mapRequired (" hasCaller" , func.hasCaller );
125
+ io.mapRequired (" minPartialAppliedArgs" , func.minPartialAppliedArgs );
126
+ io.mapRequired (" partialAppliers" , func.partialAppliers );
127
+ io.mapRequired (" fullAppliers" , func.fullAppliers );
128
+ }
129
+ };
130
+
131
+ } // namespace yaml
132
+ } // namespace llvm
133
+
134
+ void CallerAnalysis::dump () const { print (llvm::errs ()); }
135
+
136
+ void CallerAnalysis::print (const char *filePath) const {
137
+ using namespace llvm ::sys;
138
+ std::error_code error;
139
+ llvm::raw_fd_ostream fileOutputStream (filePath, error, fs::F_Text);
140
+ if (error) {
141
+ llvm::errs () << " Failed to open path \" " << filePath << " \" for writing.!" ;
142
+ llvm_unreachable (" default error handler" );
143
+ }
144
+ print (fileOutputStream);
145
+ }
146
+
147
+ void CallerAnalysis::print (llvm::raw_ostream &os) const {
148
+ llvm::yaml::Output yout (os);
149
+
150
+ // NOTE: We purposely do not iterate over our internal state here to ensure
151
+ // that we dump for all functions and that we dump the state we have stored
152
+ // with the functions in module order.
153
+ for (auto &f : Mod) {
154
+ const auto &fi = getCallerInfo (&f);
155
+
156
+ std::vector<StringRef> fullAppliers;
157
+ for (auto *caller : fi.Callers ) {
158
+ fullAppliers.push_back (caller->getName ());
159
+ }
160
+ std::vector<StringRef> partialAppliers;
161
+ for (auto iter : fi.PartialAppliers ) {
162
+ partialAppliers.push_back (iter.first ->getName ());
163
+ }
164
+
165
+ YAMLCallGraphNode node (f.getName (), fi.hasCaller (),
166
+ fi.getMinPartialAppliedArgs (),
167
+ std::move (partialAppliers), std::move (fullAppliers));
168
+ yout << node;
169
+ }
170
+ }
171
+
69
172
// ===----------------------------------------------------------------------===//
70
173
// Main Entry Point
71
174
// ===----------------------------------------------------------------------===//
175
+
72
176
SILAnalysis *swift::createCallerAnalysis (SILModule *M) {
73
177
return new CallerAnalysis (M);
74
178
}
0 commit comments