20
20
#include " swift/Demangling/Demangle.h"
21
21
#include " swift/Serialization/ModuleSummary.h"
22
22
#include " llvm/Support/CommandLine.h"
23
+ #include " llvm/Support/GenericDomTree.h"
24
+ #include " llvm/Support/GenericDomTreeConstruction.h"
23
25
#include " llvm/Support/GraphWriter.h"
24
26
#include " llvm/Support/MemoryBuffer.h"
25
27
#include " llvm/Support/YAMLParser.h"
@@ -32,6 +34,7 @@ enum class ActionType : unsigned {
32
34
None,
33
35
BinaryToYAML,
34
36
YAMLToBinary,
37
+ BinaryToDominators,
35
38
BinaryToDot,
36
39
};
37
40
@@ -51,16 +54,19 @@ static llvm::cl::opt<bool>
51
54
OmitDeadSymbol (" omit-dead-symbol" , llvm::cl::init(false ),
52
55
llvm::cl::desc(" Omit dead symbols" ));
53
56
54
- static llvm::cl::opt<ActionType>
55
- Action (llvm::cl::desc(" Mode:" ), llvm::cl::init(ActionType::None),
56
- llvm::cl::cat(Category),
57
- llvm::cl::values(
58
- clEnumValN (ActionType::BinaryToYAML, " to-yaml" ,
59
- " Convert new binary .swiftmodule.summary format to YAML" ),
60
- clEnumValN(ActionType::YAMLToBinary, " from-yaml" ,
61
- " Convert YAML to new binary .swiftmodule.summary format" ),
62
- clEnumValN(ActionType::BinaryToDot, " binary-to-dot" ,
63
- " Convert new binary .swiftmodule.summary format to Dot" )));
57
+ static llvm::cl::opt<ActionType> Action (
58
+ llvm::cl::desc (" Mode:" ), llvm::cl::init(ActionType::None),
59
+ llvm::cl::cat(Category),
60
+ llvm::cl::values(
61
+ clEnumValN (ActionType::BinaryToYAML, " to-yaml" ,
62
+ " Convert new binary .swiftmodule.summary format to YAML" ),
63
+ clEnumValN(ActionType::YAMLToBinary, " from-yaml" ,
64
+ " Convert YAML to new binary .swiftmodule.summary format" ),
65
+ clEnumValN(
66
+ ActionType::BinaryToDominators, " binary-to-dom" ,
67
+ " Convert new binary .swiftmodule.summary format to dominator tree" ),
68
+ clEnumValN(ActionType::BinaryToDot, " binary-to-dot" ,
69
+ " Convert new binary .swiftmodule.summary format to Dot" )));
64
70
65
71
} // namespace options
66
72
@@ -190,82 +196,83 @@ struct CallGraph {
190
196
struct Edge {
191
197
FunctionSummary::Call Call;
192
198
GUID Target;
193
- Node *Child;
194
199
};
195
200
196
201
struct Node {
197
- FunctionSummary *FS;
198
- SmallVector<Edge, 8 > Children;
199
- Node (FunctionSummary *FS) : FS(FS), Children() {}
200
- };
201
-
202
- struct child_iterator
203
- : public std::iterator<std::random_access_iterator_tag, Node *,
204
- ptrdiff_t > {
205
- SmallVectorImpl<Edge>::iterator baseIter;
206
-
207
- child_iterator (SmallVectorImpl<Edge>::iterator baseIter) :
208
- baseIter (baseIter)
209
- { }
210
-
211
- child_iterator &operator ++() { baseIter++; return *this ; }
212
- child_iterator operator ++(int ) {
213
- auto tmp = *this ;
214
- ++baseIter;
215
- return tmp;
216
- }
217
- Node *operator *() const { return baseIter->Child ; }
218
- bool operator ==(const child_iterator &RHS) const {
219
- return baseIter == RHS.baseIter ;
220
- }
221
- bool operator !=(const child_iterator &RHS) const {
222
- return baseIter != RHS.baseIter ;
223
- }
224
- difference_type operator -(const child_iterator &RHS) const {
225
- return baseIter - RHS.baseIter ;
202
+ GUID Guid;
203
+ CallGraph *Parent;
204
+ std::vector<Node *> Children;
205
+ std::vector<Node *> PredChildren;
206
+ std::vector<Edge> Edges;
207
+
208
+ CallGraph *getParent () const { return Parent; }
209
+
210
+ void printAsOperand (raw_ostream &OS, bool /* PrintType*/ ) {
211
+ FunctionSummary *FS = Parent->Summary .getFunctionSummary (Guid);
212
+ if (!FS) {
213
+ OS << " Entry node" ;
214
+ return ;
215
+ }
216
+ OS << " Fn#" << FS->getName ();
226
217
}
227
218
};
228
219
220
+ using child_iterator = std::vector<Node *>::iterator;
221
+
229
222
std::vector<Node> Nodes;
223
+ Node EntryNode;
224
+ ModuleSummaryIndex Summary;
230
225
using iterator = std::vector<Node>::iterator;
231
- CallGraph (ModuleSummaryIndex * );
226
+ CallGraph (ModuleSummaryIndex);
232
227
};
233
228
234
- CallGraph::CallGraph (ModuleSummaryIndex *Summary) {
235
- llvm::DenseMap<GUID, Node *> NodeMap;
236
- for (auto FI = Summary->functions_begin (), FE = Summary->functions_end ();
229
+ CallGraph::CallGraph (ModuleSummaryIndex Summary) : Nodes(), EntryNode() {
230
+ std::map<GUID, Node *> NodeMap;
231
+ Nodes.resize (Summary.functions_size ());
232
+ int idx = 0 ;
233
+ for (auto FI = Summary.functions_begin (), FE = Summary.functions_end ();
237
234
FI != FE; ++FI) {
238
- if (options::OmitDeadSymbol && !FI->second ->isLive ()) continue ;
239
- Nodes.emplace_back (FI->second .get ());
240
- Node &node = Nodes.back ();
241
- NodeMap[FI->first ] = &node;
235
+ Node *node = &Nodes[idx++];
236
+ node->Guid = FI->first ;
237
+ node->Parent = this ;
238
+ NodeMap[FI->first ] = node;
239
+ if (FI->second ->isPreserved ()) {
240
+ EntryNode.Children .push_back (node);
241
+ EntryNode.PredChildren .push_back (node);
242
+ }
242
243
}
244
+ EntryNode.Parent = this ;
243
245
244
246
for (Node &node : Nodes) {
245
- for (FunctionSummary::Call call : node.FS ->calls ()) {
247
+ FunctionSummary *FS = Summary.getFunctionSummary (node.Guid );
248
+ for (FunctionSummary::Call call : FS->calls ()) {
246
249
switch (call.getKind ()) {
247
250
case FunctionSummary::Call::Witness:
248
251
case FunctionSummary::Call::VTable: {
249
252
VFuncSlot slot = createVFuncSlot (call);
250
- for (auto Impl : Summary-> getImplementations (slot)) {
253
+ for (auto Impl : Summary. getImplementations (slot)) {
251
254
Node *CalleeNode = NodeMap[Impl.Guid ];
252
- node.Children .push_back ({ call, Impl.Guid , CalleeNode });
255
+ node.Children .push_back (CalleeNode);
256
+ node.PredChildren .push_back (CalleeNode);
257
+ node.Edges .push_back ({call, Impl.Guid });
253
258
}
254
259
break ;
255
260
}
256
261
case FunctionSummary::Call::Direct: {
257
262
Node *CalleeNode = NodeMap[call.getCallee ()];
258
- node.Children .push_back ({ call, call.getCallee (), CalleeNode });
263
+ node.Children .push_back (CalleeNode);
264
+ node.PredChildren .push_back (CalleeNode);
265
+ node.Edges .push_back ({call, call.getCallee ()});
259
266
break ;
260
267
}
261
268
case FunctionSummary::Call::kindCount:
262
269
llvm_unreachable (" impossible" );
263
270
}
264
271
}
265
272
}
273
+ this ->Summary = std::move (Summary);
266
274
}
267
275
268
-
269
276
namespace llvm {
270
277
271
278
template <> struct GraphTraits <CallGraph::Node *> {
@@ -281,13 +288,28 @@ namespace llvm {
281
288
}
282
289
};
283
290
291
+ template <> struct GraphTraits <Inverse<CallGraph::Node *>> {
292
+ using ChildIteratorType = CallGraph::child_iterator;
293
+ using Node = CallGraph::Node;
294
+ using NodeRef = Node *;
295
+ static NodeRef getEntryNode (Inverse<CallGraph::Node *> G) {
296
+ return G.Graph ;
297
+ }
298
+ static inline ChildIteratorType child_begin (NodeRef N) {
299
+ return N->PredChildren .begin ();
300
+ }
301
+ static inline ChildIteratorType child_end (NodeRef N) {
302
+ return N->PredChildren .end ();
303
+ }
304
+ };
305
+
284
306
template <> struct GraphTraits <CallGraph *>
285
307
: public GraphTraits<CallGraph::Node *> {
286
308
typedef CallGraph *GraphType;
287
309
typedef CallGraph::Node *NodeRef;
288
-
289
- static NodeRef getEntryNode (GraphType F ) { return nullptr ; }
290
-
310
+
311
+ static NodeRef getEntryNode (GraphType G ) { return &G-> EntryNode ; }
312
+
291
313
typedef pointer_iterator<CallGraph::iterator> nodes_iterator;
292
314
static nodes_iterator nodes_begin (GraphType CG) {
293
315
return nodes_iterator (CG->Nodes .begin ());
@@ -307,24 +329,28 @@ namespace llvm {
307
329
308
330
std::string getNodeLabel (const CallGraph::Node *Node,
309
331
const CallGraph *Graph) {
332
+ FunctionSummary *FS = Graph->Summary .getFunctionSummary (Node->Guid );
310
333
Demangle::Context DCtx;
311
- return DCtx.demangleSymbolAsString (Node-> FS ->getName ());
334
+ return DCtx.demangleSymbolAsString (FS->getName ());
312
335
}
313
336
314
337
static std::string getNodeAttributes (const CallGraph::Node *Node,
315
338
const CallGraph *Graph) {
316
- std::string color = Node->FS ->isLive () ? " green" : " red" ;
339
+ FunctionSummary *FS = Graph->Summary .getFunctionSummary (Node->Guid );
340
+ std::string color = FS->isLive () ? " green" : " red" ;
317
341
std::string attrs = " color=\" " + color + " \" " ;
318
342
return attrs;
319
343
}
320
344
321
345
static std::string getEdgeAttributes (const CallGraph::Node *Node,
322
346
CallGraph::child_iterator I,
323
347
const CallGraph *Graph) {
348
+ unsigned ChildIdx = I - Node->Children .begin ();
324
349
std::string Label;
325
350
raw_string_ostream O (Label);
326
351
Demangle::Context DCtx;
327
- FunctionSummary::Call call = I.baseIter ->Call ;
352
+ CallGraph::Edge edge = Node->Edges [ChildIdx];
353
+ FunctionSummary::Call call = edge.Call ;
328
354
std::string demangled = DCtx.demangleSymbolAsString (call.getName ());
329
355
O << " label=\" " ;
330
356
switch (call.getKind ()) {
@@ -348,6 +374,47 @@ namespace llvm {
348
374
}
349
375
};
350
376
} // namespace llvm
377
+ using DomCallTreeBase = llvm::DominatorTreeBase<CallGraph::Node, false >;
378
+ using DomCallInfoNode = llvm::DomTreeNodeBase<CallGraph::Node>;
379
+
380
+ namespace llvm {
381
+
382
+ template <> struct GraphTraits <DomCallInfoNode *> {
383
+ using ChildIteratorType = DomCallInfoNode::iterator;
384
+ using NodeRef = DomCallInfoNode *;
385
+
386
+ static NodeRef getEntryNode (NodeRef N) { return N; }
387
+ static inline ChildIteratorType child_begin (NodeRef N) { return N->begin (); }
388
+ static inline ChildIteratorType child_end (NodeRef N) { return N->end (); }
389
+ };
390
+
391
+ template <> struct GraphTraits <const DomCallInfoNode *> {
392
+ using ChildIteratorType = DomCallInfoNode::const_iterator;
393
+ using NodeRef = const DomCallInfoNode *;
394
+
395
+ static NodeRef getEntryNode (NodeRef N) { return N; }
396
+ static inline ChildIteratorType child_begin (NodeRef N) { return N->begin (); }
397
+ static inline ChildIteratorType child_end (NodeRef N) { return N->end (); }
398
+ };
399
+
400
+ namespace DomTreeBuilder {
401
+ extern template void Calculate<DomCallTreeBase>(DomCallTreeBase &DT);
402
+ template void Calculate<DomCallTreeBase>(DomCallTreeBase &DT);
403
+ } // namespace DomTreeBuilder
404
+ } // namespace llvm
405
+
406
+ class DomCallTree : public DomCallTreeBase {
407
+ using super = DominatorTreeBase;
408
+
409
+ public:
410
+ DomCallTree (CallGraph &CG) : DominatorTreeBase() { recalculate (CG); }
411
+ };
412
+
413
+ int dominance_analysis (CallGraph &CG) {
414
+ DomCallTree DT (CG);
415
+ DT.print (llvm::dbgs ());
416
+ return 0 ;
417
+ };
351
418
352
419
int main (int argc, char *argv[]) {
353
420
PROGRAM_START (argc, argv);
@@ -408,13 +475,20 @@ int main(int argc, char *argv[]) {
408
475
modulesummary::ModuleSummaryIndex summary;
409
476
modulesummary::loadModuleSummaryIndex (fileBufOrErr.get ()->getMemBufferRef (),
410
477
summary);
411
- CallGraph CG (& summary);
478
+ CallGraph CG (std::move ( summary) );
412
479
withOutputFile (diags, options::OutputFilename, [&](raw_ostream &out) {
413
480
llvm::WriteGraph (out, &CG);
414
481
return false ;
415
482
});
416
483
break ;
417
484
}
485
+ case ActionType::BinaryToDominators: {
486
+ modulesummary::ModuleSummaryIndex summary;
487
+ modulesummary::loadModuleSummaryIndex (fileBufOrErr.get ()->getMemBufferRef (),
488
+ summary);
489
+ CallGraph CG (std::move (summary));
490
+ return dominance_analysis (CG);
491
+ }
418
492
}
419
493
return 0 ;
420
494
}
0 commit comments