P4C
The P4 Compiler
Loading...
Searching...
No Matches
ir/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
32namespace P4 {
33
36typedef std::function<void(const char *manager, unsigned seqNo, const char *pass,
37 const IR::Node *node)>
39
40class PassManager : virtual public Visitor, virtual public Backtrack {
41 bool early_exit_flag = false;
42 mutable int never_backtracks_cache = -1;
43
44 protected:
45 safe_vector<DebugHook> debugHooks; // called after each pass
47 // if true stops compilation after first pass that signals an error
48 bool stop_on_error = true;
49 bool running = false;
50 unsigned seqNo = 0;
51 void runDebugHooks(const char *visitorName, const IR::Node *node);
52 profile_t init_apply(const IR::Node *root) override {
53 running = true;
54 return Visitor::init_apply(root);
55 }
56
57 public:
58 PassManager() = default;
59 PassManager(const PassManager &) = default;
60 PassManager(PassManager &&) = default;
61 class VisitorRef {
62 Visitor *visitor;
63 friend class PassManager;
64
65 public:
66 VisitorRef() : visitor(nullptr) {}
67 VisitorRef(Visitor *v) : visitor(v) {} // NOLINT(runtime/explicit)
68 VisitorRef(const Visitor &v) : visitor(v.clone()) { // NOLINT(runtime/explicit)
69 BUG_CHECK(visitor->check_clone(&v), "Incorrect clone in PassManager");
70 }
71 explicit VisitorRef(std::function<const IR::Node *(const IR::Node *)>);
72 // ambiguity resolution converters -- allow different lambda signatures
73 template <class T>
75 T t,
76 typename std::enable_if<
77 std::is_convertible<decltype(t(nullptr)), const IR::Node *>::value, int>::type = 0)
78 : VisitorRef(std::function<const IR::Node *(const IR::Node *)>(t)) {}
79 template <class T>
81 T t,
82 typename std::enable_if<std::is_same<decltype(t(nullptr)), void>::value, int>::type = 0)
83 : VisitorRef(std::function<const IR::Node *(const IR::Node *)>(
84 [t](const IR::Node *n) -> const IR::Node * {
85 t(n);
86 return n;
87 })) {}
88 template <class T>
89 VisitorRef(T t,
90 typename std::enable_if<std::is_same<decltype(t()), void>::value, int>::type = 0)
91 : VisitorRef(std::function<const IR::Node *(const IR::Node *)>(
92 [t](const IR::Node *n) -> const IR::Node * {
93 t();
94 return n;
95 })) {}
96 };
97 PassManager(const std::initializer_list<VisitorRef> &init) { addPasses(init); }
98 void addPasses(const std::initializer_list<VisitorRef> &init) {
99 never_backtracks_cache = -1;
100 for (auto &p : init)
101 if (p.visitor) passes.emplace_back(p.visitor);
102 }
103 void removePasses(const std::vector<cstring> &exclude);
104 void listPasses(std::ostream &, cstring sep) const;
105 const IR::Node *apply_visitor(const IR::Node *, const char * = 0) override;
106 bool backtrack(trigger &trig) override;
107 bool never_backtracks() override;
108 void setStopOnError(bool stop) { stop_on_error = stop; }
109 void addDebugHook(DebugHook h, bool recursive = false) {
110 debugHooks.push_back(h);
111 if (recursive)
112 for (auto pass : passes)
113 if (auto child = dynamic_cast<PassManager *>(pass))
114 child->addDebugHook(h, recursive);
115 }
116 void addDebugHooks(std::vector<DebugHook> hooks, bool recursive = false) {
117 debugHooks.insert(debugHooks.end(), hooks.begin(), hooks.end());
118 if (recursive)
119 for (auto pass : passes)
120 if (auto child = dynamic_cast<PassManager *>(pass))
121 child->addDebugHooks(hooks, recursive);
122 }
123 void early_exit() { early_exit_flag = true; }
124 PassManager *clone() const override { return new PassManager(*this); }
125};
126
127template <class T>
128class OnBacktrack : virtual public Visitor, virtual public Backtrack {
129 std::function<void(T *)> fn;
130
131 public:
132 explicit OnBacktrack(std::function<void(T *)> f) : fn(f) {}
133 const IR::Node *apply_visitor(const IR::Node *n, const char * = 0) override { return n; }
134 bool backtrack(trigger &trig) override {
135 if (auto *t = dynamic_cast<T *>(&trig)) {
136 fn(t);
137 return true;
138 } else {
139 return false;
140 }
141 }
142};
143
144// Repeat a pass until convergence (or up to a fixed number of repeats)
145class PassRepeated : virtual public PassManager {
146 unsigned repeats; // 0 = until convergence
147 public:
148 PassRepeated() : repeats(0) {}
149 explicit PassRepeated(const std::initializer_list<VisitorRef> &init, unsigned repeats = 0)
150 : PassManager(init), repeats(repeats) {}
151 explicit PassRepeated(const PassManager &other, unsigned repeats = 0)
152 : PassManager(other), repeats(repeats) {}
153 const IR::Node *apply_visitor(const IR::Node *, const char * = 0) override;
154 PassRepeated *setRepeats(unsigned repeats) {
155 this->repeats = repeats;
156 return this;
157 }
158 PassRepeated *clone() const override { return new PassRepeated(*this); }
159};
160
161class PassRepeatUntil : virtual public PassManager {
162 std::function<bool()> done;
163
164 public:
165 explicit PassRepeatUntil(std::function<bool()> done) : done(done) {}
166 PassRepeatUntil(const std::initializer_list<VisitorRef> &init, std::function<bool()> done)
167 : PassManager(init), done(done) {}
168 const IR::Node *apply_visitor(const IR::Node *, const char * = 0) override;
169 PassRepeatUntil *clone() const override { return new PassRepeatUntil(*this); }
170};
171
172class PassIf : virtual public PassManager {
173 std::function<bool()> cond;
174
175 public:
176 explicit PassIf(std::function<bool()> cond) : cond(cond) {}
177 PassIf(std::function<bool()> cond, const std::initializer_list<VisitorRef> &init)
178 : PassManager(init), cond(cond) {}
179 const IR::Node *apply_visitor(const IR::Node *, const char * = 0) override;
180 PassIf *clone() const override { return new PassIf(*this); }
181};
182
183// Converts a function Node* -> Node* into a visitor
184class VisitFunctor : virtual public Visitor {
185 std::function<const IR::Node *(const IR::Node *)> fn;
186 const IR::Node *apply_visitor(const IR::Node *n, const char * = 0) override { return fn(n); }
187
188 public:
189 explicit VisitFunctor(std::function<const IR::Node *(const IR::Node *)> f) : fn(f) {}
190 explicit VisitFunctor(std::function<void()> f)
191 : fn([f](const IR::Node *n) -> const IR::Node * {
192 f();
193 return n;
194 }) {}
195
196 VisitFunctor *clone() const override { return new VisitFunctor(*this); }
197};
198
199inline PassManager::VisitorRef::VisitorRef(std::function<const IR::Node *(const IR::Node *)> fn)
200 : visitor(new VisitFunctor(fn)) {}
201
202class DynamicVisitor : virtual public Visitor {
203 Visitor *visitor;
204 profile_t init_apply(const IR::Node *root) override {
205 if (visitor) return visitor->init_apply(root);
206 return Visitor::init_apply(root);
207 }
208 void end_apply(const IR::Node *root) override {
209 if (visitor) visitor->end_apply(root);
210 }
211 const IR::Node *apply_visitor(const IR::Node *root, const char *name = 0) override {
212 if (visitor) return visitor->apply_visitor(root, name);
213 return root;
214 }
215
216 public:
217 DynamicVisitor() : visitor(nullptr) {}
218 explicit DynamicVisitor(Visitor *v) : visitor(v) {}
219 void setVisitor(Visitor *v) { visitor = v; }
220 DynamicVisitor *clone() const override { return new DynamicVisitor(*this); }
221};
222
223} // namespace P4
224
225#endif /* IR_PASS_MANAGER_H_ */
Definition visitor.h:766
Definition ir/pass_manager.h:202
Definition node.h:95
Definition ir/pass_manager.h:128
Definition ir/pass_manager.h:172
Definition ir/pass_manager.h:61
Definition ir/pass_manager.h:40
Definition ir/pass_manager.h:161
Definition ir/pass_manager.h:145
Definition ir/pass_manager.h:184
Definition visitor.h:78
Definition visitor.h:75
Definition safe_vector.h:27
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
std::function< void(const char *manager, unsigned seqNo, const char *pass, const IR::Node *node)> DebugHook
Definition ir/pass_manager.h:38
Definition visitor.h:768