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 FRONTENDS_P4_TYPECHECKING_TYPECHECKER_H_
18#define FRONTENDS_P4_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 }
134
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
208 const IR::Expression *convertUntypedInvalid(const IR::Expression *expr,
209 const IR::Type *destType);
210
212 // Template, so we can have common code for both IR::Function* and const IR::Function*
213 template <class Node>
214 PreorderResult preorderFunctionImpl(Node *function);
215 template <class Node>
216 PreorderResult preorderDeclarationInstanceImpl(Node *decl);
217
218 public:
219 static const IR::Type *specialize(const IR::IMayBeGenericType *type,
220 const IR::Vector<IR::Type> *arguments,
221 const Visitor::Context *ctxt);
222
223 struct Comparison {
224 const IR::Expression *left;
225 const IR::Expression *right;
226 };
227
228 // Helper function to handle comparisons
229 bool compare(const IR::Node *errorPosition, const IR::Type *ltype, const IR::Type *rtype,
230 Comparison *compare);
231
232 // do functions pre-order so we can check the prototype
233 // before the returns
234 PreorderResult preorder(IR::Function *function);
235 PreorderResult preorder(const IR::Function *function);
236 PreorderResult preorder(const IR::P4Program *program);
237 PreorderResult preorder(IR::Declaration_Instance *decl);
238 PreorderResult preorder(const IR::Declaration_Instance *decl);
239 // check invariants for entire list before checking the entries
240 PreorderResult preorder(const IR::EntriesList *el);
241 PreorderResult preorder(const IR::Type_SerEnum *type);
242
243 const IR::Node *postorder(const IR::Declaration_MatchKind *decl);
244 const IR::Node *postorder(const IR::Declaration_Variable *decl);
245 const IR::Node *postorder(const IR::Declaration_Constant *constant);
246 const IR::Node *postorder(const IR::P4Control *cont);
247 const IR::Node *postorder(const IR::P4Parser *cont);
248 const IR::Node *postorder(const IR::Method *method);
249
250 const IR::Node *postorder(const IR::Type_Type *type);
251 const IR::Node *postorder(const IR::Type_Table *type);
252 const IR::Node *postorder(const IR::Type_Error *decl);
253 const IR::Node *postorder(const IR::Type_InfInt *type);
254 const IR::Node *postorder(const IR::Type_Method *type);
255 const IR::Node *postorder(const IR::Type_Action *type);
256 const IR::Node *postorder(const IR::Type_Name *type);
257 const IR::Node *postorder(const IR::Type_Base *type);
258 const IR::Node *postorder(const IR::Type_Var *type);
259 const IR::Node *postorder(const IR::Type_Enum *type);
260 const IR::Node *postorder(const IR::Type_Extern *type);
261 const IR::Node *postorder(const IR::StructField *field);
262 const IR::Node *postorder(const IR::Type_Header *type);
263 const IR::Node *postorder(const IR::Type_Array *type);
264 const IR::Node *postorder(const IR::Type_Struct *type);
265 const IR::Node *postorder(const IR::Type_HeaderUnion *type);
266 const IR::Node *postorder(const IR::Type_Typedef *type);
267 const IR::Node *postorder(const IR::Type_Specialized *type);
268 const IR::Node *postorder(const IR::Type_SpecializedCanonical *type);
269 const IR::Node *postorder(const IR::Type_Tuple *type);
270 const IR::Node *postorder(const IR::Type_P4List *type);
271 const IR::Node *postorder(const IR::Type_List *type);
272 const IR::Node *postorder(const IR::Type_Set *type);
273 const IR::Node *postorder(const IR::Type_ArchBlock *type);
274 const IR::Node *postorder(const IR::Type_Newtype *type);
275 const IR::Node *postorder(const IR::Type_Package *type);
276 const IR::Node *postorder(const IR::Type_ActionEnum *type);
277 const IR::Node *postorder(const IR::P4Table *type);
278 const IR::Node *postorder(const IR::P4Action *type);
279 const IR::Node *postorder(const IR::P4ValueSet *type);
280 const IR::Node *postorder(const IR::Key *key);
281 const IR::Node *postorder(const IR::Entry *e);
282
283 const IR::Node *postorder(const IR::Dots *expression);
284 const IR::Node *postorder(const IR::Argument *arg);
285 const IR::Node *postorder(const IR::SerEnumMember *member);
286 const IR::Node *postorder(const IR::Parameter *param);
287 const IR::Node *postorder(const IR::Constant *expression);
288 const IR::Node *postorder(const IR::BoolLiteral *expression);
289 const IR::Node *postorder(const IR::StringLiteral *expression);
290 const IR::Node *postorder(const IR::Operation_Relation *expression);
291 const IR::Node *postorder(const IR::Concat *expression);
292 const IR::Node *postorder(const IR::ArrayIndex *expression);
293 const IR::Node *postorder(const IR::LAnd *expression) { return binaryBool(expression); }
294 const IR::Node *postorder(const IR::LOr *expression) { return binaryBool(expression); }
295 const IR::Node *postorder(const IR::Add *expression) { return binaryArith(expression); }
296 const IR::Node *postorder(const IR::Sub *expression) { return binaryArith(expression); }
297 const IR::Node *postorder(const IR::AddSat *expression) { return binaryArith(expression); }
298 const IR::Node *postorder(const IR::SubSat *expression) { return binaryArith(expression); }
299 const IR::Node *postorder(const IR::Mul *expression) { return binaryArith(expression); }
300 const IR::Node *postorder(const IR::Div *expression) { return unsBinaryArith(expression); }
301 const IR::Node *postorder(const IR::Mod *expression) { return unsBinaryArith(expression); }
302 const IR::Node *postorder(const IR::Shl *expression) { return shift(expression); }
303 const IR::Node *postorder(const IR::Shr *expression) { return shift(expression); }
304 const IR::Node *postorder(const IR::BXor *expression) { return binaryArith(expression); }
305 const IR::Node *postorder(const IR::BAnd *expression) { return binaryArith(expression); }
306 const IR::Node *postorder(const IR::BOr *expression) { return binaryArith(expression); }
307 const IR::Node *postorder(const IR::Mask *expression) { return typeSet(expression); }
308 const IR::Node *postorder(const IR::Range *expression) { return typeSet(expression); }
309 const IR::Node *postorder(const IR::LNot *expression);
310 const IR::Node *postorder(const IR::Neg *expression);
311 const IR::Node *postorder(const IR::UPlus *expression);
312 const IR::Node *postorder(const IR::Cmpl *expression);
313 const IR::Node *postorder(const IR::Cast *expression);
314 const IR::Node *postorder(const IR::Mux *expression);
315 const IR::Node *postorder(const IR::Slice *expression);
316 const IR::Node *postorder(const IR::PlusSlice *expression);
317 const IR::Node *postorder(const IR::PathExpression *expression);
318 const IR::Node *postorder(const IR::Member *expression);
319 const IR::Node *postorder(const IR::TypeNameExpression *expression);
320 const IR::Node *postorder(const IR::ListExpression *expression);
321 const IR::Node *postorder(const IR::InvalidHeader *expression);
322 const IR::Node *postorder(const IR::InvalidHeaderUnion *expression);
323 const IR::Node *postorder(const IR::Invalid *expression);
324 const IR::Node *postorder(const IR::P4ListExpression *expression);
325 const IR::Node *postorder(const IR::StructExpression *expression);
326 const IR::Node *postorder(const IR::ArrayExpression *expression);
327 const IR::Node *postorder(const IR::MethodCallStatement *mcs);
328 const IR::Node *postorder(const IR::MethodCallExpression *expression);
329 const IR::Node *postorder(const IR::ConstructorCallExpression *expression);
330 const IR::Node *postorder(const IR::SelectExpression *expression);
331 const IR::Node *postorder(const IR::DefaultExpression *expression);
332 const IR::Node *postorder(const IR::This *expression);
333 const IR::Node *postorder(const IR::AttribLocal *local);
334 const IR::Node *postorder(const IR::ActionList *al);
335
336 const IR::Node *postorder(const IR::ReturnStatement *stat);
337 const IR::Node *postorder(const IR::ForStatement *stat);
338 const IR::Node *postorder(const IR::IfStatement *stat);
339 const IR::Node *postorder(const IR::SwitchStatement *stat);
340 const IR::Node *common_assign(const IR::BaseAssignmentStatement *stat, const IR::Type *);
341 const IR::Node *postorder(const IR::AssignmentStatement *stat);
342 const IR::Node *postorder(const IR::OpAssignmentStatement *stat);
343 const IR::Node *shiftAssign(const IR::OpAssignmentStatement *stat);
344 const IR::Node *postorder(const IR::ShlAssign *stat) { return shiftAssign(stat); }
345 const IR::Node *postorder(const IR::ShrAssign *stat) { return shiftAssign(stat); }
346 const IR::Node *postorder(const IR::ForInStatement *stat);
347 const IR::Node *postorder(const IR::ActionListElement *elem);
348 const IR::Node *postorder(const IR::KeyElement *elem);
349 const IR::Node *postorder(const IR::Property *elem);
350 const IR::Node *postorder(const IR::SelectCase *elem);
351 const IR::Node *postorder(const IR::Annotation *annotation);
352
353 void start(const IR::Node *node);
354 void finish(const IR::Node *Node);
355
356 ReadOnlyTypeInference *readOnlyClone() const;
357 // Apply recursively the typechecker to the newly created node
358 // to add all component subtypes in the typemap.
359 // Return 'true' if errors were discovered in the learning process.
360 bool learn(const IR::Node *node, Visitor *caller, const Visitor::Context *ctxt);
361};
362
363class ReadOnlyTypeInference : public virtual Inspector, public TypeInferenceBase {
364 friend class TypeInferenceBase;
365
366 ReadOnlyTypeInference(TypeMap *typeMap, std::shared_ptr<MinimalNameGenerator> nameGen)
367 : TypeInferenceBase(typeMap, std::move(nameGen)) {}
368
369 public:
370 using Inspector::postorder;
371 using Inspector::preorder;
372
373 explicit ReadOnlyTypeInference(TypeMap *typeMap, bool checkArrays = true,
374 bool errorOnNullDecls = false)
375 : TypeInferenceBase(typeMap, true, checkArrays, errorOnNullDecls) {}
376
377 Visitor::profile_t init_apply(const IR::Node *node) override;
378 void end_apply(const IR::Node *Node) override;
379
380 bool preorder(const IR::Expression *) override { return !done(); }
381 bool preorder(const IR::Type *) override { return !done(); }
382
383 // do functions pre-order so we can check the prototype
384 // before the returns
385 bool preorder(const IR::Function *function) override;
386 bool preorder(const IR::P4Program *program) override;
387 bool preorder(const IR::Declaration_Instance *decl) override;
388 // check invariants for entire list before checking the entries
389 bool preorder(const IR::EntriesList *el) override;
390 bool preorder(const IR::Type_SerEnum *type) override;
391
392 void postorder(const IR::Declaration_MatchKind *decl) override;
393 void postorder(const IR::Declaration_Variable *decl) override;
394 void postorder(const IR::Declaration_Constant *constant) override;
395 void postorder(const IR::P4Control *cont) override;
396 void postorder(const IR::P4Parser *cont) override;
397 void postorder(const IR::Method *method) override;
398
399 void postorder(const IR::Type_Type *type) override;
400 void postorder(const IR::Type_Table *type) override;
401 void postorder(const IR::Type_Error *decl) override;
402 void postorder(const IR::Type_InfInt *type) override;
403 void postorder(const IR::Type_Method *type) override;
404 void postorder(const IR::Type_Action *type) override;
405 void postorder(const IR::Type_Name *type) override;
406 void postorder(const IR::Type_Base *type) override;
407 void postorder(const IR::Type_Var *type) override;
408 void postorder(const IR::Type_Enum *type) override;
409 void postorder(const IR::Type_Extern *type) override;
410 void postorder(const IR::StructField *field) override;
411 void postorder(const IR::Type_Header *type) override;
412 void postorder(const IR::Type_Array *type) override;
413 void postorder(const IR::Type_Struct *type) override;
414 void postorder(const IR::Type_HeaderUnion *type) override;
415 void postorder(const IR::Type_Typedef *type) override;
416 void postorder(const IR::Type_Specialized *type) override;
417 void postorder(const IR::Type_SpecializedCanonical *type) override;
418 void postorder(const IR::Type_Tuple *type) override;
419 void postorder(const IR::Type_P4List *type) override;
420 void postorder(const IR::Type_List *type) override;
421 void postorder(const IR::Type_Set *type) override;
422 void postorder(const IR::Type_ArchBlock *type) override;
423 void postorder(const IR::Type_Newtype *type) override;
424 void postorder(const IR::Type_Package *type) override;
425 void postorder(const IR::Type_ActionEnum *type) override;
426 void postorder(const IR::P4Table *type) override;
427 void postorder(const IR::P4Action *type) override;
428 void postorder(const IR::P4ValueSet *type) override;
429 void postorder(const IR::Key *key) override;
430 void postorder(const IR::Entry *e) override;
431
432 void postorder(const IR::Dots *expression) override;
433 void postorder(const IR::Argument *arg) override;
434 void postorder(const IR::SerEnumMember *member) override;
435 void postorder(const IR::Parameter *param) override;
436 void postorder(const IR::Constant *expression) override;
437 void postorder(const IR::BoolLiteral *expression) override;
438 void postorder(const IR::StringLiteral *expression) override;
439 void postorder(const IR::Operation_Relation *expression) override;
440 void postorder(const IR::Concat *expression) override;
441 void postorder(const IR::ArrayIndex *expression) override;
442 void postorder(const IR::LAnd *expression) override;
443 void postorder(const IR::LOr *expression) override;
444 void postorder(const IR::Add *expression) override;
445 void postorder(const IR::Sub *expression) override;
446 void postorder(const IR::AddSat *expression) override;
447 void postorder(const IR::SubSat *expression) override;
448 void postorder(const IR::Mul *expression) override;
449 void postorder(const IR::Div *expression) override;
450 void postorder(const IR::Mod *expression) override;
451 void postorder(const IR::Shl *expression) override;
452 void postorder(const IR::Shr *expression) override;
453 void postorder(const IR::BXor *expression) override;
454 void postorder(const IR::BAnd *expression) override;
455 void postorder(const IR::BOr *expression) override;
456 void postorder(const IR::Mask *expression) override;
457 void postorder(const IR::Range *expression) override;
458 void postorder(const IR::LNot *expression) override;
459 void postorder(const IR::Neg *expression) override;
460 void postorder(const IR::UPlus *expression) override;
461 void postorder(const IR::Cmpl *expression) override;
462 void postorder(const IR::Cast *expression) override;
463 void postorder(const IR::Mux *expression) override;
464 void postorder(const IR::Slice *expression) override;
465 void postorder(const IR::PlusSlice *expression) override;
466 void postorder(const IR::PathExpression *expression) override;
467 void postorder(const IR::Member *expression) override;
468 void postorder(const IR::TypeNameExpression *expression) override;
469 void postorder(const IR::ListExpression *expression) override;
470 void postorder(const IR::InvalidHeader *expression) override;
471 void postorder(const IR::InvalidHeaderUnion *expression) override;
472 void postorder(const IR::Invalid *expression) override;
473 void postorder(const IR::P4ListExpression *expression) override;
474 void postorder(const IR::StructExpression *expression) override;
475 void postorder(const IR::ArrayExpression *expression) override;
476 void postorder(const IR::MethodCallStatement *mcs) override;
477 void postorder(const IR::MethodCallExpression *expression) override;
478 void postorder(const IR::ConstructorCallExpression *expression) override;
479 void postorder(const IR::SelectExpression *expression) override;
480 void postorder(const IR::DefaultExpression *expression) override;
481 void postorder(const IR::This *expression) override;
482 void postorder(const IR::AttribLocal *local) override;
483 void postorder(const IR::ActionList *al) override;
484
485 void postorder(const IR::ReturnStatement *stat) override;
486 void postorder(const IR::ForStatement *stat) override;
487 void postorder(const IR::IfStatement *stat) override;
488 void postorder(const IR::SwitchStatement *stat) override;
489 void postorder(const IR::AssignmentStatement *stat) override;
490 void postorder(const IR::OpAssignmentStatement *stat) override;
491 void postorder(const IR::ShlAssign *stat) override;
492 void postorder(const IR::ShrAssign *stat) override;
493 void postorder(const IR::ForInStatement *stat) override;
494 void postorder(const IR::ActionListElement *elem) override;
495 void postorder(const IR::KeyElement *elem) override;
496 void postorder(const IR::Property *elem) override;
497 void postorder(const IR::SelectCase *elem) override;
498 void postorder(const IR::Annotation *annotation) override;
499};
500
501class TypeInference : public virtual Transform, public TypeInferenceBase {
502 public:
503 using Transform::postorder;
504 using Transform::preorder;
505
506 explicit TypeInference(TypeMap *typeMap, bool readOnly = true, bool checkArrays = true,
507 bool errorOnNullDecls = false)
508 : TypeInferenceBase(typeMap, readOnly, checkArrays, errorOnNullDecls) {}
509
510 Visitor::profile_t init_apply(const IR::Node *node) override;
511 const IR::Node *apply_visitor(const IR::Node *, const char *name = nullptr) override;
512 void end_apply(const IR::Node *Node) override;
513
514 const IR::Node *pruneIfDone(const IR::Node *node) {
515 if (done()) Transform::prune();
516 return node;
517 }
518 const IR::Node *preorder(IR::Expression *expression) override {
519 return pruneIfDone(expression);
520 }
521 const IR::Node *preorder(IR::Type *type) override { return pruneIfDone(type); }
522
523 // do functions pre-order so we can check the prototype
524 // before the returns
525 const IR::Node *preorder(IR::Function *function) override;
526 const IR::Node *preorder(IR::P4Program *program) override;
527 const IR::Node *preorder(IR::Declaration_Instance *decl) override;
528 // check invariants for entire list before checking the entries
529 const IR::Node *preorder(IR::EntriesList *el) override;
530 const IR::Node *preorder(IR::Type_SerEnum *type) override;
531
532 const IR::Node *postorder(IR::Declaration_MatchKind *decl) override;
533 const IR::Node *postorder(IR::Declaration_Variable *decl) override;
534 const IR::Node *postorder(IR::Declaration_Constant *constant) override;
535 const IR::Node *postorder(IR::P4Control *cont) override;
536 const IR::Node *postorder(IR::P4Parser *cont) override;
537 const IR::Node *postorder(IR::Method *method) override;
538
539 const IR::Node *postorder(IR::Type_Type *type) override;
540 const IR::Node *postorder(IR::Type_Table *type) override;
541 const IR::Node *postorder(IR::Type_Error *decl) override;
542 const IR::Node *postorder(IR::Type_InfInt *type) override;
543 const IR::Node *postorder(IR::Type_Method *type) override;
544 const IR::Node *postorder(IR::Type_Action *type) override;
545 const IR::Node *postorder(IR::Type_Name *type) override;
546 const IR::Node *postorder(IR::Type_Base *type) override;
547 const IR::Node *postorder(IR::Type_Var *type) override;
548 const IR::Node *postorder(IR::Type_Enum *type) override;
549 const IR::Node *postorder(IR::Type_Extern *type) override;
550 const IR::Node *postorder(IR::StructField *field) override;
551 const IR::Node *postorder(IR::Type_Header *type) override;
552 const IR::Node *postorder(IR::Type_Array *type) override;
553 const IR::Node *postorder(IR::Type_Struct *type) override;
554 const IR::Node *postorder(IR::Type_HeaderUnion *type) override;
555 const IR::Node *postorder(IR::Type_Typedef *type) override;
556 const IR::Node *postorder(IR::Type_Specialized *type) override;
557 const IR::Node *postorder(IR::Type_SpecializedCanonical *type) override;
558 const IR::Node *postorder(IR::Type_Tuple *type) override;
559 const IR::Node *postorder(IR::Type_P4List *type) override;
560 const IR::Node *postorder(IR::Type_List *type) override;
561 const IR::Node *postorder(IR::Type_Set *type) override;
562 const IR::Node *postorder(IR::Type_ArchBlock *type) override;
563 const IR::Node *postorder(IR::Type_Newtype *type) override;
564 const IR::Node *postorder(IR::Type_Package *type) override;
565 const IR::Node *postorder(IR::Type_ActionEnum *type) override;
566 const IR::Node *postorder(IR::P4Table *type) override;
567 const IR::Node *postorder(IR::P4Action *type) override;
568 const IR::Node *postorder(IR::P4ValueSet *type) override;
569 const IR::Node *postorder(IR::Key *key) override;
570 const IR::Node *postorder(IR::Entry *e) override;
571
572 const IR::Node *postorder(IR::Dots *expression) override;
573 const IR::Node *postorder(IR::Argument *arg) override;
574 const IR::Node *postorder(IR::SerEnumMember *member) override;
575 const IR::Node *postorder(IR::Parameter *param) override;
576 const IR::Node *postorder(IR::Constant *expression) override;
577 const IR::Node *postorder(IR::BoolLiteral *expression) override;
578 const IR::Node *postorder(IR::StringLiteral *expression) override;
579 const IR::Node *postorder(IR::Operation_Relation *expression) override;
580 const IR::Node *postorder(IR::Concat *expression) override;
581 const IR::Node *postorder(IR::ArrayIndex *expression) override;
582 const IR::Node *postorder(IR::LAnd *expression) override;
583 const IR::Node *postorder(IR::LOr *expression) override;
584 const IR::Node *postorder(IR::Add *expression) override;
585 const IR::Node *postorder(IR::Sub *expression) override;
586 const IR::Node *postorder(IR::AddSat *expression) override;
587 const IR::Node *postorder(IR::SubSat *expression) override;
588 const IR::Node *postorder(IR::Mul *expression) override;
589 const IR::Node *postorder(IR::Div *expression) override;
590 const IR::Node *postorder(IR::Mod *expression) override;
591 const IR::Node *postorder(IR::Shl *expression) override;
592 const IR::Node *postorder(IR::Shr *expression) override;
593 const IR::Node *postorder(IR::BXor *expression) override;
594 const IR::Node *postorder(IR::BAnd *expression) override;
595 const IR::Node *postorder(IR::BOr *expression) override;
596 const IR::Node *postorder(IR::Mask *expression) override;
597 const IR::Node *postorder(IR::Range *expression) override;
598 const IR::Node *postorder(IR::LNot *expression) override;
599 const IR::Node *postorder(IR::Neg *expression) override;
600 const IR::Node *postorder(IR::UPlus *expression) override;
601 const IR::Node *postorder(IR::Cmpl *expression) override;
602 const IR::Node *postorder(IR::Cast *expression) override;
603 const IR::Node *postorder(IR::Mux *expression) override;
604 const IR::Node *postorder(IR::Slice *expression) override;
605 const IR::Node *postorder(IR::PlusSlice *expression) override;
606 const IR::Node *postorder(IR::PathExpression *expression) override;
607 const IR::Node *postorder(IR::Member *expression) override;
608 const IR::Node *postorder(IR::TypeNameExpression *expression) override;
609 const IR::Node *postorder(IR::ListExpression *expression) override;
610 const IR::Node *postorder(IR::InvalidHeader *expression) override;
611 const IR::Node *postorder(IR::InvalidHeaderUnion *expression) override;
612 const IR::Node *postorder(IR::Invalid *expression) override;
613 const IR::Node *postorder(IR::P4ListExpression *expression) override;
614 const IR::Node *postorder(IR::StructExpression *expression) override;
615 const IR::Node *postorder(IR::ArrayExpression *expression) override;
616 const IR::Node *postorder(IR::MethodCallStatement *mcs) override;
617 const IR::Node *postorder(IR::MethodCallExpression *expression) override;
618 const IR::Node *postorder(IR::ConstructorCallExpression *expression) override;
619 const IR::Node *postorder(IR::SelectExpression *expression) override;
620 const IR::Node *postorder(IR::DefaultExpression *expression) override;
621 const IR::Node *postorder(IR::This *expression) override;
622 const IR::Node *postorder(IR::AttribLocal *local) override;
623 const IR::Node *postorder(IR::ActionList *al) override;
624
625 const IR::Node *postorder(IR::ReturnStatement *stat) override;
626 const IR::Node *postorder(IR::ForStatement *stat) override;
627 const IR::Node *postorder(IR::IfStatement *stat) override;
628 const IR::Node *postorder(IR::SwitchStatement *stat) override;
629 const IR::Node *postorder(IR::AssignmentStatement *stat) override;
630 const IR::Node *postorder(IR::OpAssignmentStatement *stat) override;
631 const IR::Node *postorder(IR::ShlAssign *stat) override;
632 const IR::Node *postorder(IR::ShrAssign *stat) override;
633 const IR::Node *postorder(IR::ForInStatement *stat) override;
634 const IR::Node *postorder(IR::ActionListElement *elem) override;
635 const IR::Node *postorder(IR::KeyElement *elem) override;
636 const IR::Node *postorder(IR::Property *elem) override;
637 const IR::Node *postorder(IR::SelectCase *elem) override;
638 const IR::Node *postorder(IR::Annotation *annotation) override;
639};
640
641// Copy types from the typeMap to expressions. Updates the typeMap with newly created nodes
642class ApplyTypesToExpressions : public Transform {
643 TypeMap *typeMap;
644 IR::Node *postorder(IR::Node *n) override {
645 const IR::Node *orig = getOriginal();
646 if (auto type = typeMap->getType(orig)) {
647 if (*orig != *n) typeMap->setType(n, type);
648 }
649 return n;
650 }
651 IR::Expression *postorder(IR::Expression *e) override {
652 auto orig = getOriginal<IR::Expression>();
653 if (auto type = typeMap->getType(orig)) {
654 e->type = type;
655 if (*orig != *e) {
656 typeMap->setType(e, type);
657 if (typeMap->isLeftValue(orig)) typeMap->setLeftValue(e);
658 if (typeMap->isCompileTimeConstant(orig)) typeMap->setCompileTimeConstant(e);
659 }
660 }
661 return e;
662 }
663
664 public:
665 explicit ApplyTypesToExpressions(TypeMap *typeMap) : typeMap(typeMap) {}
666};
667
668} // namespace P4
669
670#endif /* FRONTENDS_P4_TYPECHECKING_TYPECHECKER_H_ */
Definition node.h:53
Definition ir/vector.h:59
Definition visitor.h:418
Class used to encode maps from paths to declarations.
Definition referenceMap.h:67
Definition visitor.h:442
const IR::ActionListElement * validateActionInitializer(const IR::Expression *actionCall)
Definition typeCheckStmt.cpp:258
const IR::Type_Bits * checkUnderlyingEnumType(const IR::Type *enumType)
Definition typeCheckTypes.cpp:292
const IR::Expression * convertUntypedInvalid(const IR::Expression *expr, const IR::Type *destType)
Definition typeChecker.cpp:546
virtual const IR::Type * canonicalize(const IR::Type *type)
Definition typeChecker.cpp:234
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: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:580
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:895
static const IR::Type * specialize(const IR::IMayBeGenericType *type, const IR::Vector< IR::Type > *arguments, const Visitor::Context *ctxt)
Definition typeChecker.cpp:216
const IR::ActionList * currentActionList
Action list of the current table.
Definition typeChecker.h:192
Definition typeChecker.h:223
Definition typeMap.h:32
Definition typeSubstitution.h:64
Definition visitor.h:78
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:58
bool hasVarbitsOrUnions(const TypeMap *typeMap, const IR::Type *type)
True if the type contains any varbit or header_union subtypes.
Definition typeCheckTypes.cpp:19