P4C
The P4 Compiler
Loading...
Searching...
No Matches
typeChecker.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 TYPECHECKING_TYPECHECKER_H_
18#define TYPECHECKING_TYPECHECKER_H_
19
20#include "frontends/common/resolveReferences/referenceMap.h"
21#include "frontends/common/resolveReferences/resolveReferences.h"
22#include "frontends/p4/typeMap.h"
23#include "ir/ir.h"
24#include "ir/pass_manager.h"
25#include "ir/visitor.h"
26
27namespace P4 {
28
29// This pass only clears the typeMap if the program has changed
30// or the 'force' flag is set.
31// This is needed if the types of some objects in the program change.
32class ClearTypeMap : public Inspector {
33 TypeMap *typeMap;
34 bool force;
35
36 public:
37 explicit ClearTypeMap(TypeMap *typeMap, bool force = false) : typeMap(typeMap), force(force) {
38 CHECK_NULL(typeMap);
39 }
40 bool preorder(const IR::P4Program *program) override {
41 // Clear map only if program has not changed from last time
42 // otherwise we can reuse it. The 'force' flag is needed
43 // because the program is saved only *after* typechecking,
44 // so if the program changes during type-checking, the
45 // typeMap may not be complete.
46 if (force || !typeMap->checkMap(program)) typeMap->clear();
47 return false; // prune()
48 }
49};
50
55class TypeChecking : public PassManager {
56 public:
57 TypeChecking(/* out */ ReferenceMap *refMap, /* out */ TypeMap *typeMap,
58 bool updateExpressions = false);
59};
60
61template <typename... Args>
62void typeError(const char *format, Args &&...args) {
63 ::P4::error(ErrorType::ERR_TYPE_ERROR, format, std::forward<Args>(args)...);
64}
66bool hasVarbitsOrUnions(const TypeMap *typeMap, const IR::Type *type);
67
68class ReadOnlyTypeInference;
69
70// Actual type checking algorithm.
71// In general this pass should not be called directly; call TypeChecking instead.
72// It is a transform because it may convert implicit casts into explicit casts.
73// But in general it operates like an Inspector; in fact, if it is instantiated
74// with readOnly = true, it will assert that the program is not changed.
75// It is expected that once a program has been type-checked and all casts have
76// been inserted it will not need to change ever again during type-checking.
77// In fact, several passes do modify the program such that types are invalidated.
78// For example, enum elimination converts enum values into integers. After such
79// changes the typemap has to be cleared and types must be recomputed from scratch.
80class TypeInferenceBase : public virtual Visitor, public ResolutionContext {
81 // Output: type map
82 TypeMap *typeMap;
83 const IR::Node *initialNode;
84 std::shared_ptr<MinimalNameGenerator> nameGen;
85
86 public:
87 // Node itself + flag whether we'd prune()
88 using PreorderResult = std::pair<const IR::Node *, bool>;
89
90 // @param readOnly If true it will assert that it behaves like
91 // an Inspector.
92 explicit TypeInferenceBase(TypeMap *typeMap, bool readOnly = false, bool checkArrays = true,
93 bool errorOnNullDecls = false);
94
95 protected:
96 TypeInferenceBase(TypeMap *typeMap, std::shared_ptr<MinimalNameGenerator> nameGen);
97
98 // If true we expect to leave the program unchanged
99 bool readOnly = false;
100 bool checkArrays = true;
101 bool errorOnNullDecls = false;
102 const IR::Node *getInitialNode() const { return initialNode; }
103 const IR::Type *getType(const IR::Node *element) const;
104 const IR::Type *getTypeType(const IR::Node *element) const;
105 void setType(const IR::Node *element, const IR::Type *type);
106 void setLeftValue(const IR::Expression *expression) { typeMap->setLeftValue(expression); }
107 bool isLeftValue(const IR::Expression *expression) const {
108 return typeMap->isLeftValue(expression) || expression->is<IR::DefaultExpression>();
109 }
110 void setCompileTimeConstant(const IR::Expression *expression) {
111 typeMap->setCompileTimeConstant(expression);
112 }
113 bool isCompileTimeConstant(const IR::Expression *expression) const {
114 return typeMap->isCompileTimeConstant(expression);
115 }
116
117 // This is needed because sometimes we invoke visitors recursively on subtrees explicitly.
118 // (visitDagOnce cannot take care of this).
119 bool done() const;
120
121 TypeVariableSubstitution *unifyBase(bool allowCasts, const IR::Node *errorPosition,
122 const IR::Type *destType, const IR::Type *srcType,
123 std::string_view errorFormat,
124 std::initializer_list<const IR::Node *> errorArgs);
125
129 TypeVariableSubstitution *unifyCast(const IR::Node *errorPosition, const IR::Type *destType,
130 const IR::Type *srcType, std::string_view errorFormat = {},
131 std::initializer_list<const IR::Node *> errorArgs = {}) {
132 return unifyBase(true, errorPosition, destType, srcType, errorFormat, errorArgs);
133 }
135 TypeVariableSubstitution *unify(const IR::Node *errorPosition, const IR::Type *destType,
136 const IR::Type *srcType, std::string_view errorFormat = {},
137 std::initializer_list<const IR::Node *> errorArgs = {}) {
138 return unifyBase(false, errorPosition, destType, srcType, errorFormat, errorArgs);
139 }
140
145 const IR::Expression *assignment(const IR::Node *errorPosition, const IR::Type *destType,
146 const IR::Expression *sourceExpression);
147 const IR::SelectCase *matchCase(const IR::SelectExpression *select,
148 const IR::Type_BaseList *selectType,
149 const IR::SelectCase *selectCase, const IR::Type *caseType);
150 bool canCastBetween(const IR::Type *dest, const IR::Type *src) const;
151 bool checkAbstractMethods(const IR::Declaration_Instance *inst, const IR::Type_Extern *type);
152 void addSubstitutions(const TypeVariableSubstitution *tvs);
153
154 const IR::Expression *constantFold(const IR::Expression *expression);
155
159 virtual const IR::Type *canonicalize(const IR::Type *type);
160 template <class Ctor>
161 const IR::Type *canonicalizeFields(const IR::Type_StructLike *type, Ctor constructor);
162 virtual const IR::ParameterList *canonicalizeParameters(const IR::ParameterList *params);
163
164 // various helpers
165 bool onlyBitsOrBitStructs(const IR::Type *type) const;
166 bool containsHeader(const IR::Type *canonType);
167 bool validateFields(const IR::Type *type, std::function<bool(const IR::Type *)> checker) const;
168 const IR::Node *binaryBool(const IR::Operation_Binary *op);
169 const IR::Node *binaryArith(const IR::Operation_Binary *op);
170 const IR::Node *unsBinaryArith(const IR::Operation_Binary *op);
171 const IR::Node *shift(const IR::Operation_Binary *op);
172 const IR::Node *typeSet(const IR::Operation_Binary *op);
173
174 const IR::Type *cloneWithFreshTypeVariables(const IR::IMayBeGenericType *type);
175 std::pair<const IR::Type *, const IR::Vector<IR::Argument> *> containerInstantiation(
176 const IR::Node *node, const IR::Vector<IR::Argument> *args,
177 const IR::IContainer *container);
178 const IR::Expression *actionCall(
179 bool inActionList, // if true this "call" is in the action list of a table
180 const IR::MethodCallExpression *actionCall);
181 std::pair<const IR::Type *, const IR::Vector<IR::Argument> *> checkExternConstructor(
182 const IR::Node *errorPosition, const IR::Type_Extern *ext,
183 const IR::Vector<IR::Argument> *arguments);
184
185 static constexpr bool forbidModules = true;
186 static constexpr bool forbidPackages = true;
187 bool checkParameters(const IR::ParameterList *paramList, bool forbidModules = false,
188 bool forbidPackage = false) const;
189 virtual const IR::Type *setTypeType(const IR::Type *type, bool learn = true);
190
192 const IR::ActionList *currentActionList;
196 const IR::ActionListElement *validateActionInitializer(const IR::Expression *actionCall);
197 bool containsActionEnum(const IR::Type *type) const;
198
201 const IR::Type_Bits *checkUnderlyingEnumType(const IR::Type *enumType);
202
204 // Template, so we can have common code for both IR::Function* and const IR::Function*
205 template <class Node>
206 PreorderResult preorderFunctionImpl(Node *function);
207 template <class Node>
208 PreorderResult preorderDeclarationInstanceImpl(Node *decl);
209
210 public:
211 static const IR::Type *specialize(const IR::IMayBeGenericType *type,
212 const IR::Vector<IR::Type> *arguments,
213 const Visitor::Context *ctxt);
214
215 struct Comparison {
216 const IR::Expression *left;
217 const IR::Expression *right;
218 };
219
220 // Helper function to handle comparisons
221 bool compare(const IR::Node *errorPosition, const IR::Type *ltype, const IR::Type *rtype,
222 Comparison *compare);
223
224 // do functions pre-order so we can check the prototype
225 // before the returns
226 PreorderResult preorder(IR::Function *function);
227 PreorderResult preorder(const IR::Function *function);
228 PreorderResult preorder(const IR::P4Program *program);
229 PreorderResult preorder(IR::Declaration_Instance *decl);
230 PreorderResult preorder(const IR::Declaration_Instance *decl);
231 // check invariants for entire list before checking the entries
232 PreorderResult preorder(const IR::EntriesList *el);
233 PreorderResult preorder(const IR::Type_SerEnum *type);
234
235 const IR::Node *postorder(const IR::Declaration_MatchKind *decl);
236 const IR::Node *postorder(const IR::Declaration_Variable *decl);
237 const IR::Node *postorder(const IR::Declaration_Constant *constant);
238 const IR::Node *postorder(const IR::P4Control *cont);
239 const IR::Node *postorder(const IR::P4Parser *cont);
240 const IR::Node *postorder(const IR::Method *method);
241
242 const IR::Node *postorder(const IR::Type_Type *type);
243 const IR::Node *postorder(const IR::Type_Table *type);
244 const IR::Node *postorder(const IR::Type_Error *decl);
245 const IR::Node *postorder(const IR::Type_InfInt *type);
246 const IR::Node *postorder(const IR::Type_Method *type);
247 const IR::Node *postorder(const IR::Type_Action *type);
248 const IR::Node *postorder(const IR::Type_Name *type);
249 const IR::Node *postorder(const IR::Type_Base *type);
250 const IR::Node *postorder(const IR::Type_Var *type);
251 const IR::Node *postorder(const IR::Type_Enum *type);
252 const IR::Node *postorder(const IR::Type_Extern *type);
253 const IR::Node *postorder(const IR::StructField *field);
254 const IR::Node *postorder(const IR::Type_Header *type);
255 const IR::Node *postorder(const IR::Type_Stack *type);
256 const IR::Node *postorder(const IR::Type_Struct *type);
257 const IR::Node *postorder(const IR::Type_HeaderUnion *type);
258 const IR::Node *postorder(const IR::Type_Typedef *type);
259 const IR::Node *postorder(const IR::Type_Specialized *type);
260 const IR::Node *postorder(const IR::Type_SpecializedCanonical *type);
261 const IR::Node *postorder(const IR::Type_Tuple *type);
262 const IR::Node *postorder(const IR::Type_P4List *type);
263 const IR::Node *postorder(const IR::Type_List *type);
264 const IR::Node *postorder(const IR::Type_Set *type);
265 const IR::Node *postorder(const IR::Type_ArchBlock *type);
266 const IR::Node *postorder(const IR::Type_Newtype *type);
267 const IR::Node *postorder(const IR::Type_Package *type);
268 const IR::Node *postorder(const IR::Type_ActionEnum *type);
269 const IR::Node *postorder(const IR::P4Table *type);
270 const IR::Node *postorder(const IR::P4Action *type);
271 const IR::Node *postorder(const IR::P4ValueSet *type);
272 const IR::Node *postorder(const IR::Key *key);
273 const IR::Node *postorder(const IR::Entry *e);
274
275 const IR::Node *postorder(const IR::Dots *expression);
276 const IR::Node *postorder(const IR::Argument *arg);
277 const IR::Node *postorder(const IR::SerEnumMember *member);
278 const IR::Node *postorder(const IR::Parameter *param);
279 const IR::Node *postorder(const IR::Constant *expression);
280 const IR::Node *postorder(const IR::BoolLiteral *expression);
281 const IR::Node *postorder(const IR::StringLiteral *expression);
282 const IR::Node *postorder(const IR::Operation_Relation *expression);
283 const IR::Node *postorder(const IR::Concat *expression);
284 const IR::Node *postorder(const IR::ArrayIndex *expression);
285 const IR::Node *postorder(const IR::LAnd *expression) { return binaryBool(expression); }
286 const IR::Node *postorder(const IR::LOr *expression) { return binaryBool(expression); }
287 const IR::Node *postorder(const IR::Add *expression) { return binaryArith(expression); }
288 const IR::Node *postorder(const IR::Sub *expression) { return binaryArith(expression); }
289 const IR::Node *postorder(const IR::AddSat *expression) { return binaryArith(expression); }
290 const IR::Node *postorder(const IR::SubSat *expression) { return binaryArith(expression); }
291 const IR::Node *postorder(const IR::Mul *expression) { return binaryArith(expression); }
292 const IR::Node *postorder(const IR::Div *expression) { return unsBinaryArith(expression); }
293 const IR::Node *postorder(const IR::Mod *expression) { return unsBinaryArith(expression); }
294 const IR::Node *postorder(const IR::Shl *expression) { return shift(expression); }
295 const IR::Node *postorder(const IR::Shr *expression) { return shift(expression); }
296 const IR::Node *postorder(const IR::BXor *expression) { return binaryArith(expression); }
297 const IR::Node *postorder(const IR::BAnd *expression) { return binaryArith(expression); }
298 const IR::Node *postorder(const IR::BOr *expression) { return binaryArith(expression); }
299 const IR::Node *postorder(const IR::Mask *expression) { return typeSet(expression); }
300 const IR::Node *postorder(const IR::Range *expression) { return typeSet(expression); }
301 const IR::Node *postorder(const IR::LNot *expression);
302 const IR::Node *postorder(const IR::Neg *expression);
303 const IR::Node *postorder(const IR::UPlus *expression);
304 const IR::Node *postorder(const IR::Cmpl *expression);
305 const IR::Node *postorder(const IR::Cast *expression);
306 const IR::Node *postorder(const IR::Mux *expression);
307 const IR::Node *postorder(const IR::Slice *expression);
308 const IR::Node *postorder(const IR::PlusSlice *expression);
309 const IR::Node *postorder(const IR::PathExpression *expression);
310 const IR::Node *postorder(const IR::Member *expression);
311 const IR::Node *postorder(const IR::TypeNameExpression *expression);
312 const IR::Node *postorder(const IR::ListExpression *expression);
313 const IR::Node *postorder(const IR::InvalidHeader *expression);
314 const IR::Node *postorder(const IR::InvalidHeaderUnion *expression);
315 const IR::Node *postorder(const IR::Invalid *expression);
316 const IR::Node *postorder(const IR::P4ListExpression *expression);
317 const IR::Node *postorder(const IR::StructExpression *expression);
318 const IR::Node *postorder(const IR::HeaderStackExpression *expression);
319 const IR::Node *postorder(const IR::MethodCallStatement *mcs);
320 const IR::Node *postorder(const IR::MethodCallExpression *expression);
321 const IR::Node *postorder(const IR::ConstructorCallExpression *expression);
322 const IR::Node *postorder(const IR::SelectExpression *expression);
323 const IR::Node *postorder(const IR::DefaultExpression *expression);
324 const IR::Node *postorder(const IR::This *expression);
325 const IR::Node *postorder(const IR::AttribLocal *local);
326 const IR::Node *postorder(const IR::ActionList *al);
327
328 const IR::Node *postorder(const IR::ReturnStatement *stat);
329 const IR::Node *postorder(const IR::IfStatement *stat);
330 const IR::Node *postorder(const IR::SwitchStatement *stat);
331 const IR::Node *postorder(const IR::AssignmentStatement *stat);
332 const IR::Node *postorder(const IR::ForInStatement *stat);
333 const IR::Node *postorder(const IR::ActionListElement *elem);
334 const IR::Node *postorder(const IR::KeyElement *elem);
335 const IR::Node *postorder(const IR::Property *elem);
336 const IR::Node *postorder(const IR::SelectCase *elem);
337 const IR::Node *postorder(const IR::Annotation *annotation);
338
339 void start(const IR::Node *node);
340 void finish(const IR::Node *Node);
341
342 ReadOnlyTypeInference *readOnlyClone() const;
343 // Apply recursively the typechecker to the newly created node
344 // to add all component subtypes in the typemap.
345 // Return 'true' if errors were discovered in the learning process.
346 bool learn(const IR::Node *node, Visitor *caller, const Visitor::Context *ctxt);
347};
348
349class ReadOnlyTypeInference : public virtual Inspector, public TypeInferenceBase {
350 friend class TypeInferenceBase;
351
352 ReadOnlyTypeInference(TypeMap *typeMap, std::shared_ptr<MinimalNameGenerator> nameGen)
353 : TypeInferenceBase(typeMap, std::move(nameGen)) {}
354
355 public:
356 using Inspector::postorder;
357 using Inspector::preorder;
358
359 explicit ReadOnlyTypeInference(TypeMap *typeMap, bool checkArrays = true,
360 bool errorOnNullDecls = false)
361 : TypeInferenceBase(typeMap, true, checkArrays, errorOnNullDecls) {}
362
363 Visitor::profile_t init_apply(const IR::Node *node) override;
364 void end_apply(const IR::Node *Node) override;
365
366 bool preorder(const IR::Expression *) override { return !done(); }
367 bool preorder(const IR::Type *) override { return !done(); }
368
369 // do functions pre-order so we can check the prototype
370 // before the returns
371 bool preorder(const IR::Function *function) override;
372 bool preorder(const IR::P4Program *program) override;
373 bool preorder(const IR::Declaration_Instance *decl) override;
374 // check invariants for entire list before checking the entries
375 bool preorder(const IR::EntriesList *el) override;
376 bool preorder(const IR::Type_SerEnum *type) override;
377
378 void postorder(const IR::Declaration_MatchKind *decl) override;
379 void postorder(const IR::Declaration_Variable *decl) override;
380 void postorder(const IR::Declaration_Constant *constant) override;
381 void postorder(const IR::P4Control *cont) override;
382 void postorder(const IR::P4Parser *cont) override;
383 void postorder(const IR::Method *method) override;
384
385 void postorder(const IR::Type_Type *type) override;
386 void postorder(const IR::Type_Table *type) override;
387 void postorder(const IR::Type_Error *decl) override;
388 void postorder(const IR::Type_InfInt *type) override;
389 void postorder(const IR::Type_Method *type) override;
390 void postorder(const IR::Type_Action *type) override;
391 void postorder(const IR::Type_Name *type) override;
392 void postorder(const IR::Type_Base *type) override;
393 void postorder(const IR::Type_Var *type) override;
394 void postorder(const IR::Type_Enum *type) override;
395 void postorder(const IR::Type_Extern *type) override;
396 void postorder(const IR::StructField *field) override;
397 void postorder(const IR::Type_Header *type) override;
398 void postorder(const IR::Type_Stack *type) override;
399 void postorder(const IR::Type_Struct *type) override;
400 void postorder(const IR::Type_HeaderUnion *type) override;
401 void postorder(const IR::Type_Typedef *type) override;
402 void postorder(const IR::Type_Specialized *type) override;
403 void postorder(const IR::Type_SpecializedCanonical *type) override;
404 void postorder(const IR::Type_Tuple *type) override;
405 void postorder(const IR::Type_P4List *type) override;
406 void postorder(const IR::Type_List *type) override;
407 void postorder(const IR::Type_Set *type) override;
408 void postorder(const IR::Type_ArchBlock *type) override;
409 void postorder(const IR::Type_Newtype *type) override;
410 void postorder(const IR::Type_Package *type) override;
411 void postorder(const IR::Type_ActionEnum *type) override;
412 void postorder(const IR::P4Table *type) override;
413 void postorder(const IR::P4Action *type) override;
414 void postorder(const IR::P4ValueSet *type) override;
415 void postorder(const IR::Key *key) override;
416 void postorder(const IR::Entry *e) override;
417
418 void postorder(const IR::Dots *expression) override;
419 void postorder(const IR::Argument *arg) override;
420 void postorder(const IR::SerEnumMember *member) override;
421 void postorder(const IR::Parameter *param) override;
422 void postorder(const IR::Constant *expression) override;
423 void postorder(const IR::BoolLiteral *expression) override;
424 void postorder(const IR::StringLiteral *expression) override;
425 void postorder(const IR::Operation_Relation *expression) override;
426 void postorder(const IR::Concat *expression) override;
427 void postorder(const IR::ArrayIndex *expression) override;
428 void postorder(const IR::LAnd *expression) override;
429 void postorder(const IR::LOr *expression) override;
430 void postorder(const IR::Add *expression) override;
431 void postorder(const IR::Sub *expression) override;
432 void postorder(const IR::AddSat *expression) override;
433 void postorder(const IR::SubSat *expression) override;
434 void postorder(const IR::Mul *expression) override;
435 void postorder(const IR::Div *expression) override;
436 void postorder(const IR::Mod *expression) override;
437 void postorder(const IR::Shl *expression) override;
438 void postorder(const IR::Shr *expression) override;
439 void postorder(const IR::BXor *expression) override;
440 void postorder(const IR::BAnd *expression) override;
441 void postorder(const IR::BOr *expression) override;
442 void postorder(const IR::Mask *expression) override;
443 void postorder(const IR::Range *expression) override;
444 void postorder(const IR::LNot *expression) override;
445 void postorder(const IR::Neg *expression) override;
446 void postorder(const IR::UPlus *expression) override;
447 void postorder(const IR::Cmpl *expression) override;
448 void postorder(const IR::Cast *expression) override;
449 void postorder(const IR::Mux *expression) override;
450 void postorder(const IR::Slice *expression) override;
451 void postorder(const IR::PlusSlice *expression) override;
452 void postorder(const IR::PathExpression *expression) override;
453 void postorder(const IR::Member *expression) override;
454 void postorder(const IR::TypeNameExpression *expression) override;
455 void postorder(const IR::ListExpression *expression) override;
456 void postorder(const IR::InvalidHeader *expression) override;
457 void postorder(const IR::InvalidHeaderUnion *expression) override;
458 void postorder(const IR::Invalid *expression) override;
459 void postorder(const IR::P4ListExpression *expression) override;
460 void postorder(const IR::StructExpression *expression) override;
461 void postorder(const IR::HeaderStackExpression *expression) override;
462 void postorder(const IR::MethodCallStatement *mcs) override;
463 void postorder(const IR::MethodCallExpression *expression) override;
464 void postorder(const IR::ConstructorCallExpression *expression) override;
465 void postorder(const IR::SelectExpression *expression) override;
466 void postorder(const IR::DefaultExpression *expression) override;
467 void postorder(const IR::This *expression) override;
468 void postorder(const IR::AttribLocal *local) override;
469 void postorder(const IR::ActionList *al) override;
470
471 void postorder(const IR::ReturnStatement *stat) override;
472 void postorder(const IR::IfStatement *stat) override;
473 void postorder(const IR::SwitchStatement *stat) override;
474 void postorder(const IR::AssignmentStatement *stat) override;
475 void postorder(const IR::ForInStatement *stat) override;
476 void postorder(const IR::ActionListElement *elem) override;
477 void postorder(const IR::KeyElement *elem) override;
478 void postorder(const IR::Property *elem) override;
479 void postorder(const IR::SelectCase *elem) override;
480 void postorder(const IR::Annotation *annotation) override;
481};
482
483class TypeInference : public virtual Transform, public TypeInferenceBase {
484 public:
485 using Transform::postorder;
486 using Transform::preorder;
487
488 explicit TypeInference(TypeMap *typeMap, bool readOnly = true, bool checkArrays = true,
489 bool errorOnNullDecls = false)
490 : TypeInferenceBase(typeMap, readOnly, checkArrays, errorOnNullDecls) {}
491
492 Visitor::profile_t init_apply(const IR::Node *node) override;
493 const IR::Node *apply_visitor(const IR::Node *, const char *name = nullptr) override;
494 void end_apply(const IR::Node *Node) override;
495
496 const IR::Node *pruneIfDone(const IR::Node *node) {
497 if (done()) Transform::prune();
498 return node;
499 }
500 const IR::Node *preorder(IR::Expression *expression) override {
501 return pruneIfDone(expression);
502 }
503 const IR::Node *preorder(IR::Type *type) override { return pruneIfDone(type); }
504
505 // do functions pre-order so we can check the prototype
506 // before the returns
507 const IR::Node *preorder(IR::Function *function) override;
508 const IR::Node *preorder(IR::P4Program *program) override;
509 const IR::Node *preorder(IR::Declaration_Instance *decl) override;
510 // check invariants for entire list before checking the entries
511 const IR::Node *preorder(IR::EntriesList *el) override;
512 const IR::Node *preorder(IR::Type_SerEnum *type) override;
513
514 const IR::Node *postorder(IR::Declaration_MatchKind *decl) override;
515 const IR::Node *postorder(IR::Declaration_Variable *decl) override;
516 const IR::Node *postorder(IR::Declaration_Constant *constant) override;
517 const IR::Node *postorder(IR::P4Control *cont) override;
518 const IR::Node *postorder(IR::P4Parser *cont) override;
519 const IR::Node *postorder(IR::Method *method) override;
520
521 const IR::Node *postorder(IR::Type_Type *type) override;
522 const IR::Node *postorder(IR::Type_Table *type) override;
523 const IR::Node *postorder(IR::Type_Error *decl) override;
524 const IR::Node *postorder(IR::Type_InfInt *type) override;
525 const IR::Node *postorder(IR::Type_Method *type) override;
526 const IR::Node *postorder(IR::Type_Action *type) override;
527 const IR::Node *postorder(IR::Type_Name *type) override;
528 const IR::Node *postorder(IR::Type_Base *type) override;
529 const IR::Node *postorder(IR::Type_Var *type) override;
530 const IR::Node *postorder(IR::Type_Enum *type) override;
531 const IR::Node *postorder(IR::Type_Extern *type) override;
532 const IR::Node *postorder(IR::StructField *field) override;
533 const IR::Node *postorder(IR::Type_Header *type) override;
534 const IR::Node *postorder(IR::Type_Stack *type) override;
535 const IR::Node *postorder(IR::Type_Struct *type) override;
536 const IR::Node *postorder(IR::Type_HeaderUnion *type) override;
537 const IR::Node *postorder(IR::Type_Typedef *type) override;
538 const IR::Node *postorder(IR::Type_Specialized *type) override;
539 const IR::Node *postorder(IR::Type_SpecializedCanonical *type) override;
540 const IR::Node *postorder(IR::Type_Tuple *type) override;
541 const IR::Node *postorder(IR::Type_P4List *type) override;
542 const IR::Node *postorder(IR::Type_List *type) override;
543 const IR::Node *postorder(IR::Type_Set *type) override;
544 const IR::Node *postorder(IR::Type_ArchBlock *type) override;
545 const IR::Node *postorder(IR::Type_Newtype *type) override;
546 const IR::Node *postorder(IR::Type_Package *type) override;
547 const IR::Node *postorder(IR::Type_ActionEnum *type) override;
548 const IR::Node *postorder(IR::P4Table *type) override;
549 const IR::Node *postorder(IR::P4Action *type) override;
550 const IR::Node *postorder(IR::P4ValueSet *type) override;
551 const IR::Node *postorder(IR::Key *key) override;
552 const IR::Node *postorder(IR::Entry *e) override;
553
554 const IR::Node *postorder(IR::Dots *expression) override;
555 const IR::Node *postorder(IR::Argument *arg) override;
556 const IR::Node *postorder(IR::SerEnumMember *member) override;
557 const IR::Node *postorder(IR::Parameter *param) override;
558 const IR::Node *postorder(IR::Constant *expression) override;
559 const IR::Node *postorder(IR::BoolLiteral *expression) override;
560 const IR::Node *postorder(IR::StringLiteral *expression) override;
561 const IR::Node *postorder(IR::Operation_Relation *expression) override;
562 const IR::Node *postorder(IR::Concat *expression) override;
563 const IR::Node *postorder(IR::ArrayIndex *expression) override;
564 const IR::Node *postorder(IR::LAnd *expression) override;
565 const IR::Node *postorder(IR::LOr *expression) override;
566 const IR::Node *postorder(IR::Add *expression) override;
567 const IR::Node *postorder(IR::Sub *expression) override;
568 const IR::Node *postorder(IR::AddSat *expression) override;
569 const IR::Node *postorder(IR::SubSat *expression) override;
570 const IR::Node *postorder(IR::Mul *expression) override;
571 const IR::Node *postorder(IR::Div *expression) override;
572 const IR::Node *postorder(IR::Mod *expression) override;
573 const IR::Node *postorder(IR::Shl *expression) override;
574 const IR::Node *postorder(IR::Shr *expression) override;
575 const IR::Node *postorder(IR::BXor *expression) override;
576 const IR::Node *postorder(IR::BAnd *expression) override;
577 const IR::Node *postorder(IR::BOr *expression) override;
578 const IR::Node *postorder(IR::Mask *expression) override;
579 const IR::Node *postorder(IR::Range *expression) override;
580 const IR::Node *postorder(IR::LNot *expression) override;
581 const IR::Node *postorder(IR::Neg *expression) override;
582 const IR::Node *postorder(IR::UPlus *expression) override;
583 const IR::Node *postorder(IR::Cmpl *expression) override;
584 const IR::Node *postorder(IR::Cast *expression) override;
585 const IR::Node *postorder(IR::Mux *expression) override;
586 const IR::Node *postorder(IR::Slice *expression) override;
587 const IR::Node *postorder(IR::PlusSlice *expression) override;
588 const IR::Node *postorder(IR::PathExpression *expression) override;
589 const IR::Node *postorder(IR::Member *expression) override;
590 const IR::Node *postorder(IR::TypeNameExpression *expression) override;
591 const IR::Node *postorder(IR::ListExpression *expression) override;
592 const IR::Node *postorder(IR::InvalidHeader *expression) override;
593 const IR::Node *postorder(IR::InvalidHeaderUnion *expression) override;
594 const IR::Node *postorder(IR::Invalid *expression) override;
595 const IR::Node *postorder(IR::P4ListExpression *expression) override;
596 const IR::Node *postorder(IR::StructExpression *expression) override;
597 const IR::Node *postorder(IR::HeaderStackExpression *expression) override;
598 const IR::Node *postorder(IR::MethodCallStatement *mcs) override;
599 const IR::Node *postorder(IR::MethodCallExpression *expression) override;
600 const IR::Node *postorder(IR::ConstructorCallExpression *expression) override;
601 const IR::Node *postorder(IR::SelectExpression *expression) override;
602 const IR::Node *postorder(IR::DefaultExpression *expression) override;
603 const IR::Node *postorder(IR::This *expression) override;
604 const IR::Node *postorder(IR::AttribLocal *local) override;
605 const IR::Node *postorder(IR::ActionList *al) override;
606
607 const IR::Node *postorder(IR::ReturnStatement *stat) override;
608 const IR::Node *postorder(IR::IfStatement *stat) override;
609 const IR::Node *postorder(IR::SwitchStatement *stat) override;
610 const IR::Node *postorder(IR::AssignmentStatement *stat) override;
611 const IR::Node *postorder(IR::ForInStatement *stat) override;
612 const IR::Node *postorder(IR::ActionListElement *elem) override;
613 const IR::Node *postorder(IR::KeyElement *elem) override;
614 const IR::Node *postorder(IR::Property *elem) override;
615 const IR::Node *postorder(IR::SelectCase *elem) override;
616 const IR::Node *postorder(IR::Annotation *annotation) override;
617};
618
619// Copy types from the typeMap to expressions. Updates the typeMap with newly created nodes
621 TypeMap *typeMap;
622 IR::Node *postorder(IR::Node *n) override {
623 const IR::Node *orig = getOriginal();
624 if (auto type = typeMap->getType(orig)) {
625 if (*orig != *n) typeMap->setType(n, type);
626 }
627 return n;
628 }
629 IR::Expression *postorder(IR::Expression *e) override {
630 auto orig = getOriginal<IR::Expression>();
631 if (auto type = typeMap->getType(orig)) {
632 e->type = type;
633 if (*orig != *e) {
634 typeMap->setType(e, type);
635 if (typeMap->isLeftValue(orig)) typeMap->setLeftValue(e);
636 if (typeMap->isCompileTimeConstant(orig)) typeMap->setCompileTimeConstant(e);
637 }
638 }
639 return e;
640 }
641
642 public:
643 explicit ApplyTypesToExpressions(TypeMap *typeMap) : typeMap(typeMap) {}
644};
645
646} // namespace P4
647
648#endif /* TYPECHECKING_TYPECHECKER_H_ */
Definition typeChecker.h:620
Definition typeChecker.h:32
Definition node.h:95
Definition vector.h:59
Definition visitor.h:400
Definition ir/pass_manager.h:40
Definition typeChecker.h:349
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
Visitor mixin for looking up names in enclosing scopes from the Visitor::Context.
Definition resolveReferences.h:35
Definition visitor.h:424
Definition typeChecker.h:55
Definition typeChecker.h:80
const IR::ActionListElement * validateActionInitializer(const IR::Expression *actionCall)
Definition typeCheckStmt.cpp:221
const IR::Type_Bits * checkUnderlyingEnumType(const IR::Type *enumType)
Definition typeCheckTypes.cpp:288
virtual const IR::Type * canonicalize(const IR::Type *type)
Definition typeChecker.cpp:232
bool validateFields(const IR::Type *type, std::function< bool(const IR::Type *)> checker) const
Definition typeCheckTypes.cpp:394
TypeVariableSubstitution * unifyCast(const IR::Node *errorPosition, const IR::Type *destType, const IR::Type *srcType, std::string_view errorFormat={}, std::initializer_list< const IR::Node * > errorArgs={})
Definition typeChecker.h:129
TypeVariableSubstitution * unify(const IR::Node *errorPosition, const IR::Type *destType, const IR::Type *srcType, std::string_view errorFormat={}, std::initializer_list< const IR::Node * > errorArgs={})
Same as above, not allowing casts.
Definition typeChecker.h:135
const IR::Expression * assignment(const IR::Node *errorPosition, const IR::Type *destType, const IR::Expression *sourceExpression)
Definition typeChecker.cpp:542
std::pair< const IR::Type *, const IR::Vector< IR::Argument > * > containerInstantiation(const IR::Node *node, const IR::Vector< IR::Argument > *args, const IR::IContainer *container)
Definition typeChecker.cpp:843
static const IR::Type * specialize(const IR::IMayBeGenericType *type, const IR::Vector< IR::Type > *arguments, const Visitor::Context *ctxt)
Definition typeChecker.cpp:214
const IR::ActionList * currentActionList
Action list of the current table.
Definition typeChecker.h:192
Definition typeChecker.h:215
Definition typeChecker.h:483
Definition typeMap.h:41
Definition typeSubstitution.h:73
Definition visitor.h:78
Definition visitor.h:75
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:51
bool hasVarbitsOrUnions(const TypeMap *typeMap, const IR::Type *type)
True if the type contains any varbit or header_union subtypes.
Definition typeCheckTypes.cpp:19
Definition visitor.h:47