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::PathExpression *expression);
309 const IR::Node *postorder(const IR::Member *expression);
310 const IR::Node *postorder(const IR::TypeNameExpression *expression);
311 const IR::Node *postorder(const IR::ListExpression *expression);
312 const IR::Node *postorder(const IR::InvalidHeader *expression);
313 const IR::Node *postorder(const IR::InvalidHeaderUnion *expression);
314 const IR::Node *postorder(const IR::Invalid *expression);
315 const IR::Node *postorder(const IR::P4ListExpression *expression);
316 const IR::Node *postorder(const IR::StructExpression *expression);
317 const IR::Node *postorder(const IR::HeaderStackExpression *expression);
318 const IR::Node *postorder(const IR::MethodCallStatement *mcs);
319 const IR::Node *postorder(const IR::MethodCallExpression *expression);
320 const IR::Node *postorder(const IR::ConstructorCallExpression *expression);
321 const IR::Node *postorder(const IR::SelectExpression *expression);
322 const IR::Node *postorder(const IR::DefaultExpression *expression);
323 const IR::Node *postorder(const IR::This *expression);
324 const IR::Node *postorder(const IR::AttribLocal *local);
325 const IR::Node *postorder(const IR::ActionList *al);
326
327 const IR::Node *postorder(const IR::ReturnStatement *stat);
328 const IR::Node *postorder(const IR::IfStatement *stat);
329 const IR::Node *postorder(const IR::SwitchStatement *stat);
330 const IR::Node *postorder(const IR::AssignmentStatement *stat);
331 const IR::Node *postorder(const IR::ForInStatement *stat);
332 const IR::Node *postorder(const IR::ActionListElement *elem);
333 const IR::Node *postorder(const IR::KeyElement *elem);
334 const IR::Node *postorder(const IR::Property *elem);
335 const IR::Node *postorder(const IR::SelectCase *elem);
336 const IR::Node *postorder(const IR::Annotation *annotation);
337
338 void start(const IR::Node *node);
339 void finish(const IR::Node *Node);
340
341 ReadOnlyTypeInference *readOnlyClone() const;
342 // Apply recursively the typechecker to the newly created node
343 // to add all component subtypes in the typemap.
344 // Return 'true' if errors were discovered in the learning process.
345 bool learn(const IR::Node *node, Visitor *caller, const Visitor::Context *ctxt);
346};
347
348class ReadOnlyTypeInference : public virtual Inspector, public TypeInferenceBase {
349 friend class TypeInferenceBase;
350
351 ReadOnlyTypeInference(TypeMap *typeMap, std::shared_ptr<MinimalNameGenerator> nameGen)
352 : TypeInferenceBase(typeMap, std::move(nameGen)) {}
353
354 public:
355 using Inspector::postorder;
356 using Inspector::preorder;
357
358 explicit ReadOnlyTypeInference(TypeMap *typeMap, bool checkArrays = true,
359 bool errorOnNullDecls = false)
360 : TypeInferenceBase(typeMap, true, checkArrays, errorOnNullDecls) {}
361
362 Visitor::profile_t init_apply(const IR::Node *node) override;
363 void end_apply(const IR::Node *Node) override;
364
365 bool preorder(const IR::Expression *) override { return !done(); }
366 bool preorder(const IR::Type *) override { return !done(); }
367
368 // do functions pre-order so we can check the prototype
369 // before the returns
370 bool preorder(const IR::Function *function) override;
371 bool preorder(const IR::P4Program *program) override;
372 bool preorder(const IR::Declaration_Instance *decl) override;
373 // check invariants for entire list before checking the entries
374 bool preorder(const IR::EntriesList *el) override;
375 bool preorder(const IR::Type_SerEnum *type) override;
376
377 void postorder(const IR::Declaration_MatchKind *decl) override;
378 void postorder(const IR::Declaration_Variable *decl) override;
379 void postorder(const IR::Declaration_Constant *constant) override;
380 void postorder(const IR::P4Control *cont) override;
381 void postorder(const IR::P4Parser *cont) override;
382 void postorder(const IR::Method *method) override;
383
384 void postorder(const IR::Type_Type *type) override;
385 void postorder(const IR::Type_Table *type) override;
386 void postorder(const IR::Type_Error *decl) override;
387 void postorder(const IR::Type_InfInt *type) override;
388 void postorder(const IR::Type_Method *type) override;
389 void postorder(const IR::Type_Action *type) override;
390 void postorder(const IR::Type_Name *type) override;
391 void postorder(const IR::Type_Base *type) override;
392 void postorder(const IR::Type_Var *type) override;
393 void postorder(const IR::Type_Enum *type) override;
394 void postorder(const IR::Type_Extern *type) override;
395 void postorder(const IR::StructField *field) override;
396 void postorder(const IR::Type_Header *type) override;
397 void postorder(const IR::Type_Stack *type) override;
398 void postorder(const IR::Type_Struct *type) override;
399 void postorder(const IR::Type_HeaderUnion *type) override;
400 void postorder(const IR::Type_Typedef *type) override;
401 void postorder(const IR::Type_Specialized *type) override;
402 void postorder(const IR::Type_SpecializedCanonical *type) override;
403 void postorder(const IR::Type_Tuple *type) override;
404 void postorder(const IR::Type_P4List *type) override;
405 void postorder(const IR::Type_List *type) override;
406 void postorder(const IR::Type_Set *type) override;
407 void postorder(const IR::Type_ArchBlock *type) override;
408 void postorder(const IR::Type_Newtype *type) override;
409 void postorder(const IR::Type_Package *type) override;
410 void postorder(const IR::Type_ActionEnum *type) override;
411 void postorder(const IR::P4Table *type) override;
412 void postorder(const IR::P4Action *type) override;
413 void postorder(const IR::P4ValueSet *type) override;
414 void postorder(const IR::Key *key) override;
415 void postorder(const IR::Entry *e) override;
416
417 void postorder(const IR::Dots *expression) override;
418 void postorder(const IR::Argument *arg) override;
419 void postorder(const IR::SerEnumMember *member) override;
420 void postorder(const IR::Parameter *param) override;
421 void postorder(const IR::Constant *expression) override;
422 void postorder(const IR::BoolLiteral *expression) override;
423 void postorder(const IR::StringLiteral *expression) override;
424 void postorder(const IR::Operation_Relation *expression) override;
425 void postorder(const IR::Concat *expression) override;
426 void postorder(const IR::ArrayIndex *expression) override;
427 void postorder(const IR::LAnd *expression) override;
428 void postorder(const IR::LOr *expression) override;
429 void postorder(const IR::Add *expression) override;
430 void postorder(const IR::Sub *expression) override;
431 void postorder(const IR::AddSat *expression) override;
432 void postorder(const IR::SubSat *expression) override;
433 void postorder(const IR::Mul *expression) override;
434 void postorder(const IR::Div *expression) override;
435 void postorder(const IR::Mod *expression) override;
436 void postorder(const IR::Shl *expression) override;
437 void postorder(const IR::Shr *expression) override;
438 void postorder(const IR::BXor *expression) override;
439 void postorder(const IR::BAnd *expression) override;
440 void postorder(const IR::BOr *expression) override;
441 void postorder(const IR::Mask *expression) override;
442 void postorder(const IR::Range *expression) override;
443 void postorder(const IR::LNot *expression) override;
444 void postorder(const IR::Neg *expression) override;
445 void postorder(const IR::UPlus *expression) override;
446 void postorder(const IR::Cmpl *expression) override;
447 void postorder(const IR::Cast *expression) override;
448 void postorder(const IR::Mux *expression) override;
449 void postorder(const IR::Slice *expression) override;
450 void postorder(const IR::PathExpression *expression) override;
451 void postorder(const IR::Member *expression) override;
452 void postorder(const IR::TypeNameExpression *expression) override;
453 void postorder(const IR::ListExpression *expression) override;
454 void postorder(const IR::InvalidHeader *expression) override;
455 void postorder(const IR::InvalidHeaderUnion *expression) override;
456 void postorder(const IR::Invalid *expression) override;
457 void postorder(const IR::P4ListExpression *expression) override;
458 void postorder(const IR::StructExpression *expression) override;
459 void postorder(const IR::HeaderStackExpression *expression) override;
460 void postorder(const IR::MethodCallStatement *mcs) override;
461 void postorder(const IR::MethodCallExpression *expression) override;
462 void postorder(const IR::ConstructorCallExpression *expression) override;
463 void postorder(const IR::SelectExpression *expression) override;
464 void postorder(const IR::DefaultExpression *expression) override;
465 void postorder(const IR::This *expression) override;
466 void postorder(const IR::AttribLocal *local) override;
467 void postorder(const IR::ActionList *al) override;
468
469 void postorder(const IR::ReturnStatement *stat) override;
470 void postorder(const IR::IfStatement *stat) override;
471 void postorder(const IR::SwitchStatement *stat) override;
472 void postorder(const IR::AssignmentStatement *stat) override;
473 void postorder(const IR::ForInStatement *stat) override;
474 void postorder(const IR::ActionListElement *elem) override;
475 void postorder(const IR::KeyElement *elem) override;
476 void postorder(const IR::Property *elem) override;
477 void postorder(const IR::SelectCase *elem) override;
478 void postorder(const IR::Annotation *annotation) override;
479};
480
481class TypeInference : public virtual Transform, public TypeInferenceBase {
482 public:
483 using Transform::postorder;
484 using Transform::preorder;
485
486 explicit TypeInference(TypeMap *typeMap, bool readOnly = true, bool checkArrays = true,
487 bool errorOnNullDecls = false)
488 : TypeInferenceBase(typeMap, readOnly, checkArrays, errorOnNullDecls) {}
489
490 Visitor::profile_t init_apply(const IR::Node *node) override;
491 const IR::Node *apply_visitor(const IR::Node *, const char *name = nullptr) override;
492 void end_apply(const IR::Node *Node) override;
493
494 const IR::Node *pruneIfDone(const IR::Node *node) {
495 if (done()) Transform::prune();
496 return node;
497 }
498 const IR::Node *preorder(IR::Expression *expression) override {
499 return pruneIfDone(expression);
500 }
501 const IR::Node *preorder(IR::Type *type) override { return pruneIfDone(type); }
502
503 // do functions pre-order so we can check the prototype
504 // before the returns
505 const IR::Node *preorder(IR::Function *function) override;
506 const IR::Node *preorder(IR::P4Program *program) override;
507 const IR::Node *preorder(IR::Declaration_Instance *decl) override;
508 // check invariants for entire list before checking the entries
509 const IR::Node *preorder(IR::EntriesList *el) override;
510 const IR::Node *preorder(IR::Type_SerEnum *type) override;
511
512 const IR::Node *postorder(IR::Declaration_MatchKind *decl) override;
513 const IR::Node *postorder(IR::Declaration_Variable *decl) override;
514 const IR::Node *postorder(IR::Declaration_Constant *constant) override;
515 const IR::Node *postorder(IR::P4Control *cont) override;
516 const IR::Node *postorder(IR::P4Parser *cont) override;
517 const IR::Node *postorder(IR::Method *method) override;
518
519 const IR::Node *postorder(IR::Type_Type *type) override;
520 const IR::Node *postorder(IR::Type_Table *type) override;
521 const IR::Node *postorder(IR::Type_Error *decl) override;
522 const IR::Node *postorder(IR::Type_InfInt *type) override;
523 const IR::Node *postorder(IR::Type_Method *type) override;
524 const IR::Node *postorder(IR::Type_Action *type) override;
525 const IR::Node *postorder(IR::Type_Name *type) override;
526 const IR::Node *postorder(IR::Type_Base *type) override;
527 const IR::Node *postorder(IR::Type_Var *type) override;
528 const IR::Node *postorder(IR::Type_Enum *type) override;
529 const IR::Node *postorder(IR::Type_Extern *type) override;
530 const IR::Node *postorder(IR::StructField *field) override;
531 const IR::Node *postorder(IR::Type_Header *type) override;
532 const IR::Node *postorder(IR::Type_Stack *type) override;
533 const IR::Node *postorder(IR::Type_Struct *type) override;
534 const IR::Node *postorder(IR::Type_HeaderUnion *type) override;
535 const IR::Node *postorder(IR::Type_Typedef *type) override;
536 const IR::Node *postorder(IR::Type_Specialized *type) override;
537 const IR::Node *postorder(IR::Type_SpecializedCanonical *type) override;
538 const IR::Node *postorder(IR::Type_Tuple *type) override;
539 const IR::Node *postorder(IR::Type_P4List *type) override;
540 const IR::Node *postorder(IR::Type_List *type) override;
541 const IR::Node *postorder(IR::Type_Set *type) override;
542 const IR::Node *postorder(IR::Type_ArchBlock *type) override;
543 const IR::Node *postorder(IR::Type_Newtype *type) override;
544 const IR::Node *postorder(IR::Type_Package *type) override;
545 const IR::Node *postorder(IR::Type_ActionEnum *type) override;
546 const IR::Node *postorder(IR::P4Table *type) override;
547 const IR::Node *postorder(IR::P4Action *type) override;
548 const IR::Node *postorder(IR::P4ValueSet *type) override;
549 const IR::Node *postorder(IR::Key *key) override;
550 const IR::Node *postorder(IR::Entry *e) override;
551
552 const IR::Node *postorder(IR::Dots *expression) override;
553 const IR::Node *postorder(IR::Argument *arg) override;
554 const IR::Node *postorder(IR::SerEnumMember *member) override;
555 const IR::Node *postorder(IR::Parameter *param) override;
556 const IR::Node *postorder(IR::Constant *expression) override;
557 const IR::Node *postorder(IR::BoolLiteral *expression) override;
558 const IR::Node *postorder(IR::StringLiteral *expression) override;
559 const IR::Node *postorder(IR::Operation_Relation *expression) override;
560 const IR::Node *postorder(IR::Concat *expression) override;
561 const IR::Node *postorder(IR::ArrayIndex *expression) override;
562 const IR::Node *postorder(IR::LAnd *expression) override;
563 const IR::Node *postorder(IR::LOr *expression) override;
564 const IR::Node *postorder(IR::Add *expression) override;
565 const IR::Node *postorder(IR::Sub *expression) override;
566 const IR::Node *postorder(IR::AddSat *expression) override;
567 const IR::Node *postorder(IR::SubSat *expression) override;
568 const IR::Node *postorder(IR::Mul *expression) override;
569 const IR::Node *postorder(IR::Div *expression) override;
570 const IR::Node *postorder(IR::Mod *expression) override;
571 const IR::Node *postorder(IR::Shl *expression) override;
572 const IR::Node *postorder(IR::Shr *expression) override;
573 const IR::Node *postorder(IR::BXor *expression) override;
574 const IR::Node *postorder(IR::BAnd *expression) override;
575 const IR::Node *postorder(IR::BOr *expression) override;
576 const IR::Node *postorder(IR::Mask *expression) override;
577 const IR::Node *postorder(IR::Range *expression) override;
578 const IR::Node *postorder(IR::LNot *expression) override;
579 const IR::Node *postorder(IR::Neg *expression) override;
580 const IR::Node *postorder(IR::UPlus *expression) override;
581 const IR::Node *postorder(IR::Cmpl *expression) override;
582 const IR::Node *postorder(IR::Cast *expression) override;
583 const IR::Node *postorder(IR::Mux *expression) override;
584 const IR::Node *postorder(IR::Slice *expression) override;
585 const IR::Node *postorder(IR::PathExpression *expression) override;
586 const IR::Node *postorder(IR::Member *expression) override;
587 const IR::Node *postorder(IR::TypeNameExpression *expression) override;
588 const IR::Node *postorder(IR::ListExpression *expression) override;
589 const IR::Node *postorder(IR::InvalidHeader *expression) override;
590 const IR::Node *postorder(IR::InvalidHeaderUnion *expression) override;
591 const IR::Node *postorder(IR::Invalid *expression) override;
592 const IR::Node *postorder(IR::P4ListExpression *expression) override;
593 const IR::Node *postorder(IR::StructExpression *expression) override;
594 const IR::Node *postorder(IR::HeaderStackExpression *expression) override;
595 const IR::Node *postorder(IR::MethodCallStatement *mcs) override;
596 const IR::Node *postorder(IR::MethodCallExpression *expression) override;
597 const IR::Node *postorder(IR::ConstructorCallExpression *expression) override;
598 const IR::Node *postorder(IR::SelectExpression *expression) override;
599 const IR::Node *postorder(IR::DefaultExpression *expression) override;
600 const IR::Node *postorder(IR::This *expression) override;
601 const IR::Node *postorder(IR::AttribLocal *local) override;
602 const IR::Node *postorder(IR::ActionList *al) override;
603
604 const IR::Node *postorder(IR::ReturnStatement *stat) override;
605 const IR::Node *postorder(IR::IfStatement *stat) override;
606 const IR::Node *postorder(IR::SwitchStatement *stat) override;
607 const IR::Node *postorder(IR::AssignmentStatement *stat) override;
608 const IR::Node *postorder(IR::ForInStatement *stat) override;
609 const IR::Node *postorder(IR::ActionListElement *elem) override;
610 const IR::Node *postorder(IR::KeyElement *elem) override;
611 const IR::Node *postorder(IR::Property *elem) override;
612 const IR::Node *postorder(IR::SelectCase *elem) override;
613 const IR::Node *postorder(IR::Annotation *annotation) override;
614};
615
616// Copy types from the typeMap to expressions. Updates the typeMap with newly created nodes
618 TypeMap *typeMap;
619 IR::Node *postorder(IR::Node *n) override {
620 const IR::Node *orig = getOriginal();
621 if (auto type = typeMap->getType(orig)) {
622 if (*orig != *n) typeMap->setType(n, type);
623 }
624 return n;
625 }
626 IR::Expression *postorder(IR::Expression *e) override {
627 auto orig = getOriginal<IR::Expression>();
628 if (auto type = typeMap->getType(orig)) {
629 e->type = type;
630 if (*orig != *e) {
631 typeMap->setType(e, type);
632 if (typeMap->isLeftValue(orig)) typeMap->setLeftValue(e);
633 if (typeMap->isCompileTimeConstant(orig)) typeMap->setCompileTimeConstant(e);
634 }
635 }
636 return e;
637 }
638
639 public:
640 explicit ApplyTypesToExpressions(TypeMap *typeMap) : typeMap(typeMap) {}
641};
642
643} // namespace P4
644
645#endif /* TYPECHECKING_TYPECHECKER_H_ */
Definition typeChecker.h:617
Definition typeChecker.h:32
Definition node.h:95
Definition vector.h:58
Definition visitor.h:400
Definition pass_manager.h:40
Definition typeChecker.h:348
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:33
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:481
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 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