-
Notifications
You must be signed in to change notification settings - Fork 442
Commit
…ern - preserve InOut references (#4255) * Resolve method call arguments before stepping into the extern. * Cleanup. * Review comments. * Review comments.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -121,10 +121,54 @@ void ExprStepper::evalActionCall(const IR::P4Action *action, const IR::MethodCal | |
result->emplace_back(state); | ||
} | ||
|
||
bool ExprStepper::resolveMethodCallArguments(const IR::MethodCallExpression *call) { | ||
IR::Vector<IR::Argument> resolvedArgs; | ||
const auto *method = call->method->type->checkedTo<IR::Type_MethodBase>(); | ||
const auto &methodParams = method->parameters->parameters; | ||
const auto *callArguments = call->arguments; | ||
for (size_t idx = 0; idx < callArguments->size(); ++idx) { | ||
const auto *arg = callArguments->at(idx); | ||
const auto *param = methodParams.at(idx); | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
fruffy
Author
Collaborator
|
||
const auto *argExpr = arg->expression; | ||
if (param->direction == IR::Direction::Out || SymbolicEnv::isSymbolicValue(argExpr)) { | ||
continue; | ||
} | ||
// If the parameter is not an out parameter (meaning we do not care about its content) and | ||
// the argument is not yet symbolic, try to resolve it. | ||
return stepToSubexpr( | ||
argExpr, result, state, [call, idx, param](const Continuation::Parameter *v) { | ||
// TODO: It seems expensive to copy the function every time we resolve an argument. | ||
// We should do this all at once. But how? | ||
// This is the same problem as in stepToListSubexpr | ||
// Thankfully, most method calls have less than 10 arguments. | ||
auto *clonedCall = call->clone(); | ||
auto *arguments = clonedCall->arguments->clone(); | ||
auto *arg = arguments->at(idx)->clone(); | ||
const IR::Expression *computedExpr = v->param; | ||
// A parameter with direction InOut might be read and also written to. | ||
// We capture this ambiguity with an InOutReference. | ||
if (param->direction == IR::Direction::InOut) { | ||
auto stateVar = ToolsVariables::convertReference(arg->expression); | ||
computedExpr = new IR::InOutReference(stateVar, computedExpr); | ||
} | ||
arg->expression = computedExpr; | ||
(*arguments)[idx] = arg; | ||
clonedCall->arguments = arguments; | ||
return Continuation::Return(clonedCall); | ||
}); | ||
} | ||
return true; | ||
} | ||
|
||
bool ExprStepper::preorder(const IR::MethodCallExpression *call) { | ||
logStep(call); | ||
// A method call expression represents an invocation of an action, a table, an extern, or | ||
// setValid/setInvalid. | ||
|
||
if (!resolveMethodCallArguments(call)) { | ||
return false; | ||
} | ||
|
||
// Handle method calls. These are either table invocations or extern calls. | ||
if (call->method->type->is<IR::Type_Method>()) { | ||
if (const auto *path = call->method->to<IR::PathExpression>()) { | ||
|
@@ -255,6 +299,13 @@ bool ExprStepper::preorder(const IR::Mux *mux) { | |
|
||
bool ExprStepper::preorder(const IR::PathExpression *pathExpression) { | ||
logStep(pathExpression); | ||
// If the path expression is a Type_MatchKind, convert it to a StringLiteral. | ||
if (pathExpression->type->is<IR::Type_MatchKind>()) { | ||
state.replaceTopBody(Continuation::Return( | ||
new IR::StringLiteral(IR::Type_MatchKind::get(), pathExpression->path->name))); | ||
result->emplace_back(state); | ||
return false; | ||
} | ||
// Otherwise convert the path expression into a qualified member and return it. | ||
state.replaceTopBody(Continuation::Return(state.get(pathExpression))); | ||
result->emplace_back(state); | ||
|
@fruffy, there can be unequal method params and call arguments?
call: *.prepend_to_prog_header(0);, method: _<>(), methodParams size: 0, callArguments size: 1