blob: 007724ab8e32b84e7121109d7af3b1b5c439867c [file] [log] [blame]
Jacques Pienaar10b6fcb2018-09-04 22:04:21 -07001//===- CFGFunctionViewGraph.h - View/write graphviz graphs ------*- C++ -*-===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17
18#include "mlir/Transforms/CFGFunctionViewGraph.h"
19
20using namespace mlir;
21
22namespace llvm {
23
24// Specialize GraphTraits to treat a CFGFunction as a graph of basic blocks.
25template <>
26struct llvm::GraphTraits<const CFGFunction *> {
27 using NodeRef = const BasicBlock *;
28 using ChildIteratorType = BasicBlock::const_succ_iterator;
29 using nodes_iterator = pointer_iterator<CFGFunction::const_iterator>;
30
31 static NodeRef getEntryNode(const CFGFunction *function) {
32 return &function->front();
33 }
34
35 static nodes_iterator nodes_begin(const CFGFunction *F) {
36 return nodes_iterator(F->begin());
37 }
38 static nodes_iterator nodes_end(const CFGFunction *F) {
39 return nodes_iterator(F->end());
40 }
41
42 static ChildIteratorType child_begin(NodeRef basicBlock) {
43 return basicBlock->succ_begin();
44 }
45 static ChildIteratorType child_end(NodeRef basicBlock) {
46 return basicBlock->succ_end();
47 }
48};
49
50// Specialize DOTGraphTraits to produce more readable output.
51template <>
52struct llvm::DOTGraphTraits<const CFGFunction *>
53 : public DefaultDOTGraphTraits {
54 using DefaultDOTGraphTraits::DefaultDOTGraphTraits;
55
56 static std::string getNodeLabel(const BasicBlock *basicBlock,
57 const CFGFunction *);
58};
59
60std::string llvm::DOTGraphTraits<const CFGFunction *>::getNodeLabel(
61 const BasicBlock *basicBlock, const CFGFunction *) {
62 // Reuse the print output for the node labels.
63 std::string outStreamStr;
64 raw_string_ostream os(outStreamStr);
65 basicBlock->print(os);
66 std::string &outStr = os.str();
67
68 if (outStr[0] == '\n')
69 outStr.erase(outStr.begin());
70
71 // Process string output to left justify the block.
72 for (unsigned i = 0; i != outStr.length(); ++i) {
73 if (outStr[i] == '\n') {
74 outStr[i] = '\\';
75 outStr.insert(outStr.begin() + i + 1, 'l');
76 }
77 }
78
79 return outStr;
80}
81
82} // end namespace llvm
83
84void mlir::viewGraph(const CFGFunction &function, const llvm::Twine &name,
85 bool shortNames, const llvm::Twine &title,
86 llvm::GraphProgram::Name program) {
87 llvm::ViewGraph(&function, name, shortNames, title, program);
88}
89
90llvm::raw_ostream &mlir::writeGraph(llvm::raw_ostream &os,
91 const CFGFunction *function,
92 bool shortNames, const llvm::Twine &title) {
93 return llvm::WriteGraph(os, function, shortNames, title);
94}
95
96void mlir::CFGFunction::viewGraph() const {
97 ::mlir::viewGraph(*this, llvm::Twine("cfgfunc ") + getName().str());
98}
99
100namespace {
101struct PrintCFGPass : public CFGFunctionPass {
102 PrintCFGPass(llvm::raw_ostream &os, bool shortNames, const llvm::Twine &title)
103 : os(os), shortNames(shortNames), title(title) {}
104 void runOnCFGFunction(CFGFunction *function) override {
105 mlir::writeGraph(os, function, shortNames, title);
106 }
107
108private:
109 llvm::raw_ostream &os;
110 bool shortNames;
111 const llvm::Twine &title;
112};
113} // namespace
114
115CFGFunctionPass *mlir::createPrintCFGGraphPass(llvm::raw_ostream &os,
116 bool shortNames,
117 const llvm::Twine &title) {
118 return new PrintCFGPass(os, shortNames, title);
119}