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>
74 VisitorRef(
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>
80 VisitorRef(
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 auto getPasses() { return Util::iterator_range(passes); }
126};
127
128template <class T>
129class OnBacktrack : virtual public Visitor, virtual public Backtrack {
130 std::function<void(T *)> fn;
131
132 public:
133 explicit OnBacktrack(std::function<void(T *)> f) : fn(f) {}
134 const IR::Node *apply_visitor(const IR::Node *n, const char * = 0) override { return n; }
135 bool backtrack(trigger &trig) override {
136 if (auto *t = dynamic_cast<T *>(&trig)) {
137 fn(t);
138 return true;
139 } else {
140 return false;
141 }
142 }
143};
144
145// Repeat a pass until convergence (or up to a fixed number of repeats)
146class PassRepeated : virtual public PassManager {
147 unsigned repeats; // 0 = until convergence
148 public:
149 PassRepeated() : repeats(0) {}
150 explicit PassRepeated(const std::initializer_list<VisitorRef> &init, unsigned repeats = 0)
151 : PassManager(init), repeats(repeats) {}
152 explicit PassRepeated(const PassManager &other, unsigned repeats = 0)
153 : PassManager(other), repeats(repeats) {}
154 const IR::Node *apply_visitor(const IR::Node *, const char * = 0) override;
155 PassRepeated *setRepeats(unsigned repeats) {
156 this->repeats = repeats;
157 return this;
158 }
159 PassRepeated *clone() const override { return new PassRepeated(*this); }
160};
161
162class PassRepeatUntil : virtual public PassManager {
163 std::function<bool()> done;
164
165 public:
166 explicit PassRepeatUntil(std::function<bool()> done) : done(done) {}
167 PassRepeatUntil(const std::initializer_list<VisitorRef> &init, std::function<bool()> done)
168 : PassManager(init), done(done) {}
169 const IR::Node *apply_visitor(const IR::Node *, const char * = 0) override;
170 PassRepeatUntil *clone() const override { return new PassRepeatUntil(*this); }
171};
172
173class PassIf : virtual public PassManager {
174 std::function<bool()> cond;
175
176 public:
177 explicit PassIf(std::function<bool()> cond) : cond(cond) {}
178 PassIf(std::function<bool()> cond, const std::initializer_list<VisitorRef> &init)
179 : PassManager(init), cond(cond) {}
180 const IR::Node *apply_visitor(const IR::Node *, const char * = 0) override;
181 PassIf *clone() const override { return new PassIf(*this); }
182};
183
184// Converts a function Node* -> Node* into a visitor
185class VisitFunctor : virtual public Visitor {
186 std::function<const IR::Node *(const IR::Node *)> fn;
187 const IR::Node *apply_visitor(const IR::Node *n, const char * = 0) override { return fn(n); }
188
189 public:
190 explicit VisitFunctor(std::function<const IR::Node *(const IR::Node *)> f) : fn(f) {}
191 explicit VisitFunctor(std::function<void()> f)
192 : fn([f](const IR::Node *n) -> const IR::Node * {
193 f();
194 return n;
195 }) {}
196
197 VisitFunctor *clone() const override { return new VisitFunctor(*this); }
198};
199
200inline PassManager::VisitorRef::VisitorRef(std::function<const IR::Node *(const IR::Node *)> fn)
201 : visitor(new VisitFunctor(fn)) {}
202
203class DynamicVisitor : virtual public Visitor {
204 Visitor *visitor;
205 profile_t init_apply(const IR::Node *root) override {
206 if (visitor) return visitor->init_apply(root);
207 return Visitor::init_apply(root);
208 }
209 void end_apply(const IR::Node *root) override {
210 if (visitor) visitor->end_apply(root);
211 }
212 const IR::Node *apply_visitor(const IR::Node *root, const char *name = 0) override {
213 if (visitor) return visitor->apply_visitor(root, name);
214 return root;
215 }
216
217 public:
218 DynamicVisitor() : visitor(nullptr) {}
219 explicit DynamicVisitor(Visitor *v) : visitor(v) {}
220 void setVisitor(Visitor *v) { visitor = v; }
221 DynamicVisitor *clone() const override { return new DynamicVisitor(*this); }
222};
223
224} // namespace P4
225
226#endif /* IR_PASS_MANAGER_H_ */
Definition visitor.h:789
Definition node.h:53
Definition ir/pass_manager.h:185
Definition visitor.h:78
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:791