P4C
The P4 Compiler
Loading...
Searching...
No Matches
node.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_NODE_H_
18#define IR_NODE_H_
19
20#include <iosfwd>
21
22#include "ir-tree-macros.h"
23#include "ir/gen-tree-macro.h"
24#include "lib/castable.h"
25#include "lib/cstring.h"
26#include "lib/exceptions.h"
27#include "lib/source_file.h"
28
29namespace P4 {
30class Visitor;
31struct Visitor_Context;
32class Inspector;
33class Modifier;
34class Transform;
35class JSONGenerator;
36class JSONLoader;
37} // namespace P4
38
39namespace P4::Util {
40class JsonObject;
41} // namespace P4::Util
42
43namespace P4::IR {
44
45using namespace P4::literals;
46
47class Node;
48class Annotation; // IWYU pragma: keep
49template <class T>
50class Vector; // IWYU pragma: keep
51template <class T>
52class IndexedVector; // IWYU pragma: keep
53
56template <class, class = void>
57struct has_static_type_name : std::false_type {};
58
59template <class T>
60struct has_static_type_name<T, std::void_t<decltype(T::static_type_name())>> : std::true_type {};
61
62template <class T>
63inline constexpr bool has_static_type_name_v = has_static_type_name<T>::value;
64
65// node interface
66class INode : public Util::IHasSourceInfo, public IHasDbPrint, public ICastable {
67 public:
68 virtual ~INode() {}
69 virtual const Node *getNode() const = 0;
70 virtual Node *getNode() = 0;
71 virtual void toJSON(JSONGenerator &) const = 0;
72 virtual cstring node_type_name() const = 0;
73 virtual void validate() const {}
74
75 // default checkedTo implementation for nodes: just fallback to generic ICastable method
76 template <typename T>
77 std::enable_if_t<!has_static_type_name_v<T>, const T *> checkedTo() const {
79 }
80
81 // alternative checkedTo implementation that produces slightly better error message
82 // due to node_type_name() / static_type_name() being available
83 template <typename T>
84 std::enable_if_t<has_static_type_name_v<T>, const T *> checkedTo() const {
85 const auto *result = to<T>();
86 BUG_CHECK(result, "Cast failed: %1% with type %2% is not a %3%.", this, node_type_name(),
87 T::static_type_name());
88 return result;
89 }
90
91 DECLARE_TYPEINFO_WITH_TYPEID(INode, NodeKind::INode);
92};
93
94class Node : public virtual INode {
95 public:
96 virtual bool apply_visitor_preorder(Modifier &v);
97 virtual void apply_visitor_postorder(Modifier &v);
98 virtual void apply_visitor_revisit(Modifier &v, const Node *n) const;
99 virtual void apply_visitor_loop_revisit(Modifier &v) const;
100 virtual bool apply_visitor_preorder(Inspector &v) const;
101 virtual void apply_visitor_postorder(Inspector &v) const;
102 virtual void apply_visitor_revisit(Inspector &v) const;
103 virtual void apply_visitor_loop_revisit(Inspector &v) const;
104 virtual const Node *apply_visitor_preorder(Transform &v);
105 virtual const Node *apply_visitor_postorder(Transform &v);
106 virtual void apply_visitor_revisit(Transform &v, const Node *n) const;
107 virtual void apply_visitor_loop_revisit(Transform &v) const;
108 Node &operator=(const Node &) = default;
109 Node &operator=(Node &&) = default;
110
111 protected:
112 static int currentId;
113 void traceVisit(const char *visitor) const;
114 friend class ::P4::Visitor;
115 friend class ::P4::Inspector;
116 friend class ::P4::Modifier;
117 friend class ::P4::Transform;
118 cstring prepareSourceInfoForJSON(Util::SourceInfo &si, unsigned *lineNumber,
119 unsigned *columnNumber) const;
120
121 public:
122 Util::SourceInfo srcInfo;
123 int id; // unique id for each node
124 int clone_id; // unique id this node was cloned from (recursively)
125 void traceCreation() const;
126 Node() : id(currentId++), clone_id(id) { traceCreation(); }
127 explicit Node(Util::SourceInfo si) : srcInfo(si), id(currentId++), clone_id(id) {
128 traceCreation();
129 }
130 Node(const Node &other) : srcInfo(other.srcInfo), id(currentId++), clone_id(other.clone_id) {
131 traceCreation();
132 }
133 virtual ~Node() {}
134 const Node *apply(Visitor &v, const Visitor_Context *ctxt = nullptr) const;
135 const Node *apply(Visitor &&v, const Visitor_Context *ctxt = nullptr) const {
136 return apply(v, ctxt);
137 }
138 virtual Node *clone() const = 0;
139 void dbprint(std::ostream &out) const override;
140 virtual void dump_fields(std::ostream &) const {}
141 const Node *getNode() const final { return this; }
142 Node *getNode() final { return this; }
143 Util::SourceInfo getSourceInfo() const override { return srcInfo; }
144 cstring node_type_name() const override { return "Node"_cs; }
145 static cstring static_type_name() { return "Node"_cs; }
146 virtual int num_children() { return 0; }
147 explicit Node(JSONLoader &json);
148 cstring toString() const override { return node_type_name(); }
149 void toJSON(JSONGenerator &json) const override;
150 void sourceInfoToJSON(JSONGenerator &json) const;
151 Util::JsonObject *sourceInfoJsonObj() const;
152 /* operator== does a 'shallow' comparison, comparing two Node subclass objects for equality,
153 * and comparing pointers in the Node directly for equality */
154 virtual bool operator==(const Node &a) const { return this->typeId() == a.typeId(); }
155 /* 'equiv' does a deep-equals comparison, comparing all non-pointer fields and recursing
156 * though all Node subclass pointers to compare them with 'equiv' as well. */
157 virtual bool equiv(const Node &a) const { return this->typeId() == a.typeId(); }
158#define DEFINE_OPEQ_FUNC(CLASS, BASE) \
159 virtual bool operator==(const CLASS &) const { return false; }
160 IRNODE_ALL_SUBCLASSES(DEFINE_OPEQ_FUNC)
161#undef DEFINE_OPEQ_FUNC
162 virtual void visit_children(Visitor &) {}
163 virtual void visit_children(Visitor &) const {}
164
165 bool operator!=(const Node &n) const { return !operator==(n); }
166
170 template <typename Sink>
171 friend void AbslStringify(Sink &sink, const IR::Node *n) {
172 sink.Append(n->toString());
173 }
174
175 DECLARE_TYPEINFO_WITH_TYPEID(Node, NodeKind::Node, INode);
176};
177
178// simple version of dbprint
179cstring dbp(const INode *node);
180
181inline bool equal(const Node *a, const Node *b) { return a == b || (a && b && *a == *b); }
182inline bool equal(const INode *a, const INode *b) {
183 return a == b || (a && b && *a->getNode() == *b->getNode());
184}
185inline bool equiv(const Node *a, const Node *b) { return a == b || (a && b && a->equiv(*b)); }
186inline bool equiv(const INode *a, const INode *b) {
187 return a == b || (a && b && a->getNode()->equiv(*b->getNode()));
188}
189// NOLINTBEGIN(bugprone-macro-parentheses)
190/* common things that ALL Node subclasses must define */
191#define IRNODE_SUBCLASS(T) \
192 public: \
193 T *clone() const override { return new T(*this); } \
194 IRNODE_COMMON_SUBCLASS(T)
195#define IRNODE_ABSTRACT_SUBCLASS(T) \
196 public: \
197 T *clone() const override = 0; \
198 IRNODE_COMMON_SUBCLASS(T)
199
200// NOLINTEND(bugprone-macro-parentheses)
201#define IRNODE_COMMON_SUBCLASS(T) \
202 public: \
203 using Node::operator==; \
204 bool apply_visitor_preorder(Modifier &v) override; \
205 void apply_visitor_postorder(Modifier &v) override; \
206 void apply_visitor_revisit(Modifier &v, const Node *n) const override; \
207 void apply_visitor_loop_revisit(Modifier &v) const override; \
208 bool apply_visitor_preorder(Inspector &v) const override; \
209 void apply_visitor_postorder(Inspector &v) const override; \
210 void apply_visitor_revisit(Inspector &v) const override; \
211 void apply_visitor_loop_revisit(Inspector &v) const override; \
212 const Node *apply_visitor_preorder(Transform &v) override; \
213 const Node *apply_visitor_postorder(Transform &v) override; \
214 void apply_visitor_revisit(Transform &v, const Node *n) const override; \
215 void apply_visitor_loop_revisit(Transform &v) const override;
216
217/* only define 'apply' for a limited number of classes (those we want to call
218 * visitors directly on), as defining it and making it virtual would mean that
219 * NO Transform could transform the class into a sibling class */
220#define IRNODE_DECLARE_APPLY_OVERLOAD(T) \
221 const T *apply(Visitor &v, const Visitor_Context *ctxt = nullptr) const; \
222 const T *apply(Visitor &&v, const Visitor_Context *ctxt = nullptr) const { \
223 return apply(v, ctxt); \
224 }
225#define IRNODE_DEFINE_APPLY_OVERLOAD(CLASS, TEMPLATE, TT) \
226 TEMPLATE \
227 const IR::CLASS TT *IR::CLASS TT::apply(Visitor &v, const Visitor_Context *ctxt) const { \
228 const CLASS *tmp = this; \
229 auto prof = v.init_apply(tmp, ctxt); \
230 v.visit(tmp); \
231 v.end_apply(tmp); \
232 return tmp; \
233 }
234
235} // namespace P4::IR
236
237#endif /* IR_NODE_H_ */
Definition castable.h:36
const T * checkedTo() const
Performs a checked cast. A BUG occurs if the cast fails.
Definition castable.h:54
Definition stringify.h:33
Definition node.h:66
Definition node.h:52
Definition node.h:94
friend void AbslStringify(Sink &sink, const IR::Node *n)
Definition node.h:171
Definition visitor.h:400
Definition json_generator.h:36
Definition json_loader.h:38
Definition visitor.h:372
Definition visitor.h:424
Definition source_file.h:227
Definition json.h:164
Definition source_file.h:131
Definition visitor.h:75
Definition cstring.h:85
Definition cstring.h:80
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
STL namespace.
Definition node.h:57
T * to() noexcept
Definition rtti.h:226
virtual TypeId typeId() const noexcept=0
Definition visitor.h:47