P4C
The P4 Compiler
Loading...
Searching...
No Matches
p4formatter.h
1#ifndef BACKENDS_P4FMT_P4FORMATTER_H_
2#define BACKENDS_P4FMT_P4FORMATTER_H_
3
4#include "frontends/common/resolveReferences/resolveReferences.h"
5#include "ir/ir.h"
6#include "ir/visitor.h"
7#include "lib/sourceCodeBuilder.h"
8
9namespace P4::P4Fmt {
15 int expressionPrecedence;
16 bool isDeclaration;
17 bool withinArgument;
18 bool noIncludes = false;
20
21 struct VecPrint {
22 cstring separator;
23 cstring terminator;
24
25 VecPrint(const char *sep, const char *term) : separator(sep), terminator(term) {}
26 };
27
28 struct ListPrint {
29 cstring start;
30 cstring end;
31
32 ListPrint(const char *start, const char *end) : start(start), end(end) {}
33 };
34
35 // maintained as stacks
36 std::vector<VecPrint> vectorSeparator;
37 size_t vectorSeparator_init_apply_size = 0;
38 std::vector<ListPrint> listTerminators;
39 size_t listTerminators_init_apply_size = 0;
40
41 void setVecSep(const char *sep, const char *term = nullptr) {
42 vectorSeparator.push_back(VecPrint(sep, term));
43 }
44 void doneVec() {
45 BUG_CHECK(!vectorSeparator.empty(), "Empty vectorSeparator");
46 vectorSeparator.pop_back();
47 }
48 VecPrint getSep() {
49 BUG_CHECK(!vectorSeparator.empty(), "Empty vectorSeparator");
50 return vectorSeparator.back();
51 }
52
53 void doneList() {
54 BUG_CHECK(!listTerminators.empty(), "Empty listTerminators");
55 listTerminators.pop_back();
56 }
57
58 // RAII helper class to manage separators
59 class WithSeparator {
60 P4Formatter &formatter;
61
62 public:
63 WithSeparator(P4Formatter &fmt, const char *sep, const char *term = nullptr)
64 : formatter(fmt) {
65 formatter.setVecSep(sep, term);
66 }
67
68 ~WithSeparator() { formatter.doneVec(); }
69 };
70
71 // For collections which provide support for range based for loops
72 // e.g. `IndexedVector` or similar collections
73 template <typename Collection, typename Func>
74 void visitCollection(const Collection &collection, const std::string &separator,
75 Func visitFunc) {
76 bool first = true;
77 for (const auto &elem : collection) {
78 if (!first) {
79 builder.append(separator);
80 }
81 first = false;
82 visitFunc(elem);
83 }
84 }
85
86 // For `Enumerator`
87 template <typename Enumerator, typename Func>
88 void visitCollection(Enumerator &enumerator, const std::string &separator, Func visitFunc) {
89 bool first = true;
90 while (enumerator.moveNext()) {
91 if (!first) {
92 builder.append(separator);
93 }
94 first = false;
95 visitFunc(enumerator.getCurrent());
96 }
97 }
98
99 bool isSystemFile(std::filesystem::path &file);
100 std::filesystem::path ifSystemFile(
101 const IR::Node *node); // return file containing node if system file
102
103 public:
104 // Output is constructed here
106 // FIXME -- simplify this by getting rid of the 'builder' object and just emitting
107 // directly to the ostream. The SourceCodeBuilder object does not appear to add any
108 // useful functionality the ostream does not already provide; it just serves to
109 // obfuscate the code
110 std::ostream *outStream;
115
116 explicit P4Formatter(Util::SourceCodeBuilder &builder, cstring mainFile = nullptr)
117 : expressionPrecedence(DBPrint::Prec_Low),
118 isDeclaration(true),
119 withinArgument(false),
120 builder(builder),
121 outStream(nullptr),
123 visitDagOnce = false;
124 setName("P4Formatter");
125 }
126 explicit P4Formatter(std::ostream *outStream, cstring mainFile = nullptr)
127 : expressionPrecedence(DBPrint::Prec_Low),
128 isDeclaration(true),
129 withinArgument(false),
130 builder(*new Util::SourceCodeBuilder()),
131 outStream(outStream),
133 visitDagOnce = false;
134 setName("P4Formatter");
135 }
136 P4Formatter()
137 : // this is useful for debugging
138 expressionPrecedence(DBPrint::Prec_Low),
139 isDeclaration(true),
140 withinArgument(false),
141 builder(*new Util::SourceCodeBuilder()),
142 outStream(&std::cout),
143 mainFile(nullptr) {
144 visitDagOnce = false;
145 setName("P4Formatter");
146 }
147
148 void setnoIncludesArg(bool condition) { noIncludes = condition; }
149
150 void setListTerm(const char *start, const char *end) {
151 listTerminators.push_back(ListPrint(start, end));
152 }
153 Visitor::profile_t init_apply(const IR::Node *node) override;
154 void end_apply(const IR::Node *node) override;
155
156 bool process(const IR::Type_StructLike *t, const char *name);
157
158 bool preorder(const IR::Node *node) override;
159
160 // types
161 bool preorder(const IR::Type_Boolean *t) override;
162 bool preorder(const IR::Type_Varbits *t) override;
163 bool preorder(const IR::Type_Bits *t) override;
164 bool preorder(const IR::Type_InfInt *t) override;
165 bool preorder(const IR::Type_String *t) override;
166 bool preorder(const IR::Type_Var *t) override;
167 bool preorder(const IR::Type_Dontcare *t) override;
168 bool preorder(const IR::Type_Void *t) override;
169 bool preorder(const IR::Type_Error *t) override;
170 bool preorder(const IR::Type_Struct *t) override { return process(t, "struct"); }
171 bool preorder(const IR::Type_Header *t) override { return process(t, "header"); }
172 bool preorder(const IR::Type_HeaderUnion *t) override { return process(t, "header_union"); }
173 bool preorder(const IR::Type_Package *t) override;
174 bool preorder(const IR::Type_Parser *t) override;
175 bool preorder(const IR::Type_Control *t) override;
176 bool preorder(const IR::Type_Name *t) override;
177 bool preorder(const IR::Type_Stack *t) override;
178 bool preorder(const IR::Type_Specialized *t) override;
179 bool preorder(const IR::Type_Enum *t) override;
180 bool preorder(const IR::Type_SerEnum *t) override;
181 bool preorder(const IR::Type_Typedef *t) override;
182 bool preorder(const IR::Type_Newtype *t) override;
183 bool preorder(const IR::Type_Extern *t) override;
184 bool preorder(const IR::Type_Unknown *t) override;
185 bool preorder(const IR::Type_BaseList *t) override;
186 bool preorder(const IR::Type *t) override {
187 builder.append(t->toString());
188 return false;
189 }
190 bool preorder(const IR::Type_SpecializedCanonical *t) override {
191 BUG("%1%: specialized canonical type in IR tree", t);
192 return false;
193 }
194
195 // declarations
196 bool preorder(const IR::Declaration_Constant *cst) override;
197 bool preorder(const IR::Declaration_Variable *v) override;
198 bool preorder(const IR::Declaration_Instance *t) override;
199 bool preorder(const IR::Declaration_MatchKind *d) override;
200
201 // expressions
202 bool preorder(const IR::Dots *e) override;
203 bool preorder(const IR::NamedDots *e) override;
204 bool preorder(const IR::Constant *c) override;
205 bool preorder(const IR::Slice *slice) override;
206 bool preorder(const IR::BoolLiteral *b) override;
207 bool preorder(const IR::StringLiteral *s) override;
208 bool preorder(const IR::PathExpression *p) override;
209 bool preorder(const IR::Cast *c) override;
210 bool preorder(const IR::Operation_Binary *b) override;
211 bool preorder(const IR::Operation_Unary *u) override;
212 bool preorder(const IR::ArrayIndex *a) override;
213 bool preorder(const IR::TypeNameExpression *e) override;
214 bool preorder(const IR::Mux *a) override;
215 bool preorder(const IR::ConstructorCallExpression *e) override;
216 bool preorder(const IR::Member *e) override;
217 bool preorder(const IR::SelectCase *e) override;
218 bool preorder(const IR::SelectExpression *e) override;
219 bool preorder(const IR::ListExpression *e) override;
220 bool preorder(const IR::P4ListExpression *e) override;
221 bool preorder(const IR::StructExpression *e) override;
222 bool preorder(const IR::Invalid *e) override;
223 bool preorder(const IR::InvalidHeader *e) override;
224 bool preorder(const IR::InvalidHeaderUnion *e) override;
225 bool preorder(const IR::HeaderStackExpression *e) override;
226 bool preorder(const IR::MethodCallExpression *e) override;
227 bool preorder(const IR::DefaultExpression *e) override;
228 bool preorder(const IR::This *e) override;
229
230 // vectors
231 bool preorder(const IR::Vector<IR::ActionListElement> *v) override;
232 bool preorder(const IR::Vector<IR::Annotation> *v) override;
233 bool preorder(const IR::Vector<IR::Entry> *v) override;
234 bool preorder(const IR::Vector<IR::Expression> *v) override;
235 bool preorder(const IR::Vector<IR::Argument> *v) override;
236 bool preorder(const IR::Vector<IR::KeyElement> *v) override;
237 bool preorder(const IR::Vector<IR::Method> *v) override;
238 bool preorder(const IR::Vector<IR::Node> *v) override;
239 bool preorder(const IR::Vector<IR::SelectCase> *v) override;
240 bool preorder(const IR::Vector<IR::SwitchCase> *v) override;
241 bool preorder(const IR::Vector<IR::Type> *v) override;
242 bool preorder(const IR::IndexedVector<IR::Declaration_ID> *v) override;
243 bool preorder(const IR::IndexedVector<IR::Declaration> *v) override;
244 bool preorder(const IR::IndexedVector<IR::Node> *v) override;
245 bool preorder(const IR::IndexedVector<IR::ParserState> *v) override;
246 bool preorder(const IR::IndexedVector<IR::StatOrDecl> *v) override;
247
248 // statements
249 bool preorder(const IR::AssignmentStatement *s) override;
250 bool preorder(const IR::BlockStatement *s) override;
251 bool preorder(const IR::MethodCallStatement *s) override;
252 bool preorder(const IR::EmptyStatement *s) override;
253 bool preorder(const IR::ReturnStatement *s) override;
254 bool preorder(const IR::BreakStatement *s) override;
255 bool preorder(const IR::ContinueStatement *s) override;
256 bool preorder(const IR::ExitStatement *s) override;
257 bool preorder(const IR::SwitchCase *s) override;
258 bool preorder(const IR::SwitchStatement *s) override;
259 bool preorder(const IR::IfStatement *s) override;
260 bool preorder(const IR::ForStatement *s) override;
261 bool preorder(const IR::ForInStatement *s) override;
262
263 // misc
264 bool preorder(const IR::NamedExpression *ne) override;
265 bool preorder(const IR::Argument *arg) override;
266 bool preorder(const IR::Path *p) override;
267 bool preorder(const IR::Parameter *p) override;
268 bool preorder(const IR::Annotations *a) override;
269 bool preorder(const IR::Annotation *a) override;
270 bool preorder(const IR::P4Program *program) override;
271 bool preorder(const IR::P4Control *c) override;
272 bool preorder(const IR::P4Action *c) override;
273 bool preorder(const IR::ParserState *s) override;
274 bool preorder(const IR::P4Parser *c) override;
275 bool preorder(const IR::TypeParameters *p) override;
276 bool preorder(const IR::ParameterList *p) override;
277 bool preorder(const IR::Method *p) override;
278 bool preorder(const IR::Function *function) override;
279
280 bool preorder(const IR::ExpressionValue *v) override;
281 bool preorder(const IR::ActionListElement *ale) override;
282 bool preorder(const IR::ActionList *v) override;
283 bool preorder(const IR::Key *v) override;
284 bool preorder(const IR::Property *p) override;
285 bool preorder(const IR::TableProperties *t) override;
286 bool preorder(const IR::EntriesList *l) override;
287 bool preorder(const IR::Entry *e) override;
288 bool preorder(const IR::P4Table *c) override;
289 bool preorder(const IR::P4ValueSet *c) override;
290
291 // in case it is accidentally called on a V1Program
292 bool preorder(const IR::V1Program *) override { return false; }
293};
294
295std::string toP4(const IR::INode *node);
296
297} // namespace P4::P4Fmt
298#endif /* BACKENDS_P4FMT_P4FORMATTER_H_ */
Definition node.h:95
Definition visitor.h:400
Definition p4formatter.h:14
cstring mainFile
Definition p4formatter.h:114
Visitor mixin for looking up names in enclosing scopes from the Visitor::Context.
Definition resolveReferences.h:35
Definition sourceCodeBuilder.h:29
Definition cstring.h:85
STL namespace.