P4C
The P4 Compiler
Loading...
Searching...
No Matches
methodInstance.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_METHODINSTANCE_H_
9#define FRONTENDS_P4_METHODINSTANCE_H_
10
11#include "frontends/common/resolveReferences/referenceMap.h"
12#include "frontends/p4/parameterSubstitution.h"
13#include "frontends/p4/typeMap.h"
14#include "ir/ir.h"
15
16namespace P4 {
17
18class InstanceBase : public ICastable {
19 protected:
20 virtual ~InstanceBase() {}
21
22 public:
28
29 DECLARE_TYPEINFO(InstanceBase);
30};
31
47class MethodInstance : public InstanceBase {
48 protected:
49 MethodInstance(const IR::MethodCallExpression *mce, const IR::IDeclaration *decl,
50 const IR::Type_MethodBase *originalMethodType,
51 const IR::Type_MethodBase *actualMethodType)
52 : expr(mce),
53 object(decl),
56 CHECK_NULL(mce);
57 CHECK_NULL(originalMethodType);
58 CHECK_NULL(actualMethodType);
59 }
60
61 void bindParameters() {
62 auto params = getActualParameters();
63 substitution.populate(params, expr->arguments);
64 }
65
66 public:
67 const IR::MethodCallExpression *expr;
73 const IR::Type_MethodBase *originalMethodType;
76 const IR::Type_MethodBase *actualMethodType;
77 virtual bool isApply() const { return false; }
78
85 static MethodInstance *resolve(const IR::MethodCallExpression *mce,
86 const DeclarationLookup *refMap, TypeMap *typeMap,
87 bool useExpressionType = false,
88 const Visitor::Context *ctxt = nullptr, bool incomplete = false);
89 static MethodInstance *resolve(const IR::MethodCallExpression *mce,
90 const DeclarationLookup *refMap, TypeMap *typeMap,
91 const Visitor::Context *ctxt, bool incomplete = false) {
92 return resolve(mce, refMap, typeMap, false, ctxt, incomplete);
93 }
94 static MethodInstance *resolve(const IR::MethodCallStatement *mcs,
95 const DeclarationLookup *refMap, TypeMap *typeMap,
96 const Visitor::Context *ctxt = nullptr) {
97 return resolve(mcs->methodCall, refMap, typeMap, false, ctxt, false);
98 }
99 static MethodInstance *resolve(const IR::MethodCallExpression *mce,
100 const DeclarationLookup *refMap,
101 const Visitor::Context *ctxt = nullptr) {
102 return resolve(mce, refMap, nullptr, true, ctxt, false);
103 }
104 static MethodInstance *resolve(const IR::MethodCallStatement *mcs,
105 const DeclarationLookup *refMap,
106 const Visitor::Context *ctxt = nullptr) {
107 return resolve(mcs->methodCall, refMap, nullptr, true, ctxt, false);
108 }
109
110 const IR::ParameterList *getOriginalParameters() const {
111 return originalMethodType->parameters;
112 }
113 const IR::ParameterList *getActualParameters() const { return actualMethodType->parameters; }
114
115 DECLARE_TYPEINFO(MethodInstance, InstanceBase);
116};
117
120class ApplyMethod final : public MethodInstance {
121 ApplyMethod(const IR::MethodCallExpression *expr, const IR::IDeclaration *decl,
122 const IR::IApply *applyObject)
123 : MethodInstance(expr, decl, applyObject->getApplyMethodType(),
124 applyObject->getApplyMethodType()),
125 applyObject(applyObject) {
126 CHECK_NULL(applyObject);
127 bindParameters();
128 }
129 friend class MethodInstance;
130
131 public:
132 const IR::IApply *applyObject;
133 bool isApply() const override { return true; }
134 bool isTableApply() const { return object->is<IR::P4Table>(); }
135
136 DECLARE_TYPEINFO(ApplyMethod, MethodInstance);
137};
138
140class ExternCall : public MethodInstance {
141 protected:
142 ExternCall(const IR::MethodCallExpression *expr, const IR::IDeclaration *decl,
143 const IR::Method *method, const IR::Type_Method *originalMethodType,
144 const IR::Type_Method *actualMethodType, bool incomplete)
145 : MethodInstance(expr, decl, originalMethodType, actualMethodType), method(method) {
146 CHECK_NULL(method);
147 bindParameters();
148 if (!incomplete)
149 typeSubstitution.setBindings(expr, method->type->typeParameters, expr->typeArguments);
150 }
151
152 public:
153 const IR::Method *method;
154
155 DECLARE_TYPEINFO(ExternCall, MethodInstance);
156};
157
159class ExternMethod final : public ExternCall {
160 ExternMethod(const IR::MethodCallExpression *expr, const IR::IDeclaration *decl,
161 const IR::Method *method, const IR::Type_Extern *originalExternType,
162 const IR::Type_Method *originalMethodType, const IR::Type_Extern *actualExternType,
163 const IR::Type_Method *actualMethodType, bool incomplete)
164 : ExternCall(expr, decl, method, originalMethodType, actualMethodType, incomplete),
165 originalExternType(originalExternType),
166 actualExternType(actualExternType) {
167 CHECK_NULL(originalExternType);
168 CHECK_NULL(actualExternType);
169 }
170 friend class MethodInstance;
171
172 public:
173 const IR::Type_Extern *originalExternType; // type of object method is applied to
174 const IR::Type_Extern *actualExternType; // with type variables substituted
175
177 // If this method is abstract, will consist of (just) the concrete implementation,
178 // otherwise will consist of those methods that are @synchronous with this
179 std::vector<const IR::IDeclaration *> mayCall() const;
180
181 DECLARE_TYPEINFO(ExternMethod, ExternCall);
182};
183
185class ExternFunction final : public ExternCall {
186 ExternFunction(const IR::MethodCallExpression *expr, const IR::Method *method,
187 const IR::Type_Method *originalMethodType,
188 const IR::Type_Method *actualMethodType, bool incomplete)
189 : ExternCall(expr, nullptr, method, originalMethodType, actualMethodType, incomplete) {}
190 friend class MethodInstance;
191
192 public:
193 DECLARE_TYPEINFO(ExternFunction, ExternCall);
194};
195
200class ActionCall final : public MethodInstance {
201 ActionCall(const IR::MethodCallExpression *expr, const IR::P4Action *action,
202 const IR::Type_Action *actionType)
203 : // Actions are never generic
204 MethodInstance(expr, nullptr, actionType, actionType),
205 action(action) {
206 CHECK_NULL(action);
207 bindParameters();
208 }
209 friend class MethodInstance;
210
211 public:
212 const IR::P4Action *action;
215 const IR::P4Action *specialize(const DeclarationLookup *refMap) const;
216
217 DECLARE_TYPEINFO(ActionCall, MethodInstance);
218};
219
223class FunctionCall final : public MethodInstance {
224 FunctionCall(const IR::MethodCallExpression *expr, const IR::Function *function,
225 const IR::Type_Method *originalMethodType, const IR::Type_Method *actualMethodType,
226 bool incomplete)
227 : MethodInstance(expr, nullptr, originalMethodType, actualMethodType), function(function) {
228 CHECK_NULL(function);
229 bindParameters();
230 if (!incomplete)
231 typeSubstitution.setBindings(function, function->type->typeParameters,
232 expr->typeArguments);
233 }
234 friend class MethodInstance;
235
236 public:
237 const IR::Function *function;
238
239 DECLARE_TYPEINFO(FunctionCall, MethodInstance);
240};
241
251class BuiltInMethod final : public MethodInstance {
252 friend class MethodInstance;
253 BuiltInMethod(const IR::MethodCallExpression *expr, IR::ID name,
254 const IR::Expression *appliedTo, const IR::Type_Method *methodType)
255 : MethodInstance(expr, nullptr, methodType, methodType), name(name), appliedTo(appliedTo) {
256 CHECK_NULL(appliedTo);
257 bindParameters();
258 }
259
260 public:
261 const IR::ID name;
262 const IR::Expression *appliedTo; // object is an expression
263
264 DECLARE_TYPEINFO(BuiltInMethod, MethodInstance);
265};
266
268
275class ConstructorCall : public InstanceBase {
276 protected:
277 virtual ~ConstructorCall() {}
278 explicit ConstructorCall(const IR::ConstructorCallExpression *cce) : cce(cce) {
279 CHECK_NULL(cce);
280 }
281
282 public:
283 const IR::ConstructorCallExpression *cce = nullptr;
284 const IR::Vector<IR::Type> *typeArguments = nullptr;
285 const IR::ParameterList *constructorParameters = nullptr;
286 static ConstructorCall *resolve(const IR::ConstructorCallExpression *cce,
287 const DeclarationLookup *refMap, TypeMap *typeMap);
288 DECLARE_TYPEINFO(ConstructorCall, InstanceBase);
289};
290
292class ExternConstructorCall : public ConstructorCall {
293 explicit ExternConstructorCall(const IR::ConstructorCallExpression *cce,
294 const IR::Type_Extern *type, const IR::Method *constructor)
295 : ConstructorCall(cce), type(type), constructor(constructor) {
296 CHECK_NULL(type);
297 CHECK_NULL(constructor);
298 }
299 friend class ConstructorCall;
300
301 public:
302 const IR::Type_Extern *type; // actual extern declaration in program IR
303 const IR::Method *constructor; // that is being invoked
304
305 DECLARE_TYPEINFO(ExternConstructorCall, ConstructorCall);
306};
307
310class ContainerConstructorCall : public ConstructorCall {
311 explicit ContainerConstructorCall(const IR::ConstructorCallExpression *cce,
312 const IR::IContainer *cont)
313 : ConstructorCall(cce), container(cont) {
314 CHECK_NULL(cont);
315 }
316 friend class ConstructorCall;
317
318 public:
319 const IR::IContainer *container; // actual container in program IR
320
321 DECLARE_TYPEINFO(ContainerConstructorCall, ConstructorCall);
322};
323
325
327class Instantiation : public InstanceBase {
328 protected:
329 void substitute() {
330 substitution.populate(constructorParameters, constructorArguments);
331 typeSubstitution.setBindings(instance, typeParameters, typeArguments);
332 }
333
334 public:
335 Instantiation(const IR::Declaration_Instance *instance,
336 const IR::Vector<IR::Type> *typeArguments)
337 : instance(instance), typeArguments(typeArguments) {
338 CHECK_NULL(instance);
339 constructorArguments = instance->arguments;
340 }
341
342 const IR::Declaration_Instance *instance;
343 const IR::Vector<IR::Type> *typeArguments;
344 const IR::Vector<IR::Argument> *constructorArguments;
345 const IR::ParameterList *constructorParameters = nullptr;
346 const IR::TypeParameters *typeParameters = nullptr;
347
348 static Instantiation *resolve(const IR::Declaration_Instance *instance,
349 DeclarationLookup *refMap, TypeMap *typeMap);
350
351 DECLARE_TYPEINFO(Instantiation, InstanceBase);
352};
353
354class ExternInstantiation : public Instantiation {
355 public:
356 ExternInstantiation(const IR::Declaration_Instance *instance,
357 const IR::Vector<IR::Type> *typeArguments, const IR::Type_Extern *type)
358 : Instantiation(instance, typeArguments), type(type) {
359 auto constructor = type->lookupConstructor(constructorArguments);
360 BUG_CHECK(constructor, "%1%: could not find constructor", type);
361 constructorParameters = constructor->type->parameters;
362 typeParameters = type->typeParameters;
363 substitute();
364 }
365 const IR::Type_Extern *type;
366
367 DECLARE_TYPEINFO(ExternInstantiation, Instantiation);
368};
369
370class PackageInstantiation : public Instantiation {
371 public:
372 PackageInstantiation(const IR::Declaration_Instance *instance,
373 const IR::Vector<IR::Type> *typeArguments, const IR::Type_Package *package)
374 : Instantiation(instance, typeArguments), package(package) {
375 constructorParameters = package->getConstructorParameters();
376 typeParameters = package->typeParameters;
377 substitute();
378 }
379 const IR::Type_Package *package;
380
381 DECLARE_TYPEINFO(PackageInstantiation, Instantiation);
382};
383
384class ParserInstantiation : public Instantiation {
385 public:
386 ParserInstantiation(const IR::Declaration_Instance *instance,
387 const IR::Vector<IR::Type> *typeArguments, const IR::P4Parser *parser)
388 : Instantiation(instance, typeArguments), parser(parser) {
389 typeParameters = parser->type->typeParameters;
390 constructorParameters = parser->getConstructorParameters();
391 substitute();
392 }
393 const IR::P4Parser *parser;
394
395 DECLARE_TYPEINFO(ParserInstantiation, Instantiation);
396};
397
398class ControlInstantiation : public Instantiation {
399 public:
400 ControlInstantiation(const IR::Declaration_Instance *instance,
401 const IR::Vector<IR::Type> *typeArguments, const IR::P4Control *control)
402 : Instantiation(instance, typeArguments), control(control) {
403 typeParameters = control->type->typeParameters;
404 constructorParameters = control->getConstructorParameters();
405 substitute();
406 }
407 const IR::P4Control *control;
408
409 DECLARE_TYPEINFO(ControlInstantiation, Instantiation);
410};
411
412} // namespace P4
413
414#endif /* FRONTENDS_P4_METHODINSTANCE_H_ */
const IR::P4Action * specialize(const DeclarationLookup *refMap) const
Definition methodInstance.cpp:118
Definition referenceMap.h:48
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:191
Definition castable.h:27
The Declaration interface, representing objects with names.
Definition declaration.h:17
Definition ir/vector.h:50
Definition methodInstance.h:18
TypeVariableSubstitution typeSubstitution
Definition methodInstance.h:27
ParameterSubstitution substitution
For each callee parameter the corresponding argument.
Definition methodInstance.h:24
Definition methodInstance.h:47
const IR::Type_MethodBase * actualMethodType
Definition methodInstance.h:76
const IR::Type_MethodBase * originalMethodType
Definition methodInstance.h:73
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:16
const IR::IDeclaration * object
Definition methodInstance.h:70
Definition parameterSubstitution.h:21
Definition typeMap.h:32
Definition typeSubstitution.h:64
Definition typeMap.h:32
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:13
Definition id.h:19