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 FRONTENDS_P4_PARSEANNOTATIONS_H_
18#define FRONTENDS_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) {aname, &P4::ParseAnnotations::parseSkip}
31
32// Parses an empty annotation.
33#define PARSE_EMPTY(aname) {aname, &P4::ParseAnnotations::parseEmpty}
34
35// Parses an annotation with a single-element body.
36#define PARSE(aname, tname) \
37 {aname, [](IR::Annotation *annotation) { \
38 const IR::tname *parsed = \
39 P4::P4ParserDriver::parse##tname(annotation->srcInfo, annotation->getUnparsed()); \
40 if (parsed != nullptr) { \
41 annotation->body.emplace<IR::Annotation::ExpressionAnnotation>(parsed); \
42 } \
43 return parsed != nullptr; \
44 }}
45
46// Parses an annotation that is either an integer constant or a string literal.
47#define PARSE_CONSTANT_OR_STRING_LITERAL(aname) \
48 {aname, [](IR::Annotation *annotation) { \
49 const IR::Expression *parsed = P4::P4ParserDriver::parseConstantOrStringLiteral( \
50 annotation->srcInfo, annotation->getUnparsed()); \
51 if (parsed != nullptr) { \
52 annotation->body.emplace<IR::Annotation::ExpressionAnnotation>(parsed); \
53 } \
54 return parsed != nullptr; \
55 }}
56
57#define PARSE_CONSTANT(aname) \
58 {aname, [](IR::Annotation *annotation) { \
59 const IR::Expression *parsed = \
60 P4::P4ParserDriver::parseConstant(annotation->srcInfo, annotation->getUnparsed()); \
61 if (parsed != nullptr) { \
62 annotation->body.emplace<IR::Annotation::ExpressionAnnotation>(parsed); \
63 } \
64 return parsed != nullptr; \
65 }}
66
67#define PARSE_STRING_LITERAL(aname) \
68 {aname, [](IR::Annotation *annotation) { \
69 const IR::Expression *parsed = P4::P4ParserDriver::parseStringLiteral( \
70 annotation->srcInfo, annotation->getUnparsed()); \
71 if (parsed != nullptr) { \
72 annotation->body.emplace<IR::Annotation::ExpressionAnnotation>(parsed); \
73 } \
74 return parsed != nullptr; \
75 }}
76
77// Parses an annotation whose body is a pair.
78#define PARSE_PAIR(aname, tname) \
79 {aname, [](IR::Annotation *annotation) { \
80 const IR::Vector<IR::Expression> *parsed = P4::P4ParserDriver::parse##tname##Pair( \
81 annotation->srcInfo, annotation->getUnparsed()); \
82 if (parsed != nullptr) { \
83 annotation->body.emplace<IR::Annotation::ExpressionAnnotation>(*parsed); \
84 } \
85 return parsed != nullptr; \
86 }}
87
88// Parses an annotation whose body is a triple.
89#define PARSE_TRIPLE(aname, tname) \
90 {aname, [](IR::Annotation *annotation) { \
91 const IR::Vector<IR::Expression> *parsed = P4::P4ParserDriver::parse##tname##Triple( \
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// Parses an annotation whose body is a list of expressions.
100#define PARSE_EXPRESSION_LIST(aname) {aname, &P4::ParseAnnotations::parseExpressionList}
101
102// Parses an annotation whose body is a list of key-value pairs.
103#define PARSE_KV_LIST(aname) {aname, &P4::ParseAnnotations::parseKvList}
104
105// Parses an annotation whose body is a list of integer constants.
106#define PARSE_CONSTANT_LIST(aname) {aname, &P4::ParseAnnotations::parseConstantList}
107
108// Parses an annotation whose body is a list, where each element is an integer constant or a string
109// literal.
110#define PARSE_CONSTANT_OR_STRING_LITERAL_LIST(aname) \
111 {aname, &P4::ParseAnnotations::parseConstantOrStringLiteralList}
112
113// Parses an annotation whose body is a list of string literals.
114#define PARSE_STRING_LITERAL_LIST(aname) {aname, &P4::ParseAnnotations::parseStringLiteralList}
115
116// Parses a P4Runtime translation which contains both types or expressions.
117#define PARSE_P4RUNTIME_TRANSLATION(aname) \
118 {aname, &P4::ParseAnnotations::parseP4rtTranslationAnnotation}
119
121 public:
122 using Modifier::postorder;
123
126 typedef std::function<bool(IR::Annotation *)> Handler;
127
129 typedef std::unordered_map<cstring, Handler> HandlerMap;
130
132 explicit ParseAnnotations(bool warn = false) : warnUnknown(warn), handlers(standardHandlers()) {
133 setName("ParseAnnotations");
134 }
135
137 ParseAnnotations(const char *targetName, bool includeStandard, HandlerMap handlers,
138 bool warn = false)
139 : warnUnknown(warn) {
140 std::string buf = targetName;
141 buf += "__ParseAnnotations";
142 setName(buf.c_str());
143
144 if (includeStandard) {
145 this->handlers = standardHandlers();
146 this->handlers.insert(handlers.begin(), handlers.end());
147 } else {
148 this->handlers = handlers;
149 }
150 }
151
152 void postorder(IR::Annotation *annotation) final;
153
154 static HandlerMap standardHandlers();
155
156 static bool parseSkip(IR::Annotation *annotation);
157 static bool parseEmpty(IR::Annotation *annotation);
158 static bool parseExpressionList(IR::Annotation *annotation);
159 static bool parseKvList(IR::Annotation *annotation);
160 static bool parseConstantList(IR::Annotation *annotation);
161 static bool parseConstantOrStringLiteralList(IR::Annotation *annotation);
162 static bool parseStringLiteralList(IR::Annotation *annotation);
163 // Parses a `@p4runtime_translation` annotation.
164 static bool parseP4rtTranslationAnnotation(IR::Annotation *annotation);
165
166 void addHandler(cstring name, Handler h) { handlers.insert({name, h}); }
167
168 private:
170 const bool warnUnknown;
171
174 std::set<cstring> warned;
175
176 HandlerMap handlers;
177};
178
180class ParseAnnotationBodies final : public PassManager {
181 public:
182 ParseAnnotationBodies(ParseAnnotations *pa, TypeMap *typeMap) {
183 passes.push_back(pa);
184 passes.push_back(new ClearTypeMap(typeMap));
185 setName("ParseAnnotationBodies");
186 }
187};
188
189} // namespace P4
190
191#endif /* FRONTENDS_P4_PARSEANNOTATIONS_H_ */
Definition typeChecker.h:32
Definition visitor.h:385
Definition parseAnnotations.h:120
ParseAnnotations(bool warn=false)
Produces a pass that rewrites the spec-defined annotations.
Definition parseAnnotations.h:132
std::function< bool(IR::Annotation *)> Handler
Definition parseAnnotations.h:126
std::unordered_map< cstring, Handler > HandlerMap
Keyed on annotation names.
Definition parseAnnotations.h:129
ParseAnnotations(const char *targetName, bool includeStandard, HandlerMap handlers, bool warn=false)
Produces a pass that rewrites a custom set of annotations.
Definition parseAnnotations.h:137
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