P4C
The P4 Compiler
Loading...
Searching...
No Matches
core/small_step/expr_stepper.h
1/*
2 * SPDX-FileCopyrightText: 2022 The P4 Language Consortium
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#ifndef BACKENDS_P4TOOLS_MODULES_TESTGEN_CORE_SMALL_STEP_EXPR_STEPPER_H_
8#define BACKENDS_P4TOOLS_MODULES_TESTGEN_CORE_SMALL_STEP_EXPR_STEPPER_H_
9
10#include <cstdint>
11#include <utility>
12#include <vector>
13
14#include "ir/ir.h"
15#include "ir/solver.h"
16#include "lib/cstring.h"
17
18#include "backends/p4tools/modules/testgen/core/extern_info.h"
19#include "backends/p4tools/modules/testgen/core/program_info.h"
20#include "backends/p4tools/modules/testgen/core/small_step/abstract_stepper.h"
21#include "backends/p4tools/modules/testgen/lib/execution_state.h"
22
23namespace P4::P4Tools::P4Testgen {
24
26class ExprStepper : public AbstractStepper {
27 /**************************************************************************************************
28 ExternMethodImpls
29 **************************************************************************************************/
30 public:
32 template <typename StepperType>
33 class ExternMethodImpls {
34 public:
40 using MethodImpl = std::function<void(const ExternInfo &externInfo, StepperType &stepper)>;
41
54 std::optional<MethodImpl> find(const IR::PathExpression &externObjectRef,
55 const IR::ID &methodName,
56 const IR::Vector<IR::Argument> &args) const {
57 // We have to check the extern type here. We may receive a specialized canonical type,
58 // which we need to unpack.
59 const IR::Type_Extern *externType = nullptr;
60 if (const auto *type = externObjectRef.type->to<IR::Type_Extern>()) {
61 externType = type;
62 } else if (const auto *specType =
63 externObjectRef.type->to<IR::Type_SpecializedCanonical>()) {
64 CHECK_NULL(specType->substituted);
65 externType = specType->substituted->checkedTo<IR::Type_Extern>();
66 } else if (externObjectRef.path->name == IR::ID("*method")) {
67 } else {
68 BUG("Not a valid extern: %1% with member %2%. Type is %3%.", externObjectRef,
69 methodName, externObjectRef.type->node_type_name());
70 }
71
72 cstring qualifiedMethodName = externType->name + "." + methodName;
73 auto submapIt = impls.find(qualifiedMethodName);
74 if (submapIt == impls.end()) {
75 return std::nullopt;
76 }
77 if (submapIt->second.count(args.size()) == 0) {
78 return std::nullopt;
79 }
80
81 // Find matching methods: if any arguments are named, then the parameter name must
82 // match.
83 std::optional<MethodImpl> matchingImpl;
84 for (const auto &pair : submapIt->second.at(args.size())) {
85 const auto &paramNames = pair.first;
86 const auto &methodImpl = pair.second;
87
88 if (matches(paramNames, args)) {
89 BUG_CHECK(!matchingImpl, "Ambiguous extern method call: %1%",
90 qualifiedMethodName);
91 matchingImpl = methodImpl;
92 }
93 }
94
95 return matchingImpl;
96 }
97
98 private:
103 std::map<cstring,
104 std::map<size_t, std::vector<std::pair<std::vector<cstring>, MethodImpl>>>>
105 impls;
106
110 static bool matches(const std::vector<cstring> &paramNames,
111 const IR::Vector<IR::Argument> &args) {
112 // Number of parameters should match the number of arguments.
113 if (paramNames.size() != args.size()) {
114 return false;
115 }
116 // Any named argument should match the name of the corresponding parameter.
117 for (size_t idx = 0; idx < paramNames.size(); idx++) {
118 const auto &paramName = paramNames.at(idx);
119 const auto &arg = args.at(idx);
120
121 if (arg->name.name == nullptr) {
122 continue;
123 }
124 if (paramName != arg->name.name) {
125 return false;
126 }
127 }
128
129 return true;
130 }
131
132 public:
138 using ImplList = std::list<std::tuple<cstring, std::vector<cstring>, MethodImpl>>;
139
140 explicit ExternMethodImpls(const ImplList &implList) {
141 for (const auto &implSpec : implList) {
142 auto &[name, paramNames, impl] = implSpec;
143
144 auto &tmpImplList = impls[name][paramNames.size()];
145
146 // Make sure that we have at most one implementation for each set of parameter
147 // names. This is a quadratic-time algorithm, but should be fine, since we expect
148 // the number of overloads to be small in practice.
149 for (auto &pair : tmpImplList) {
150 BUG_CHECK(pair.first != paramNames, "Multiple implementations of %1%(%2%)",
151 name, paramNames);
152 }
153
154 tmpImplList.emplace_back(paramNames, impl);
155 }
156 }
157 };
158
161
164
165 /**************************************************************************************************
166 ExprStepper
167 **************************************************************************************************/
168
169 private:
171 friend class TableStepper;
172
174 friend class ExtractUtils;
175
176 protected:
182
184 const IR::Expression *advanceCond;
185
188
190 const IR::Expression *advanceFailCond;
191 };
192
197 int advanceSize) const;
203 const ExecutionState &state, const IR::Expression *advanceExpr,
204 const IR::Expression *restrictions) const;
205
209 static std::vector<std::pair<IR::StateVariable, const IR::Expression *>> setFields(
210 ExecutionState &nextState, const std::vector<IR::StateVariable> &flatFields,
211 int varBitFieldSize);
216 void handleHitMissActionRun(const IR::Member *member);
217
221 bool resolveMethodCallArguments(const IR::MethodCallExpression *call);
222
234 virtual void evalExternMethodCall(const ExternInfo &externInfo);
235
248 void evalInternalExternMethodCall(const ExternInfo &externInfo);
249
257 void evalActionCall(const IR::P4Action *action, const IR::MethodCallExpression *call);
258
263 // Otherwise, the target default value is chosen.
265 void generateCopyIn(ExecutionState &nextState, const IR::StateVariable &targetPath,
266 const IR::StateVariable &srcPath, cstring dir, bool forceTaint) const;
267
271 virtual void stepNoMatch(std::string traceLog, const IR::Expression *condition = nullptr);
272
273 public:
274 ExprStepper(const ExprStepper &) = default;
275
276 ExprStepper(ExprStepper &&) = default;
277
278 ExprStepper &operator=(const ExprStepper &) = delete;
279
280 ExprStepper &operator=(ExprStepper &&) = delete;
281
283
284 bool preorder(const IR::BoolLiteral *boolLiteral) override;
285 bool preorder(const IR::Constant *constant) override;
286 bool preorder(const IR::Member *member) override;
287 bool preorder(const IR::ArrayIndex *arr) override;
288 bool preorder(const IR::MethodCallExpression *call) override;
289 bool preorder(const IR::Mux *mux) override;
290 bool preorder(const IR::PathExpression *pathExpression) override;
291
295 bool preorder(const IR::P4ValueSet *valueSet) override;
296 bool preorder(const IR::Operation_Binary *binary) override;
297 bool preorder(const IR::Operation_Unary *unary) override;
298 bool preorder(const IR::SelectExpression *selectExpression) override;
299 bool preorder(const IR::BaseListExpression *listExpression) override;
300 bool preorder(const IR::StructExpression *structExpression) override;
301 bool preorder(const IR::AbstractSlice *slice) override;
302 bool preorder(const IR::P4Table *table) override;
303};
304
305} // namespace P4::P4Tools::P4Testgen
306
307#endif /* BACKENDS_P4TOOLS_MODULES_TESTGEN_CORE_SMALL_STEP_EXPR_STEPPER_H_ */
Provides a higher-level interface for an SMT solver.
Definition solver.h:30
Definition ir/vector.h:59
ExecutionState & state
The state being evaluated.
Definition abstract_stepper.h:55
const ProgramInfo & programInfo
Target-specific information about the P4 program being evaluated.
Definition abstract_stepper.h:52
Represents state of execution after having reached a program point.
Definition execution_state.h:40
Encapsulates a set of extern method implementations.
Definition core/small_step/expr_stepper.h:33
std::optional< MethodImpl > find(const IR::PathExpression &externObjectRef, const IR::ID &methodName, const IR::Vector< IR::Argument > &args) const
Definition core/small_step/expr_stepper.h:54
std::list< std::tuple< cstring, std::vector< cstring >, MethodImpl > > ImplList
Definition core/small_step/expr_stepper.h:138
std::function< void(const ExternInfo &externInfo, StepperType &stepper)> MethodImpl
Definition core/small_step/expr_stepper.h:40
int advanceFailSize
Specifies at what point the parser cursor advancement will fail.
Definition core/small_step/expr_stepper.h:187
virtual PacketCursorAdvanceInfo calculateSuccessfulParserAdvance(const ExecutionState &state, int advanceSize) const
Definition extern_stepper.cpp:99
void evalInternalExternMethodCall(const ExternInfo &externInfo)
Definition extern_stepper.cpp:331
int advanceSize
How much the parser cursor will be advanced in a successful parsing case.
Definition core/small_step/expr_stepper.h:181
static std::vector< std::pair< IR::StateVariable, const IR::Expression * > > setFields(ExecutionState &nextState, const std::vector< IR::StateVariable > &flatFields, int varBitFieldSize)
Definition extern_stepper.cpp:48
friend class ExtractUtils
Extract utils may access some protected members of the expression stepper.
Definition core/small_step/expr_stepper.h:174
virtual void evalExternMethodCall(const ExternInfo &externInfo)
Definition extern_stepper.cpp:923
void evalActionCall(const IR::P4Action *action, const IR::MethodCallExpression *call)
Definition core/small_step/expr_stepper.cpp:102
virtual void stepNoMatch(std::string traceLog, const IR::Expression *condition=nullptr)
Definition core/small_step/expr_stepper.cpp:520
void handleHitMissActionRun(const IR::Member *member)
Definition core/small_step/expr_stepper.cpp:55
static const ExprStepper::ExternMethodImpls< ExprStepper > CORE_EXTERN_METHOD_IMPLS
Provides implementations of all known extern methods built into P4 core.
Definition core/small_step/expr_stepper.h:163
friend class TableStepper
We delegate evaluation to the TableStepper, which needs to access protected members.
Definition core/small_step/expr_stepper.h:171
void generateCopyIn(ExecutionState &nextState, const IR::StateVariable &targetPath, const IR::StateVariable &srcPath, cstring dir, bool forceTaint) const
TODO: Consolidate this into the copy_in_out extern.
const IR::Expression * advanceFailCond
The condition that needs to be satisfied for the advance/extract to be rejected.
Definition core/small_step/expr_stepper.h:190
virtual PacketCursorAdvanceInfo calculateAdvanceExpression(const ExecutionState &state, const IR::Expression *advanceExpr, const IR::Expression *restrictions) const
Definition extern_stepper.cpp:111
const IR::Expression * advanceCond
The condition that needs to be satisfied to successfully advance the parser cursor.
Definition core/small_step/expr_stepper.h:184
static const ExprStepper::ExternMethodImpls< ExprStepper > INTERNAL_EXTERN_METHOD_IMPLS
Definitions of internal helper functions.
Definition core/small_step/expr_stepper.h:160
bool resolveMethodCallArguments(const IR::MethodCallExpression *call)
Definition core/small_step/expr_stepper.cpp:129
Definition core/small_step/expr_stepper.h:179
Definition extern_info.h:20
Stores target-specific information about a P4 program.
Definition core/program_info.h:27
Definition cstring.h:85
Definition phv/solver/action_constraint_solver.cpp:33
Definition id.h:28