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 void sourceInfoFromJSON(JSONLoader &json);
152 Util::JsonObject *sourceInfoJsonObj() const;
153 /* operator== does a 'shallow' comparison, comparing two Node subclass objects for equality,
154 * and comparing pointers in the Node directly for equality */
155 virtual bool operator==(const Node &a) const { return this->typeId() == a.typeId(); }
156 /* 'equiv' does a deep-equals comparison, comparing all non-pointer fields and recursing
157 * though all Node subclass pointers to compare them with 'equiv' as well. */
158 virtual bool equiv(const Node &a) const { return this->typeId() == a.typeId(); }
159#define DEFINE_OPEQ_FUNC(CLASS, BASE) \
160 virtual bool operator==(const CLASS &) const { return false; }
161 IRNODE_ALL_SUBCLASSES(DEFINE_OPEQ_FUNC)
162#undef DEFINE_OPEQ_FUNC
163 virtual void visit_children(Visitor &, const char * /*name*/ = nullptr) {}
164 virtual void visit_children(Visitor &, const char * /*name*/ = nullptr) const {}
165
166 bool operator!=(const Node &n) const { return !operator==(n); }
167
171 template <typename Sink>
172 friend void AbslStringify(Sink &sink, const IR::Node *n) {
173 sink.Append(n->toString());
174 }
175
176 DECLARE_TYPEINFO_WITH_TYPEID(Node, NodeKind::Node, INode);
177};
178
179// simple version of dbprint
180cstring dbp(const INode *node);
181
182inline bool equal(const Node *a, const Node *b) { return a == b || (a && b && *a == *b); }
183inline bool equal(const INode *a, const INode *b) {
184 return a == b || (a && b && *a->getNode() == *b->getNode());
185}
186inline bool equiv(const Node *a, const Node *b) { return a == b || (a && b && a->equiv(*b)); }
187inline bool equiv(const INode *a, const INode *b) {
188 return a == b || (a && b && a->getNode()->equiv(*b->getNode()));
189}
190// NOLINTBEGIN(bugprone-macro-parentheses)
191/* common things that ALL Node subclasses must define */
192#define IRNODE_SUBCLASS(T) \
193 public: \
194 T *clone() const override { return new T(*this); } \
195 IRNODE_COMMON_SUBCLASS(T)
196#define IRNODE_ABSTRACT_SUBCLASS(T) \
197 public: \
198 T *clone() const override = 0; \
199 IRNODE_COMMON_SUBCLASS(T)
200
201// NOLINTEND(bugprone-macro-parentheses)
202#define IRNODE_COMMON_SUBCLASS(T) \
203 public: \
204 using Node::operator==; \
205 bool apply_visitor_preorder(Modifier &v) override; \
206 void apply_visitor_postorder(Modifier &v) override; \
207 void apply_visitor_revisit(Modifier &v, const Node *n) const override; \
208 void apply_visitor_loop_revisit(Modifier &v) const override; \
209 bool apply_visitor_preorder(Inspector &v) const override; \
210 void apply_visitor_postorder(Inspector &v) const override; \
211 void apply_visitor_revisit(Inspector &v) const override; \
212 void apply_visitor_loop_revisit(Inspector &v) const override; \
213 const Node *apply_visitor_preorder(Transform &v) override; \
214 const Node *apply_visitor_postorder(Transform &v) override; \
215 void apply_visitor_revisit(Transform &v, const Node *n) const override; \
216 void apply_visitor_loop_revisit(Transform &v) const override;
217
218/* only define 'apply' for a limited number of classes (those we want to call
219 * visitors directly on), as defining it and making it virtual would mean that
220 * NO Transform could transform the class into a sibling class */
221#define IRNODE_DECLARE_APPLY_OVERLOAD(T) \
222 const T *apply(Visitor &v, const Visitor_Context *ctxt = nullptr) const; \
223 const T *apply(Visitor &&v, const Visitor_Context *ctxt = nullptr) const { \
224 return apply(v, ctxt); \
225 }
226#define IRNODE_DEFINE_APPLY_OVERLOAD(CLASS, TEMPLATE, TT) \
227 TEMPLATE \
228 const IR::CLASS TT *IR::CLASS TT::apply(Visitor &v, const Visitor_Context *ctxt) const { \
229 const CLASS *tmp = this; \
230 auto prof = v.init_apply(tmp, ctxt); \
231 v.visit(tmp); \
232 v.end_apply(tmp); \
233 return tmp; \
234 }
235
236} // namespace P4::IR
237
238#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 indexed_vector.h:40
Definition node.h:94
friend void AbslStringify(Sink &sink, const IR::Node *n)
Definition node.h:172
Definition vector.h:59
Definition visitor.h:413
Definition json_generator.h:39
Definition json_loader.h:40
Definition visitor.h:385
Definition visitor.h:437
Definition source_file.h:228
Definition json.h:165
Definition source_file.h:132
Definition visitor.h:75
Definition cstring.h:85
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