Skip to content

Commit

Permalink
Remove the array indices conversions and handle indices in the interp…
Browse files Browse the repository at this point in the history
…reter. (#4024)
  • Loading branch information
fruffy-bfn authored Jun 13, 2023
1 parent 2873755 commit dff9347
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 16 deletions.
5 changes: 0 additions & 5 deletions backends/p4tools/common/compiler/compiler_target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,6 @@ std::optional<const IR::P4Program *> CompilerTarget::runCompilerImpl(
return std::nullopt;
}

// Rewrite all occurrences of ArrayIndex to be members instead.
// IMPORTANT: After this change, the program will no longer type-check.
// This is why perform this rewrite after all front and mid end passes have been applied.
program = program->apply(HSIndexToMember());

return program;
}

Expand Down
9 changes: 5 additions & 4 deletions backends/p4tools/common/compiler/convert_hs_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <string>

#include "ir/id.h"
#include "ir/irutils.h"
#include "lib/cstring.h"

namespace P4Tools {
Expand All @@ -14,10 +15,10 @@ const IR::Node *HSIndexToMember::postorder(IR::ArrayIndex *curArrayIndex) {
return curArrayIndex;
}

const IR::Member *HSIndexToMember::produceStackIndex(const IR::Type *type,
const IR::Expression *expression,
size_t arrayIndex) {
return new IR::Member(type, expression, IR::ID(std::to_string(arrayIndex)));
const IR::ArrayIndex *HSIndexToMember::produceStackIndex(const IR::Type *type,
const IR::Expression *expression,
size_t arrayIndex) {
return new IR::ArrayIndex(type, expression, IR::getConstant(IR::getBitType(32), arrayIndex));
}

} // namespace P4Tools
5 changes: 3 additions & 2 deletions backends/p4tools/common/compiler/convert_hs_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ class HSIndexToMember : public Transform {

/// Convert a parent expression and an index into a member expression with that
/// particular index as string member. The type is used to specify the member type.
static const IR::Member *produceStackIndex(const IR::Type *type,
const IR::Expression *expression, size_t arrayIndex);
static const IR::ArrayIndex *produceStackIndex(const IR::Type *type,
const IR::Expression *expression,
size_t arrayIndex);
};

} // namespace P4Tools
Expand Down
6 changes: 3 additions & 3 deletions backends/p4tools/common/core/abstract_execution_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,13 @@ std::vector<IR::StateVariable> AbstractExecutionState::getFlatFields(
} else if (const auto *typeStack = fieldType->to<IR::Type_Stack>()) {
const auto *stackElementsType = resolveType(typeStack->elementType);
for (size_t arrayIndex = 0; arrayIndex < typeStack->getSize(); arrayIndex++) {
const auto *newMember = HSIndexToMember::produceStackIndex(
const auto *newArr = HSIndexToMember::produceStackIndex(
stackElementsType, new IR::Member(typeStack, parent, field->name), arrayIndex);
BUG_CHECK(stackElementsType->is<IR::Type_StructLike>(),
"Try to make the flat fields for non Type_StructLike element : %1%",
stackElementsType);
auto subFields = getFlatFields(
newMember, stackElementsType->to<IR::Type_StructLike>(), validVector);
auto subFields = getFlatFields(newArr, stackElementsType->to<IR::Type_StructLike>(),
validVector);
flatFields.insert(flatFields.end(), subFields.begin(), subFields.end());
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ bool ExprStepper::preorder(const IR::Member *member) {
return stepSymbolicValue(state.get(member));
}

bool ExprStepper::preorder(const IR::ArrayIndex *arr) { return stepSymbolicValue(state.get(arr)); }

void ExprStepper::evalActionCall(const IR::P4Action *action, const IR::MethodCallExpression *call) {
const auto *actionNameSpace = action->to<IR::INamespace>();
BUG_CHECK(actionNameSpace, "Does not instantiate an INamespace: %1%", actionNameSpace);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ class ExprStepper : public AbstractStepper {
bool preorder(const IR::BoolLiteral *boolLiteral) override;
bool preorder(const IR::Constant *constant) override;
bool preorder(const IR::Member *member) override;
bool preorder(const IR::ArrayIndex *arr) override;
bool preorder(const IR::MethodCallExpression *call) override;
bool preorder(const IR::Mux *mux) override;
bool preorder(const IR::PathExpression *pathExpression) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ void ExprStepper::evalExternMethodCall(const IR::MethodCallExpression *call,
const ExecutionState &state, SmallStepEvaluator::Result &result) {
const auto *emitOutput = args->at(0)->expression;
const auto *emitType = emitOutput->type->checkedTo<IR::Type_StructLike>();
if (!emitOutput->is<IR::Member>()) {
if (!(emitOutput->is<IR::Member>() || emitOutput->is<IR::ArrayIndex>())) {
TESTGEN_UNIMPLEMENTED("Emit input %1% of type %2% not supported", emitOutput,
emitType);
}
Expand Down
38 changes: 38 additions & 0 deletions backends/p4tools/p4tools.def
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ class StateVariable : Expression {
Expression const &operator*() const { return *ref; }
Expression operator->() const { return ref; }

/// StateVariables can be Members, PathExpressions, or ArrayIndices.
StateVariable(Member member) : Expression(member->getSourceInfo(), member->type), ref(member) {}
/// The expression type is derived from the path.
StateVariable(PathExpression path) : Expression(path->getSourceInfo(), path->type), ref(path) {}
StateVariable(ArrayIndex arr) : Expression(arr->getSourceInfo(), arr->type), ref(arr) {}

/// Implements comparisons so that StateVariables can be used as map keys.
bool operator==(const StateVariable &other) const override {
Expand All @@ -42,6 +44,9 @@ class StateVariable : Expression {
if (e2->is<PathExpression>()) {
return 1;
}
if (e2->is<ArrayIndex>()) {
return 1;
}
}
// e1 is a PathExpression.
if (const auto *p1 = e1->to<PathExpression>()) {
Expand All @@ -51,6 +56,21 @@ class StateVariable : Expression {
if (e2->is<Member>()) {
return -1;
}
if (e2->is<ArrayIndex>()) {
return 1;
}
}
// e1 is a ArrayIndex.
if (const auto *a1 = e1->to<ArrayIndex>()) {
if (const auto *a2 = e2->to<ArrayIndex>()) {
return compare(a1, a2);
}
if (e2->is<Member>()) {
return -1;
}
if (e2->is<PathExpression>()) {
return -1;
}
}
BUG("Either %1% of type %2% or %3% of type %4% is not a valid StateVariable", e1, e1->node_type_name(), e2, e2->node_type_name());
}
Expand Down Expand Up @@ -79,6 +99,24 @@ class StateVariable : Expression {
return 0;
}

int compare(const ArrayIndex *a1, const ArrayIndex *a2) const {
auto result = compare(a1->left, a2->left);
if (result != 0) {
return result;
}
auto a1Val = a1->right->to<Constant>();
BUG_CHECK(a1Val != nullptr, "Value %1% is not a constant. Only constants are supported as part of a state variable.", a1->right);
auto a2Val = a2->right->to<Constant>();
BUG_CHECK(a2Val != nullptr, "Value %1% is not a constant. Only constants are supported as part of a state variable.", a2->right);
if (a1Val->value < a2Val->value) {
return -1;
}
if (a1Val->value > a2Val->value) {
return 1;
}
return 0;
}

toString { return ref->toString(); }

dbprint { ref->dbprint(out); }
Expand Down
2 changes: 1 addition & 1 deletion midend/hsIndexSimplify.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class HSIndexFinder : public Inspector {
void addNewVariable();
};

/// This class substitutes index of a header stack in all occurence of found header stack.
/// This class substitutes index of a header stack in all occurences of found header stack.
class HSIndexTransform : public Transform {
friend class HSIndexContretizer;
size_t index;
Expand Down

0 comments on commit dff9347

Please sign in to comment.