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 virtual const Annotation *getAnnotation(cstring) const { return nullptr; }
75
76 // default checkedTo implementation for nodes: just fallback to generic ICastable method
77 template <typename T>
78 std::enable_if_t<!has_static_type_name_v<T>, const T *> checkedTo() const {
80 }
81
82 // alternative checkedTo implementation that produces slightly better error message
83 // due to node_type_name() / static_type_name() being available
84 template <typename T>
85 std::enable_if_t<has_static_type_name_v<T>, const T *> checkedTo() const {
86 const auto *result = to<T>();
87 BUG_CHECK(result, "Cast failed: %1% with type %2% is not a %3%.", this, node_type_name(),
88 T::static_type_name());
89 return result;
90 }
91
92 DECLARE_TYPEINFO_WITH_TYPEID(INode, NodeKind::INode);
93};
94
95class Node : public virtual INode {
96 public:
97 virtual bool apply_visitor_preorder(Modifier &v);
98 virtual void apply_visitor_postorder(Modifier &v);
99 virtual void apply_visitor_revisit(Modifier &v, const Node *n) const;
100 virtual void apply_visitor_loop_revisit(Modifier &v) const;
101 virtual bool apply_visitor_preorder(Inspector &v) const;
102 virtual void apply_visitor_postorder(Inspector &v) const;
103 virtual void apply_visitor_revisit(Inspector &v) const;
104 virtual void apply_visitor_loop_revisit(Inspector &v) const;
105 virtual const Node *apply_visitor_preorder(Transform &v);
106 virtual const Node *apply_visitor_postorder(Transform &v);
107 virtual void apply_visitor_revisit(Transform &v, const Node *n) const;
108 virtual void apply_visitor_loop_revisit(Transform &v) const;
109 Node &operator=(const Node &) = default;
110 Node &operator=(Node &&) = default;
111
112 protected:
113 static int currentId;
114 void traceVisit(const char *visitor) const;
115 friend class ::P4::Visitor;
116 friend class ::P4::Inspector;
117 friend class ::P4::Modifier;
118 friend class ::P4::Transform;
119 cstring prepareSourceInfoForJSON(Util::SourceInfo &si, unsigned *lineNumber,
120 unsigned *columnNumber) const;
121
122 public:
123 Util::SourceInfo srcInfo;
124 int id; // unique id for each node
125 int clone_id; // unique id this node was cloned from (recursively)
126 void traceCreation() const;
127 Node() : id(currentId++), clone_id(id) { traceCreation(); }
128 explicit Node(Util::SourceInfo si) : srcInfo(si), id(currentId++), clone_id(id) {
129 traceCreation();
130 }
131 Node(const Node &other) : srcInfo(other.srcInfo), id(currentId++), clone_id(other.clone_id) {
132 traceCreation();
133 }
134 virtual ~Node() {}
135 const Node *apply(Visitor &v, const Visitor_Context *ctxt = nullptr) const;
136 const Node *apply(Visitor &&v, const Visitor_Context *ctxt = nullptr) const {
137 return apply(v, ctxt);
138 }
139 virtual Node *clone() const = 0;
140 void dbprint(std::ostream &out) const override;
141 virtual void dump_fields(std::ostream &) const {}
142 const Node *getNode() const final { return this; }
143 Node *getNode() final { return this; }
144 Util::SourceInfo getSourceInfo() const override { return srcInfo; }
145 cstring node_type_name() const override { return "Node"_cs; }
146 static cstring static_type_name() { return "Node"_cs; }
147 virtual int num_children() { return 0; }
148 explicit Node(JSONLoader &json);
149 cstring toString() const override { return node_type_name(); }
150 void toJSON(JSONGenerator &json) const override;
151 void sourceInfoToJSON(JSONGenerator &json) const;
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 &) {}
164 virtual void visit_children(Visitor &) const {}
165
166 bool operator!=(const Node &n) const { return !operator==(n); }
167
168 DECLARE_TYPEINFO_WITH_TYPEID(Node, NodeKind::Node, INode);
169};
170
171// simple version of dbprint
172cstring dbp(const INode *node);
173
174inline bool equal(const Node *a, const Node *b) { return a == b || (a && b && *a == *b); }
175inline bool equal(const INode *a, const INode *b) {
176 return a == b || (a && b && *a->getNode() == *b->getNode());
177}
178inline bool equiv(const Node *a, const Node *b) { return a == b || (a && b && a->equiv(*b)); }
179inline bool equiv(const INode *a, const INode *b) {
180 return a == b || (a && b && a->getNode()->equiv(*b->getNode()));
181}
182// NOLINTBEGIN(bugprone-macro-parentheses)
183/* common things that ALL Node subclasses must define */
184#define IRNODE_SUBCLASS(T) \
185 public: \
186 T *clone() const override { return new T(*this); } \
187 IRNODE_COMMON_SUBCLASS(T)
188#define IRNODE_ABSTRACT_SUBCLASS(T) \
189 public: \
190 T *clone() const override = 0; \
191 IRNODE_COMMON_SUBCLASS(T)
192
193// NOLINTEND(bugprone-macro-parentheses)
194#define IRNODE_COMMON_SUBCLASS(T) \
195 public: \
196 using Node::operator==; \
197 bool apply_visitor_preorder(Modifier &v) override; \
198 void apply_visitor_postorder(Modifier &v) override; \
199 void apply_visitor_revisit(Modifier &v, const Node *n) const override; \
200 void apply_visitor_loop_revisit(Modifier &v) const override; \
201 bool apply_visitor_preorder(Inspector &v) const override; \
202 void apply_visitor_postorder(Inspector &v) const override; \
203 void apply_visitor_revisit(Inspector &v) const override; \
204 void apply_visitor_loop_revisit(Inspector &v) const override; \
205 const Node *apply_visitor_preorder(Transform &v) override; \
206 const Node *apply_visitor_postorder(Transform &v) override; \
207 void apply_visitor_revisit(Transform &v, const Node *n) const override; \
208 void apply_visitor_loop_revisit(Transform &v) const override;
209
210/* only define 'apply' for a limited number of classes (those we want to call
211 * visitors directly on), as defining it and making it virtual would mean that
212 * NO Transform could transform the class into a sibling class */
213#define IRNODE_DECLARE_APPLY_OVERLOAD(T) \
214 const T *apply(Visitor &v, const Visitor_Context *ctxt = nullptr) const; \
215 const T *apply(Visitor &&v, const Visitor_Context *ctxt = nullptr) const { \
216 return apply(v, ctxt); \
217 }
218#define IRNODE_DEFINE_APPLY_OVERLOAD(CLASS, TEMPLATE, TT) \
219 TEMPLATE \
220 const IR::CLASS TT *IR::CLASS TT::apply(Visitor &v, const Visitor_Context *ctxt) const { \
221 const CLASS *tmp = this; \
222 auto prof = v.init_apply(tmp, ctxt); \
223 v.visit(tmp); \
224 v.end_apply(tmp); \
225 return tmp; \
226 }
227
228} // namespace P4::IR
229
230#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:95
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:220
Definition json.h:164
Definition source_file.h:124
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