P4C
The P4 Compiler
Loading...
Searching...
No Matches
methodInstance.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_METHODINSTANCE_H_
18#define FRONTENDS_P4_METHODINSTANCE_H_
19
20#include "frontends/common/resolveReferences/referenceMap.h"
21#include "frontends/p4/parameterSubstitution.h"
22#include "frontends/p4/typeMap.h"
23#include "ir/ir.h"
24
25namespace P4 {
26
27class InstanceBase : public ICastable {
28 protected:
29 virtual ~InstanceBase() {}
30
31 public:
37
38 DECLARE_TYPEINFO(InstanceBase);
39};
40
57 protected:
58 MethodInstance(const IR::MethodCallExpression *mce, const IR::IDeclaration *decl,
59 const IR::Type_MethodBase *originalMethodType,
60 const IR::Type_MethodBase *actualMethodType)
61 : expr(mce),
62 object(decl),
65 CHECK_NULL(mce);
66 CHECK_NULL(originalMethodType);
67 CHECK_NULL(actualMethodType);
68 }
69
70 void bindParameters() {
71 auto params = getActualParameters();
72 substitution.populate(params, expr->arguments);
73 }
74
75 public:
76 const IR::MethodCallExpression *expr;
82 const IR::Type_MethodBase *originalMethodType;
85 const IR::Type_MethodBase *actualMethodType;
86 virtual bool isApply() const { return false; }
87
94 static MethodInstance *resolve(const IR::MethodCallExpression *mce,
95 const DeclarationLookup *refMap, TypeMap *typeMap,
96 bool useExpressionType = false,
97 const Visitor::Context *ctxt = nullptr, bool incomplete = false);
98 static MethodInstance *resolve(const IR::MethodCallExpression *mce,
99 const DeclarationLookup *refMap, TypeMap *typeMap,
100 const Visitor::Context *ctxt, bool incomplete = false) {
101 return resolve(mce, refMap, typeMap, false, ctxt, incomplete);
102 }
103 static MethodInstance *resolve(const IR::MethodCallStatement *mcs,
104 const DeclarationLookup *refMap, TypeMap *typeMap,
105 const Visitor::Context *ctxt = nullptr) {
106 return resolve(mcs->methodCall, refMap, typeMap, false, ctxt, false);
107 }
108 static MethodInstance *resolve(const IR::MethodCallExpression *mce,
109 const DeclarationLookup *refMap,
110 const Visitor::Context *ctxt = nullptr) {
111 return resolve(mce, refMap, nullptr, true, ctxt, false);
112 }
113 static MethodInstance *resolve(const IR::MethodCallStatement *mcs,
114 const DeclarationLookup *refMap,
115 const Visitor::Context *ctxt = nullptr) {
116 return resolve(mcs->methodCall, refMap, nullptr, true, ctxt, false);
117 }
118
119 const IR::ParameterList *getOriginalParameters() const {
120 return originalMethodType->parameters;
121 }
122 const IR::ParameterList *getActualParameters() const { return actualMethodType->parameters; }
123
124 DECLARE_TYPEINFO(MethodInstance, InstanceBase);
125};
126
129class ApplyMethod final : public MethodInstance {
130 ApplyMethod(const IR::MethodCallExpression *expr, const IR::IDeclaration *decl,
131 const IR::IApply *applyObject)
132 : MethodInstance(expr, decl, applyObject->getApplyMethodType(),
133 applyObject->getApplyMethodType()),
134 applyObject(applyObject) {
135 CHECK_NULL(applyObject);
136 bindParameters();
137 }
138 friend class MethodInstance;
139
140 public:
141 const IR::IApply *applyObject;
142 bool isApply() const override { return true; }
143 bool isTableApply() const { return object->is<IR::P4Table>(); }
144
145 DECLARE_TYPEINFO(ApplyMethod, MethodInstance);
146};
147
150 protected:
151 ExternCall(const IR::MethodCallExpression *expr, const IR::IDeclaration *decl,
152 const IR::Method *method, const IR::Type_Method *originalMethodType,
153 const IR::Type_Method *actualMethodType, bool incomplete)
154 : MethodInstance(expr, decl, originalMethodType, actualMethodType), method(method) {
155 CHECK_NULL(method);
156 bindParameters();
157 if (!incomplete)
158 typeSubstitution.setBindings(expr, method->type->typeParameters, expr->typeArguments);
159 }
160
161 public:
162 const IR::Method *method;
163
164 DECLARE_TYPEINFO(ExternCall, MethodInstance);
165};
166
168class ExternMethod final : public ExternCall {
169 ExternMethod(const IR::MethodCallExpression *expr, const IR::IDeclaration *decl,
170 const IR::Method *method, const IR::Type_Extern *originalExternType,
171 const IR::Type_Method *originalMethodType, const IR::Type_Extern *actualExternType,
172 const IR::Type_Method *actualMethodType, bool incomplete)
173 : ExternCall(expr, decl, method, originalMethodType, actualMethodType, incomplete),
174 originalExternType(originalExternType),
175 actualExternType(actualExternType) {
176 CHECK_NULL(originalExternType);
177 CHECK_NULL(actualExternType);
178 }
179 friend class MethodInstance;
180
181 public:
182 const IR::Type_Extern *originalExternType; // type of object method is applied to
183 const IR::Type_Extern *actualExternType; // with type variables substituted
184
186 // If this method is abstract, will consist of (just) the concrete implementation,
187 // otherwise will consist of those methods that are @synchronous with this
188 std::vector<const IR::IDeclaration *> mayCall() const;
189
190 DECLARE_TYPEINFO(ExternMethod, ExternCall);
191};
192
194class ExternFunction final : public ExternCall {
195 ExternFunction(const IR::MethodCallExpression *expr, const IR::Method *method,
196 const IR::Type_Method *originalMethodType,
197 const IR::Type_Method *actualMethodType, bool incomplete)
198 : ExternCall(expr, nullptr, method, originalMethodType, actualMethodType, incomplete) {}
199 friend class MethodInstance;
200
201 public:
202 DECLARE_TYPEINFO(ExternFunction, ExternCall);
203};
204
209class ActionCall final : public MethodInstance {
210 ActionCall(const IR::MethodCallExpression *expr, const IR::P4Action *action,
211 const IR::Type_Action *actionType)
212 : // Actions are never generic
213 MethodInstance(expr, nullptr, actionType, actionType),
214 action(action) {
215 CHECK_NULL(action);
216 bindParameters();
217 }
218 friend class MethodInstance;
219
220 public:
221 const IR::P4Action *action;
224 const IR::P4Action *specialize(const DeclarationLookup *refMap) const;
225
226 DECLARE_TYPEINFO(ActionCall, MethodInstance);
227};
228
232class FunctionCall final : public MethodInstance {
233 FunctionCall(const IR::MethodCallExpression *expr, const IR::Function *function,
234 const IR::Type_Method *originalMethodType, const IR::Type_Method *actualMethodType,
235 bool incomplete)
236 : MethodInstance(expr, nullptr, originalMethodType, actualMethodType), function(function) {
237 CHECK_NULL(function);
238 bindParameters();
239 if (!incomplete)
240 typeSubstitution.setBindings(function, function->type->typeParameters,
241 expr->typeArguments);
242 }
243 friend class MethodInstance;
244
245 public:
246 const IR::Function *function;
247
248 DECLARE_TYPEINFO(FunctionCall, MethodInstance);
249};
250
260class BuiltInMethod final : public MethodInstance {
261 friend class MethodInstance;
262 BuiltInMethod(const IR::MethodCallExpression *expr, IR::ID name,
263 const IR::Expression *appliedTo, const IR::Type_Method *methodType)
264 : MethodInstance(expr, nullptr, methodType, methodType), name(name), appliedTo(appliedTo) {
265 CHECK_NULL(appliedTo);
266 bindParameters();
267 }
268
269 public:
270 const IR::ID name;
271 const IR::Expression *appliedTo; // object is an expression
272
273 DECLARE_TYPEINFO(BuiltInMethod, MethodInstance);
274};
275
277
285 protected:
286 virtual ~ConstructorCall() {}
287 explicit ConstructorCall(const IR::ConstructorCallExpression *cce) : cce(cce) {
288 CHECK_NULL(cce);
289 }
290
291 public:
292 const IR::ConstructorCallExpression *cce = nullptr;
293 const IR::Vector<IR::Type> *typeArguments = nullptr;
294 const IR::ParameterList *constructorParameters = nullptr;
295 static ConstructorCall *resolve(const IR::ConstructorCallExpression *cce,
296 const DeclarationLookup *refMap, TypeMap *typeMap);
297 DECLARE_TYPEINFO(ConstructorCall, InstanceBase);
298};
299
302 explicit ExternConstructorCall(const IR::ConstructorCallExpression *cce,
303 const IR::Type_Extern *type, const IR::Method *constructor)
304 : ConstructorCall(cce), type(type), constructor(constructor) {
305 CHECK_NULL(type);
306 CHECK_NULL(constructor);
307 }
308 friend class ConstructorCall;
309
310 public:
311 const IR::Type_Extern *type; // actual extern declaration in program IR
312 const IR::Method *constructor; // that is being invoked
313
314 DECLARE_TYPEINFO(ExternConstructorCall, ConstructorCall);
315};
316
320 explicit ContainerConstructorCall(const IR::ConstructorCallExpression *cce,
321 const IR::IContainer *cont)
322 : ConstructorCall(cce), container(cont) {
323 CHECK_NULL(cont);
324 }
325 friend class ConstructorCall;
326
327 public:
328 const IR::IContainer *container; // actual container in program IR
329
330 DECLARE_TYPEINFO(ContainerConstructorCall, ConstructorCall);
331};
332
334
337 protected:
338 void substitute() {
339 substitution.populate(constructorParameters, constructorArguments);
340 typeSubstitution.setBindings(instance, typeParameters, typeArguments);
341 }
342
343 public:
344 Instantiation(const IR::Declaration_Instance *instance,
345 const IR::Vector<IR::Type> *typeArguments)
346 : instance(instance), typeArguments(typeArguments) {
347 CHECK_NULL(instance);
348 constructorArguments = instance->arguments;
349 }
350
351 const IR::Declaration_Instance *instance;
352 const IR::Vector<IR::Type> *typeArguments;
353 const IR::Vector<IR::Argument> *constructorArguments;
354 const IR::ParameterList *constructorParameters = nullptr;
355 const IR::TypeParameters *typeParameters = nullptr;
356
357 static Instantiation *resolve(const IR::Declaration_Instance *instance,
358 DeclarationLookup *refMap, TypeMap *typeMap);
359
360 DECLARE_TYPEINFO(Instantiation, InstanceBase);
361};
362
364 public:
365 ExternInstantiation(const IR::Declaration_Instance *instance,
366 const IR::Vector<IR::Type> *typeArguments, const IR::Type_Extern *type)
367 : Instantiation(instance, typeArguments), type(type) {
368 auto constructor = type->lookupConstructor(constructorArguments);
369 BUG_CHECK(constructor, "%1%: could not find constructor", type);
370 constructorParameters = constructor->type->parameters;
371 typeParameters = type->typeParameters;
372 substitute();
373 }
374 const IR::Type_Extern *type;
375
376 DECLARE_TYPEINFO(ExternInstantiation, Instantiation);
377};
378
380 public:
381 PackageInstantiation(const IR::Declaration_Instance *instance,
382 const IR::Vector<IR::Type> *typeArguments, const IR::Type_Package *package)
383 : Instantiation(instance, typeArguments), package(package) {
384 constructorParameters = package->getConstructorParameters();
385 typeParameters = package->typeParameters;
386 substitute();
387 }
388 const IR::Type_Package *package;
389
390 DECLARE_TYPEINFO(PackageInstantiation, Instantiation);
391};
392
394 public:
395 ParserInstantiation(const IR::Declaration_Instance *instance,
396 const IR::Vector<IR::Type> *typeArguments, const IR::P4Parser *parser)
397 : Instantiation(instance, typeArguments), parser(parser) {
398 typeParameters = parser->type->typeParameters;
399 constructorParameters = parser->getConstructorParameters();
400 substitute();
401 }
402 const IR::P4Parser *parser;
403
404 DECLARE_TYPEINFO(ParserInstantiation, Instantiation);
405};
406
408 public:
409 ControlInstantiation(const IR::Declaration_Instance *instance,
410 const IR::Vector<IR::Type> *typeArguments, const IR::P4Control *control)
411 : Instantiation(instance, typeArguments), control(control) {
412 typeParameters = control->type->typeParameters;
413 constructorParameters = control->getConstructorParameters();
414 substitute();
415 }
416 const IR::P4Control *control;
417
418 DECLARE_TYPEINFO(ControlInstantiation, Instantiation);
419};
420
421} // namespace P4
422
423#endif /* FRONTENDS_P4_METHODINSTANCE_H_ */
Definition methodInstance.h:209
const IR::P4Action * specialize(const DeclarationLookup *refMap) const
Definition methodInstance.cpp:126
Definition methodInstance.h:129
Definition methodInstance.h:260
Definition methodInstance.h:284
Definition methodInstance.h:319
Definition methodInstance.h:407
Definition referenceMap.h:57
Definition methodInstance.h:149
Definition methodInstance.h:301
Definition methodInstance.h:194
Definition methodInstance.h:363
Definition methodInstance.h:168
std::vector< const IR::IDeclaration * > mayCall() const
Set of IR::Method and IR::Function objects that may be called by this method.
Definition methodInstance.cpp:198
Definition methodInstance.h:232
Definition castable.h:36
The Declaration interface, representing objects with names.
Definition declaration.h:26
Definition vector.h:58
Definition methodInstance.h:27
TypeVariableSubstitution typeSubstitution
Definition methodInstance.h:36
ParameterSubstitution substitution
For each callee parameter the corresponding argument.
Definition methodInstance.h:33
Used to resolve a Declaration_Instance.
Definition methodInstance.h:336
Definition methodInstance.h:56
const IR::Type_MethodBase * actualMethodType
Definition methodInstance.h:85
const IR::Type_MethodBase * originalMethodType
Definition methodInstance.h:82
static MethodInstance * resolve(const IR::MethodCallExpression *mce, const DeclarationLookup *refMap, TypeMap *typeMap, bool useExpressionType=false, const Visitor::Context *ctxt=nullptr, bool incomplete=false)
Definition methodInstance.cpp:27
const IR::IDeclaration * object
Definition methodInstance.h:79
Definition methodInstance.h:379
Definition parameterSubstitution.h:30
void populate(const IR::ParameterList *params, const IR::Vector< IR::Argument > *args)
Definition parameterSubstitution.cpp:34
Definition methodInstance.h:393
Definition typeMap.h:41
Definition typeSubstitution.h:73
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition id.h:28
bool is() const noexcept
Definition rtti.h:216
Definition visitor.h:47