P4C
The P4 Compiler
Loading...
Searching...
No Matches
parseAnnotations.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 P4_PARSEANNOTATIONS_H_
18#define P4_PARSEANNOTATIONS_H_
19
20#include "frontends/p4/typeChecking/typeChecker.h"
21#include "frontends/parsers/parserDriver.h"
22#include "ir/ir.h"
23
24/*
25 * Parses known/predefined annotations used by the compiler.
26 */
27namespace P4 {
28
29// A no-op handler. Useful for avoiding warnings about ignored annotations.
30#define PARSE_SKIP(aname) \
31 { aname, &P4::ParseAnnotations::parseSkip }
32
33// Parses an empty annotation.
34#define PARSE_EMPTY(aname) \
35 { aname, &P4::ParseAnnotations::parseEmpty }
36
37// Parses an annotation with a single-element body.
38#define PARSE(aname, tname) \
39 { \
40 aname, [](IR::Annotation *annotation) { \
41 const IR::tname *parsed = \
42 P4::P4ParserDriver::parse##tname(annotation->srcInfo, annotation->getUnparsed()); \
43 if (parsed != nullptr) { \
44 annotation->body.emplace<IR::Annotation::ExpressionAnnotation>(parsed); \
45 } \
46 return parsed != nullptr; \
47 } \
48 }
49
50// Parses an annotation that is either an integer constant or a string literal.
51#define PARSE_CONSTANT_OR_STRING_LITERAL(aname) \
52 { \
53 aname, [](IR::Annotation *annotation) { \
54 const IR::Expression *parsed = P4::P4ParserDriver::parseConstantOrStringLiteral( \
55 annotation->srcInfo, annotation->getUnparsed()); \
56 if (parsed != nullptr) { \
57 annotation->body.emplace<IR::Annotation::ExpressionAnnotation>(parsed); \
58 } \
59 return parsed != nullptr; \
60 } \
61 }
62
63#define PARSE_CONSTANT(aname) \
64 { \
65 aname, [](IR::Annotation *annotation) { \
66 const IR::Expression *parsed = \
67 P4::P4ParserDriver::parseConstant(annotation->srcInfo, annotation->getUnparsed()); \
68 if (parsed != nullptr) { \
69 annotation->body.emplace<IR::Annotation::ExpressionAnnotation>(parsed); \
70 } \
71 return parsed != nullptr; \
72 } \
73 }
74
75#define PARSE_STRING_LITERAL(aname) \
76 { \
77 aname, [](IR::Annotation *annotation) { \
78 const IR::Expression *parsed = P4::P4ParserDriver::parseStringLiteral( \
79 annotation->srcInfo, annotation->getUnparsed()); \
80 if (parsed != nullptr) { \
81 annotation->body.emplace<IR::Annotation::ExpressionAnnotation>(parsed); \
82 } \
83 return parsed != nullptr; \
84 } \
85 }
86
87// Parses an annotation whose body is a pair.
88#define PARSE_PAIR(aname, tname) \
89 { \
90 aname, [](IR::Annotation *annotation) { \
91 const IR::Vector<IR::Expression> *parsed = P4::P4ParserDriver::parse##tname##Pair( \
92 annotation->srcInfo, annotation->getUnparsed()); \
93 if (parsed != nullptr) { \
94 annotation->body.emplace<IR::Annotation::ExpressionAnnotation>(*parsed); \
95 } \
96 return parsed != nullptr; \
97 } \
98 }
99
100// Parses an annotation whose body is a triple.
101#define PARSE_TRIPLE(aname, tname) \
102 { \
103 aname, [](IR::Annotation *annotation) { \
104 const IR::Vector<IR::Expression> *parsed = P4::P4ParserDriver::parse##tname##Triple( \
105 annotation->srcInfo, annotation->getUnparsed()); \
106 if (parsed != nullptr) { \
107 annotation->body.emplace<IR::Annotation::ExpressionAnnotation>(*parsed); \
108 } \
109 return parsed != nullptr; \
110 } \
111 }
112
113// Parses an annotation whose body is a list of expressions.
114#define PARSE_EXPRESSION_LIST(aname) \
115 { aname, &P4::ParseAnnotations::parseExpressionList }
116
117// Parses an annotation whose body is a list of key-value pairs.
118#define PARSE_KV_LIST(aname) \
119 { aname, &P4::ParseAnnotations::parseKvList }
120
121// Parses an annotation whose body is a list of integer constants.
122#define PARSE_CONSTANT_LIST(aname) \
123 { aname, &P4::ParseAnnotations::parseConstantList }
124
125// Parses an annotation whose body is a list, where each element is an integer constant or a string
126// literal.
127#define PARSE_CONSTANT_OR_STRING_LITERAL_LIST(aname) \
128 { aname, &P4::ParseAnnotations::parseConstantOrStringLiteralList }
129
130// Parses an annotation whose body is a list of string literals.
131#define PARSE_STRING_LITERAL_LIST(aname) \
132 { aname, &P4::ParseAnnotations::parseStringLiteralList }
133
134// Parses a P4Runtime translation which contains both types or expressions.
135#define PARSE_P4RUNTIME_TRANSLATION(aname) \
136 { aname, &P4::ParseAnnotations::parseP4rtTranslationAnnotation }
137
139 public:
140 using Modifier::postorder;
141
144 typedef std::function<bool(IR::Annotation *)> Handler;
145
147 typedef std::unordered_map<cstring, Handler> HandlerMap;
148
150 explicit ParseAnnotations(bool warn = false) : warnUnknown(warn), handlers(standardHandlers()) {
151 setName("ParseAnnotations");
152 }
153
155 ParseAnnotations(const char *targetName, bool includeStandard, HandlerMap handlers,
156 bool warn = false)
157 : warnUnknown(warn) {
158 std::string buf = targetName;
159 buf += "__ParseAnnotations";
160 setName(buf.c_str());
161
162 if (includeStandard) {
163 this->handlers = standardHandlers();
164 this->handlers.insert(handlers.begin(), handlers.end());
165 } else {
166 this->handlers = handlers;
167 }
168 }
169
170 void postorder(IR::Annotation *annotation) final;
171
172 static HandlerMap standardHandlers();
173
174 static bool parseSkip(IR::Annotation *annotation);
175 static bool parseEmpty(IR::Annotation *annotation);
176 static bool parseExpressionList(IR::Annotation *annotation);
177 static bool parseKvList(IR::Annotation *annotation);
178 static bool parseConstantList(IR::Annotation *annotation);
179 static bool parseConstantOrStringLiteralList(IR::Annotation *annotation);
180 static bool parseStringLiteralList(IR::Annotation *annotation);
181 // Parses a `@p4runtime_translation` annotation.
182 static bool parseP4rtTranslationAnnotation(IR::Annotation *annotation);
183
184 void addHandler(cstring name, Handler h) { handlers.insert({name, h}); }
185
186 private:
188 const bool warnUnknown;
189
192 std::set<cstring> warned;
193
194 HandlerMap handlers;
195};
196
198class ParseAnnotationBodies final : public PassManager {
199 public:
201 passes.push_back(pa);
202 passes.push_back(new ClearTypeMap(typeMap));
203 setName("ParseAnnotationBodies");
204 }
205};
206
207} // namespace P4
208
209#endif /* P4_PARSEANNOTATIONS_H_ */
Definition typeChecker.h:32
Definition visitor.h:372
Clears a type map after calling a ParseAnnotations instance.
Definition parseAnnotations.h:198
Definition parseAnnotations.h:138
ParseAnnotations(bool warn=false)
Produces a pass that rewrites the spec-defined annotations.
Definition parseAnnotations.h:150
std::function< bool(IR::Annotation *)> Handler
Definition parseAnnotations.h:144
std::unordered_map< cstring, Handler > HandlerMap
Keyed on annotation names.
Definition parseAnnotations.h:147
ParseAnnotations(const char *targetName, bool includeStandard, HandlerMap handlers, bool warn=false)
Produces a pass that rewrites a custom set of annotations.
Definition parseAnnotations.h:155
Definition ir/pass_manager.h:40
Definition typeMap.h:41
Definition cstring.h:85
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24