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