P4C
The P4 Compiler
Loading...
Searching...
No Matches
pass_manager.h
1/*
2Copyright 2013-present Barefoot Networks, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef IR_PASS_MANAGER_H_
18#define IR_PASS_MANAGER_H_
19
20#include <functional>
21#include <initializer_list>
22#include <iosfwd>
23#include <type_traits>
24#include <vector>
25
26#include "ir/node.h"
27#include "ir/visitor.h"
28#include "lib/cstring.h"
29#include "lib/exceptions.h"
30#include "lib/safe_vector.h"
31
34typedef std::function<void(const char *manager, unsigned seqNo, const char *pass,
35 const IR::Node *node)>
36 DebugHook;
37
38class PassManager : virtual public Visitor, virtual public Backtrack {
39 bool early_exit_flag = false;
40 mutable int never_backtracks_cache = -1;
41
42 protected:
43 safe_vector<DebugHook> debugHooks; // called after each pass
45 // if true stops compilation after first pass that signals an error
46 bool stop_on_error = true;
47 bool running = false;
48 unsigned seqNo = 0;
49 void runDebugHooks(const char *visitorName, const IR::Node *node);
50 profile_t init_apply(const IR::Node *root) override {
51 running = true;
52 return Visitor::init_apply(root);
53 }
54
55 public:
56 PassManager() = default;
57 PassManager(const PassManager &) = default;
58 PassManager(PassManager &&) = default;
59 class VisitorRef {
60 Visitor *visitor;
61 friend class PassManager;
62
63 public:
64 VisitorRef() : visitor(nullptr) {}
65 VisitorRef(Visitor *v) : visitor(v) {} // NOLINT(runtime/explicit)
66 VisitorRef(const Visitor &v) : visitor(v.clone()) { // NOLINT(runtime/explicit)
67 BUG_CHECK(visitor->check_clone(&v), "Incorrect clone in PassManager");
68 }
69 explicit VisitorRef(std::function<const IR::Node *(const IR::Node *)>);
70 // ambiguity resolution converters -- allow different lambda signatures
71 template <class T>
73 T t,
74 typename std::enable_if<
75 std::is_convertible<decltype(t(nullptr)), const IR::Node *>::value, int>::type = 0)
76 : VisitorRef(std::function<const IR::Node *(const IR::Node *)>(t)) {}
77 template <class T>
79 T t,
80 typename std::enable_if<std::is_same<decltype(t(nullptr)), void>::value, int>::type = 0)
81 : VisitorRef(std::function<const IR::Node *(const IR::Node *)>(
82 [t](const IR::Node *n) -> const IR::Node * {
83 t(n);
84 return n;
85 })) {}
86 template <class T>
87 VisitorRef(T t,
88 typename std::enable_if<std::is_same<decltype(t()), void>::value, int>::type = 0)
89 : VisitorRef(std::function<const IR::Node *(const IR::Node *)>(
90 [t](const IR::Node *n) -> const IR::Node * {
91 t();
92 return n;
93 })) {}
94 };
95 PassManager(const std::initializer_list<VisitorRef> &init) { addPasses(init); }
96 void addPasses(const std::initializer_list<VisitorRef> &init) {
97 never_backtracks_cache = -1;
98 for (auto &p : init)
99 if (p.visitor) passes.emplace_back(p.visitor);
100 }
101 void removePasses(const std::vector<cstring> &exclude);
102 void listPasses(std::ostream &, cstring sep) const;
103 const IR::Node *apply_visitor(const IR::Node *, const char * = 0) override;
104 bool backtrack(trigger &trig) override;
105 bool never_backtracks() override;
106 void setStopOnError(bool stop) { stop_on_error = stop; }
107 void addDebugHook(DebugHook h, bool recursive = false) {
108 debugHooks.push_back(h);
109 if (recursive)
110 for (auto pass : passes)
111 if (auto child = dynamic_cast<PassManager *>(pass))
112 child->addDebugHook(h, recursive);
113 }
114 void addDebugHooks(std::vector<DebugHook> hooks, bool recursive = false) {
115 debugHooks.insert(debugHooks.end(), hooks.begin(), hooks.end());
116 if (recursive)
117 for (auto pass : passes)
118 if (auto child = dynamic_cast<PassManager *>(pass))
119 child->addDebugHooks(hooks, recursive);
120 }
121 void early_exit() { early_exit_flag = true; }
122 PassManager *clone() const override { return new PassManager(*this); }
123};
124
125template <class T>
126class OnBacktrack : virtual public Visitor, virtual public Backtrack {
127 std::function<void(T *)> fn;
128
129 public:
130 explicit OnBacktrack(std::function<void(T *)> f) : fn(f) {}
131 const IR::Node *apply_visitor(const IR::Node *n, const char * = 0) override { return n; }
132 bool backtrack(trigger &trig) override {
133 if (auto *t = dynamic_cast<T *>(&trig)) {
134 fn(t);
135 return true;
136 } else {
137 return false;
138 }
139 }
140};
141
142// Repeat a pass until convergence (or up to a fixed number of repeats)
143class PassRepeated : virtual public PassManager {
144 unsigned repeats; // 0 = until convergence
145 public:
146 PassRepeated() : repeats(0) {}
147 explicit PassRepeated(const std::initializer_list<VisitorRef> &init, unsigned repeats = 0)
148 : PassManager(init), repeats(repeats) {}
149 explicit PassRepeated(const PassManager &other, unsigned repeats = 0)
150 : PassManager(other), repeats(repeats) {}
151 const IR::Node *apply_visitor(const IR::Node *, const char * = 0) override;
152 PassRepeated *setRepeats(unsigned repeats) {
153 this->repeats = repeats;
154 return this;
155 }
156 PassRepeated *clone() const override { return new PassRepeated(*this); }
157};
158
159class PassRepeatUntil : virtual public PassManager {
160 std::function<bool()> done;
161
162 public:
163 explicit PassRepeatUntil(std::function<bool()> done) : done(done) {}
164 PassRepeatUntil(const std::initializer_list<VisitorRef> &init, std::function<bool()> done)
165 : PassManager(init), done(done) {}
166 const IR::Node *apply_visitor(const IR::Node *, const char * = 0) override;
167 PassRepeatUntil *clone() const override { return new PassRepeatUntil(*this); }
168};
169
170class PassIf : virtual public PassManager {
171 std::function<bool()> cond;
172
173 public:
174 explicit PassIf(std::function<bool()> cond) : cond(cond) {}
175 PassIf(std::function<bool()> cond, const std::initializer_list<VisitorRef> &init)
176 : PassManager(init), cond(cond) {}
177 const IR::Node *apply_visitor(const IR::Node *, const char * = 0) override;
178 PassIf *clone() const override { return new PassIf(*this); }
179};
180
181// Converts a function Node* -> Node* into a visitor
182class VisitFunctor : virtual public Visitor {
183 std::function<const IR::Node *(const IR::Node *)> fn;
184 const IR::Node *apply_visitor(const IR::Node *n, const char * = 0) override { return fn(n); }
185
186 public:
187 explicit VisitFunctor(std::function<const IR::Node *(const IR::Node *)> f) : fn(f) {}
188 explicit VisitFunctor(std::function<void()> f)
189 : fn([f](const IR::Node *n) -> const IR::Node * {
190 f();
191 return n;
192 }) {}
193
194 VisitFunctor *clone() const override { return new VisitFunctor(*this); }
195};
196
197inline PassManager::VisitorRef::VisitorRef(std::function<const IR::Node *(const IR::Node *)> fn)
198 : visitor(new VisitFunctor(fn)) {}
199
200class DynamicVisitor : virtual public Visitor {
201 Visitor *visitor;
202 profile_t init_apply(const IR::Node *root) override {
203 if (visitor) return visitor->init_apply(root);
204 return Visitor::init_apply(root);
205 }
206 void end_apply(const IR::Node *root) override {
207 if (visitor) visitor->end_apply(root);
208 }
209 const IR::Node *apply_visitor(const IR::Node *root, const char *name = 0) override {
210 if (visitor) return visitor->apply_visitor(root, name);
211 return root;
212 }
213
214 public:
215 DynamicVisitor() : visitor(nullptr) {}
216 explicit DynamicVisitor(Visitor *v) : visitor(v) {}
217 void setVisitor(Visitor *v) { visitor = v; }
218 DynamicVisitor *clone() const override { return new DynamicVisitor(*this); }
219};
220
221#endif /* IR_PASS_MANAGER_H_ */
Definition visitor.h:762
Definition pass_manager.h:200
Definition node.h:93
Definition pass_manager.h:126
Definition pass_manager.h:170
Definition pass_manager.h:59
Definition pass_manager.h:38
Definition pass_manager.h:159
Definition pass_manager.h:143
Definition pass_manager.h:182
Definition visitor.h:76
Definition visitor.h:73
Definition cstring.h:80
Definition safe_vector.h:25
Definition visitor.h:764