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
56class MethodInstance : public InstanceBase {
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
149class ExternMethod final : public MethodInstance {
150 ExternMethod(const IR::MethodCallExpression *expr, const IR::IDeclaration *decl,
151 const IR::Method *method, const IR::Type_Extern *originalExternType,
152 const IR::Type_Method *originalMethodType, const IR::Type_Extern *actualExternType,
153 const IR::Type_Method *actualMethodType, bool incomplete)
154 : MethodInstance(expr, decl, originalMethodType, actualMethodType),
155 method(method),
156 originalExternType(originalExternType),
157 actualExternType(actualExternType) {
158 CHECK_NULL(method);
159 CHECK_NULL(originalExternType);
160 CHECK_NULL(actualExternType);
161 bindParameters();
162 if (!incomplete)
163 typeSubstitution.setBindings(expr, method->type->typeParameters, expr->typeArguments);
164 }
165 friend class MethodInstance;
166
167 public:
168 const IR::Method *method;
169 const IR::Type_Extern *originalExternType; // type of object method is applied to
170 const IR::Type_Extern *actualExternType; // with type variables substituted
171
173 // If this method is abstract, will consist of (just) the concrete implementation,
174 // otherwise will consist of those methods that are @synchronous with this
175 std::vector<const IR::IDeclaration *> mayCall() const;
176
177 DECLARE_TYPEINFO(ExternMethod, MethodInstance);
178};
179
181class ExternFunction final : public MethodInstance {
182 ExternFunction(const IR::MethodCallExpression *expr, const IR::Method *method,
183 const IR::Type_Method *originalMethodType,
184 const IR::Type_Method *actualMethodType, bool incomplete)
185 : MethodInstance(expr, nullptr, originalMethodType, actualMethodType), method(method) {
186 CHECK_NULL(method);
187 bindParameters();
188 if (!incomplete)
189 typeSubstitution.setBindings(expr, method->type->typeParameters, expr->typeArguments);
190 }
191 friend class MethodInstance;
192
193 public:
194 const IR::Method *method;
195
196 DECLARE_TYPEINFO(ExternFunction, MethodInstance);
197};
198
203class ActionCall final : public MethodInstance {
204 ActionCall(const IR::MethodCallExpression *expr, const IR::P4Action *action,
205 const IR::Type_Action *actionType)
206 : // Actions are never generic
207 MethodInstance(expr, nullptr, actionType, actionType),
208 action(action) {
209 CHECK_NULL(action);
210 bindParameters();
211 }
212 friend class MethodInstance;
213
214 public:
215 const IR::P4Action *action;
218 const IR::P4Action *specialize(const DeclarationLookup *refMap) const;
219
220 DECLARE_TYPEINFO(ActionCall, MethodInstance);
221};
222
226class FunctionCall final : public MethodInstance {
227 FunctionCall(const IR::MethodCallExpression *expr, const IR::Function *function,
228 const IR::Type_Method *originalMethodType, const IR::Type_Method *actualMethodType,
229 bool incomplete)
230 : MethodInstance(expr, nullptr, originalMethodType, actualMethodType), function(function) {
231 CHECK_NULL(function);
232 bindParameters();
233 if (!incomplete)
234 typeSubstitution.setBindings(function, function->type->typeParameters,
235 expr->typeArguments);
236 }
237 friend class MethodInstance;
238
239 public:
240 const IR::Function *function;
241
242 DECLARE_TYPEINFO(FunctionCall, MethodInstance);
243};
244
254class BuiltInMethod final : public MethodInstance {
255 friend class MethodInstance;
256 BuiltInMethod(const IR::MethodCallExpression *expr, IR::ID name,
257 const IR::Expression *appliedTo, const IR::Type_Method *methodType)
258 : MethodInstance(expr, nullptr, methodType, methodType), name(name), appliedTo(appliedTo) {
259 CHECK_NULL(appliedTo);
260 bindParameters();
261 }
262
263 public:
264 const IR::ID name;
265 const IR::Expression *appliedTo; // object is an expression
266
267 DECLARE_TYPEINFO(BuiltInMethod, MethodInstance);
268};
269
271
278class ConstructorCall : public InstanceBase {
279 protected:
280 virtual ~ConstructorCall() {}
281 explicit ConstructorCall(const IR::ConstructorCallExpression *cce) : cce(cce) {
282 CHECK_NULL(cce);
283 }
284
285 public:
286 const IR::ConstructorCallExpression *cce = nullptr;
287 const IR::Vector<IR::Type> *typeArguments = nullptr;
288 const IR::ParameterList *constructorParameters = nullptr;
289 static ConstructorCall *resolve(const IR::ConstructorCallExpression *cce,
290 const DeclarationLookup *refMap, TypeMap *typeMap);
291 DECLARE_TYPEINFO(ConstructorCall, InstanceBase);
292};
293
295class ExternConstructorCall : public ConstructorCall {
296 explicit ExternConstructorCall(const IR::ConstructorCallExpression *cce,
297 const IR::Type_Extern *type, const IR::Method *constructor)
298 : ConstructorCall(cce), type(type), constructor(constructor) {
299 CHECK_NULL(type);
300 CHECK_NULL(constructor);
301 }
302 friend class ConstructorCall;
303
304 public:
305 const IR::Type_Extern *type; // actual extern declaration in program IR
306 const IR::Method *constructor; // that is being invoked
307
308 DECLARE_TYPEINFO(ExternConstructorCall, ConstructorCall);
309};
310
313class ContainerConstructorCall : public ConstructorCall {
314 explicit ContainerConstructorCall(const IR::ConstructorCallExpression *cce,
315 const IR::IContainer *cont)
316 : ConstructorCall(cce), container(cont) {
317 CHECK_NULL(cont);
318 }
319 friend class ConstructorCall;
320
321 public:
322 const IR::IContainer *container; // actual container in program IR
323
324 DECLARE_TYPEINFO(ContainerConstructorCall, ConstructorCall);
325};
326
328
330class Instantiation : public InstanceBase {
331 protected:
332 void substitute() {
333 substitution.populate(constructorParameters, constructorArguments);
334 typeSubstitution.setBindings(instance, typeParameters, typeArguments);
335 }
336
337 public:
338 Instantiation(const IR::Declaration_Instance *instance,
339 const IR::Vector<IR::Type> *typeArguments)
340 : instance(instance), typeArguments(typeArguments) {
341 CHECK_NULL(instance);
342 constructorArguments = instance->arguments;
343 }
344
345 const IR::Declaration_Instance *instance;
346 const IR::Vector<IR::Type> *typeArguments;
347 const IR::Vector<IR::Argument> *constructorArguments;
348 const IR::ParameterList *constructorParameters = nullptr;
349 const IR::TypeParameters *typeParameters = nullptr;
350
351 static Instantiation *resolve(const IR::Declaration_Instance *instance,
352 DeclarationLookup *refMap, TypeMap *typeMap);
353
354 DECLARE_TYPEINFO(Instantiation, InstanceBase);
355};
356
357class ExternInstantiation : public Instantiation {
358 public:
359 ExternInstantiation(const IR::Declaration_Instance *instance,
360 const IR::Vector<IR::Type> *typeArguments, const IR::Type_Extern *type)
361 : Instantiation(instance, typeArguments), type(type) {
362 auto constructor = type->lookupConstructor(constructorArguments);
363 BUG_CHECK(constructor, "%1%: could not find constructor", type);
364 constructorParameters = constructor->type->parameters;
365 typeParameters = type->typeParameters;
366 substitute();
367 }
368 const IR::Type_Extern *type;
369
370 DECLARE_TYPEINFO(ExternInstantiation, Instantiation);
371};
372
373class PackageInstantiation : public Instantiation {
374 public:
375 PackageInstantiation(const IR::Declaration_Instance *instance,
376 const IR::Vector<IR::Type> *typeArguments, const IR::Type_Package *package)
377 : Instantiation(instance, typeArguments), package(package) {
378 constructorParameters = package->getConstructorParameters();
379 typeParameters = package->typeParameters;
380 substitute();
381 }
382 const IR::Type_Package *package;
383
384 DECLARE_TYPEINFO(PackageInstantiation, Instantiation);
385};
386
387class ParserInstantiation : public Instantiation {
388 public:
389 ParserInstantiation(const IR::Declaration_Instance *instance,
390 const IR::Vector<IR::Type> *typeArguments, const IR::P4Parser *parser)
391 : Instantiation(instance, typeArguments), parser(parser) {
392 typeParameters = parser->type->typeParameters;
393 constructorParameters = parser->getConstructorParameters();
394 substitute();
395 }
396 const IR::P4Parser *parser;
397
398 DECLARE_TYPEINFO(ParserInstantiation, Instantiation);
399};
400
401class ControlInstantiation : public Instantiation {
402 public:
403 ControlInstantiation(const IR::Declaration_Instance *instance,
404 const IR::Vector<IR::Type> *typeArguments, const IR::P4Control *control)
405 : Instantiation(instance, typeArguments), control(control) {
406 typeParameters = control->type->typeParameters;
407 constructorParameters = control->getConstructorParameters();
408 substitute();
409 }
410 const IR::P4Control *control;
411
412 DECLARE_TYPEINFO(ControlInstantiation, Instantiation);
413};
414
415} // namespace P4
416
417#endif /* FRONTENDS_P4_METHODINSTANCE_H_ */
const IR::P4Action * specialize(const DeclarationLookup *refMap) const
Definition methodInstance.cpp:126
Definition referenceMap.h:57
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 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
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 parameterSubstitution.h:30
Definition typeMap.h:41
Definition typeSubstitution.h:73
Definition typeMap.h:41
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition id.h:28