P4C
The P4 Compiler
Loading...
Searching...
No Matches
core/small_step/expr_stepper.h
1#ifndef BACKENDS_P4TOOLS_MODULES_TESTGEN_CORE_SMALL_STEP_EXPR_STEPPER_H_
2#define BACKENDS_P4TOOLS_MODULES_TESTGEN_CORE_SMALL_STEP_EXPR_STEPPER_H_
3
4#include <cstdint>
5#include <utility>
6#include <vector>
7
8#include "ir/ir.h"
9#include "ir/solver.h"
10#include "lib/cstring.h"
11
12#include "backends/p4tools/modules/testgen/core/extern_info.h"
13#include "backends/p4tools/modules/testgen/core/program_info.h"
14#include "backends/p4tools/modules/testgen/core/small_step/abstract_stepper.h"
15#include "backends/p4tools/modules/testgen/lib/execution_state.h"
16
17namespace P4::P4Tools::P4Testgen {
18
21 /**************************************************************************************************
22 ExternMethodImpls
23 **************************************************************************************************/
24 public:
26 template <typename StepperType>
28 public:
34 using MethodImpl = std::function<void(const ExternInfo &externInfo, StepperType &stepper)>;
35
48 std::optional<MethodImpl> find(const IR::PathExpression &externObjectRef,
49 const IR::ID &methodName,
50 const IR::Vector<IR::Argument> &args) const {
51 // We have to check the extern type here. We may receive a specialized canonical type,
52 // which we need to unpack.
53 const IR::Type_Extern *externType = nullptr;
54 if (const auto *type = externObjectRef.type->to<IR::Type_Extern>()) {
55 externType = type;
56 } else if (const auto *specType =
57 externObjectRef.type->to<IR::Type_SpecializedCanonical>()) {
58 CHECK_NULL(specType->substituted);
59 externType = specType->substituted->checkedTo<IR::Type_Extern>();
60 } else if (externObjectRef.path->name == IR::ID("*method")) {
61 } else {
62 BUG("Not a valid extern: %1% with member %2%. Type is %3%.", externObjectRef,
63 methodName, externObjectRef.type->node_type_name());
64 }
65
66 cstring qualifiedMethodName = externType->name + "." + methodName;
67 auto submapIt = impls.find(qualifiedMethodName);
68 if (submapIt == impls.end()) {
69 return std::nullopt;
70 }
71 if (submapIt->second.count(args.size()) == 0) {
72 return std::nullopt;
73 }
74
75 // Find matching methods: if any arguments are named, then the parameter name must
76 // match.
77 std::optional<MethodImpl> matchingImpl;
78 for (const auto &pair : submapIt->second.at(args.size())) {
79 const auto &paramNames = pair.first;
80 const auto &methodImpl = pair.second;
81
82 if (matches(paramNames, args)) {
83 BUG_CHECK(!matchingImpl, "Ambiguous extern method call: %1%",
84 qualifiedMethodName);
85 matchingImpl = methodImpl;
86 }
87 }
88
89 return matchingImpl;
90 }
91
92 private:
97 std::map<cstring,
98 std::map<size_t, std::vector<std::pair<std::vector<cstring>, MethodImpl>>>>
99 impls;
100
104 static bool matches(const std::vector<cstring> &paramNames,
105 const IR::Vector<IR::Argument> &args) {
106 // Number of parameters should match the number of arguments.
107 if (paramNames.size() != args.size()) {
108 return false;
109 }
110 // Any named argument should match the name of the corresponding parameter.
111 for (size_t idx = 0; idx < paramNames.size(); idx++) {
112 const auto &paramName = paramNames.at(idx);
113 const auto &arg = args.at(idx);
114
115 if (arg->name.name == nullptr) {
116 continue;
117 }
118 if (paramName != arg->name.name) {
119 return false;
120 }
121 }
122
123 return true;
124 }
125
126 public:
132 using ImplList = std::list<std::tuple<cstring, std::vector<cstring>, MethodImpl>>;
133
134 explicit ExternMethodImpls(const ImplList &implList) {
135 for (const auto &implSpec : implList) {
136 auto &[name, paramNames, impl] = implSpec;
137
138 auto &tmpImplList = impls[name][paramNames.size()];
139
140 // Make sure that we have at most one implementation for each set of parameter
141 // names. This is a quadratic-time algorithm, but should be fine, since we expect
142 // the number of overloads to be small in practice.
143 for (auto &pair : tmpImplList) {
144 BUG_CHECK(pair.first != paramNames, "Multiple implementations of %1%(%2%)",
145 name, paramNames);
146 }
147
148 tmpImplList.emplace_back(paramNames, impl);
149 }
150 }
151 };
152
155
158
159 /**************************************************************************************************
160 ExprStepper
161 **************************************************************************************************/
162
163 private:
165 friend class TableStepper;
166
168 friend class ExtractUtils;
169
170 protected:
176
178 const IR::Expression *advanceCond;
179
182
184 const IR::Expression *advanceFailCond;
185 };
186
191 int advanceSize) const;
197 const ExecutionState &state, const IR::Expression *advanceExpr,
198 const IR::Expression *restrictions) const;
199
203 static std::vector<std::pair<IR::StateVariable, const IR::Expression *>> setFields(
204 ExecutionState &nextState, const std::vector<IR::StateVariable> &flatFields,
205 int varBitFieldSize);
210 void handleHitMissActionRun(const IR::Member *member);
211
215 bool resolveMethodCallArguments(const IR::MethodCallExpression *call);
216
228 virtual void evalExternMethodCall(const ExternInfo &externInfo);
229
242 void evalInternalExternMethodCall(const ExternInfo &externInfo);
243
251 void evalActionCall(const IR::P4Action *action, const IR::MethodCallExpression *call);
252
257 // Otherwise, the target default value is chosen.
259 void generateCopyIn(ExecutionState &nextState, const IR::StateVariable &targetPath,
260 const IR::StateVariable &srcPath, cstring dir, bool forceTaint) const;
261
265 virtual void stepNoMatch(std::string traceLog, const IR::Expression *condition = nullptr);
266
267 public:
268 ExprStepper(const ExprStepper &) = default;
269
270 ExprStepper(ExprStepper &&) = default;
271
272 ExprStepper &operator=(const ExprStepper &) = delete;
273
274 ExprStepper &operator=(ExprStepper &&) = delete;
275
277
278 bool preorder(const IR::BoolLiteral *boolLiteral) override;
279 bool preorder(const IR::Constant *constant) override;
280 bool preorder(const IR::Member *member) override;
281 bool preorder(const IR::ArrayIndex *arr) override;
282 bool preorder(const IR::MethodCallExpression *call) override;
283 bool preorder(const IR::Mux *mux) override;
284 bool preorder(const IR::PathExpression *pathExpression) override;
285
289 bool preorder(const IR::P4ValueSet *valueSet) override;
290 bool preorder(const IR::Operation_Binary *binary) override;
291 bool preorder(const IR::Operation_Unary *unary) override;
292 bool preorder(const IR::SelectExpression *selectExpression) override;
293 bool preorder(const IR::BaseListExpression *listExpression) override;
294 bool preorder(const IR::StructExpression *structExpression) override;
295 bool preorder(const IR::Slice *slice) override;
296 bool preorder(const IR::P4Table *table) override;
297};
298
299} // namespace P4::P4Tools::P4Testgen
300
301#endif /* BACKENDS_P4TOOLS_MODULES_TESTGEN_CORE_SMALL_STEP_EXPR_STEPPER_H_ */
Provides a higher-level interface for an SMT solver.
Definition solver.h:24
Definition vector.h:58
Definition abstract_stepper.h:28
ExecutionState & state
The state being evaluated.
Definition abstract_stepper.h:49
const ProgramInfo & programInfo
Target-specific information about the P4 program being evaluated.
Definition abstract_stepper.h:46
AbstractSolver & solver
The solver backing the state being executed.
Definition abstract_stepper.h:52
Represents state of execution after having reached a program point.
Definition execution_state.h:34
Encapsulates a set of extern method implementations.
Definition core/small_step/expr_stepper.h:27
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:48
std::list< std::tuple< cstring, std::vector< cstring >, MethodImpl > > ImplList
Definition core/small_step/expr_stepper.h:132
std::function< void(const ExternInfo &externInfo, StepperType &stepper)> MethodImpl
Definition core/small_step/expr_stepper.h:34
Implements small-step operational semantics for expressions.
Definition core/small_step/expr_stepper.h:20
int advanceFailSize
Specifies at what point the parser cursor advancement will fail.
Definition core/small_step/expr_stepper.h:181
virtual PacketCursorAdvanceInfo calculateSuccessfulParserAdvance(const ExecutionState &state, int advanceSize) const
Definition extern_stepper.cpp:86
void evalInternalExternMethodCall(const ExternInfo &externInfo)
Definition extern_stepper.cpp:318
int advanceSize
How much the parser cursor will be advanced in a successful parsing case.
Definition core/small_step/expr_stepper.h:175
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:35
friend class ExtractUtils
Extract utils may access some protected members of the expression stepper.
Definition core/small_step/expr_stepper.h:168
virtual void evalExternMethodCall(const ExternInfo &externInfo)
Definition extern_stepper.cpp:918
void evalActionCall(const IR::P4Action *action, const IR::MethodCallExpression *call)
Definition core/small_step/expr_stepper.cpp:97
virtual void stepNoMatch(std::string traceLog, const IR::Expression *condition=nullptr)
Definition core/small_step/expr_stepper.cpp:512
void handleHitMissActionRun(const IR::Member *member)
Definition core/small_step/expr_stepper.cpp:50
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:157
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:184
virtual PacketCursorAdvanceInfo calculateAdvanceExpression(const ExecutionState &state, const IR::Expression *advanceExpr, const IR::Expression *restrictions) const
Definition extern_stepper.cpp:98
const IR::Expression * advanceCond
The condition that needs to be satisfied to successfully advance the parser cursor.
Definition core/small_step/expr_stepper.h:178
static const ExprStepper::ExternMethodImpls< ExprStepper > INTERNAL_EXTERN_METHOD_IMPLS
Definitions of internal helper functions.
Definition core/small_step/expr_stepper.h:154
bool resolveMethodCallArguments(const IR::MethodCallExpression *call)
Definition core/small_step/expr_stepper.cpp:124
Definition core/small_step/expr_stepper.h:173
Definition extern_info.h:14
Stores target-specific information about a P4 program.
Definition core/program_info.h:21
Implements small-step operational semantics for tables.
Definition core/small_step/table_stepper.h:20
Definition cstring.h:85
Definition id.h:28