Skip to content

Commit

Permalink
Support for [lsb+:width] slices
Browse files Browse the repository at this point in the history
- allows for non-const lsb slices (width must still be const)

Signed-off-by: Chris Dodd <[email protected]>
  • Loading branch information
ChrisDodd committed Sep 30, 2024
1 parent 7dec522 commit 623c388
Show file tree
Hide file tree
Showing 44 changed files with 380 additions and 45 deletions.
2 changes: 1 addition & 1 deletion backends/bmv2/common/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ void ExpressionConverter::postorder(const IR::StringLiteral *expression) {

void ExpressionConverter::postorder(const IR::TypeNameExpression *expression) { (void)expression; }

void ExpressionConverter::postorder(const IR::Slice *expression) {
void ExpressionConverter::postorder(const IR::AbstractSlice *expression) {
auto result = new Util::JsonObject();
auto expr = expression->e0;
int h = expression->getH();
Expand Down
2 changes: 1 addition & 1 deletion backends/bmv2/common/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class ExpressionConverter : public Inspector {
void postorder(const IR::BoolLiteral *expression) override;
void postorder(const IR::MethodCallExpression *expression) override;
void postorder(const IR::Cast *expression) override;
void postorder(const IR::Slice *expression) override;
void postorder(const IR::AbstractSlice *expression) override;
void postorder(const IR::AddSat *expression) override { saturated_binary(expression); }
void postorder(const IR::SubSat *expression) override { saturated_binary(expression); }
void postorder(const IR::Constant *expression) override;
Expand Down
2 changes: 1 addition & 1 deletion backends/bmv2/common/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const IR::Node *LowerExpressions::postorder(IR::Expression *expression) {
return expression;
}

const IR::Node *LowerExpressions::postorder(IR::Slice *expression) {
const IR::Node *LowerExpressions::postorder(IR::AbstractSlice *expression) {
// This is in a RHS expression a[m:l] -> (cast)(a >> l)
int h = expression->getH();
int l = expression->getL();
Expand Down
2 changes: 1 addition & 1 deletion backends/bmv2/common/lower.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class LowerExpressions : public Transform {
const IR::Node *postorder(IR::Shr *expression) override { return shift(expression); }
const IR::Node *postorder(IR::Cast *expression) override;
const IR::Node *postorder(IR::Neg *expression) override;
const IR::Node *postorder(IR::Slice *expression) override;
const IR::Node *postorder(IR::AbstractSlice *expression) override;
const IR::Node *postorder(IR::Concat *expression) override;
const IR::Node *preorder(IR::P4Table *table) override {
prune();
Expand Down
2 changes: 1 addition & 1 deletion backends/ebpf/codeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class CodeGenInspector : public Inspector {
bool preorder(const IR::Expression *expression) override { return notSupported(expression); }
bool preorder(const IR::Range *expression) override { return notSupported(expression); }
bool preorder(const IR::Mask *expression) override { return notSupported(expression); }
bool preorder(const IR::Slice *expression) override // should not happen
bool preorder(const IR::AbstractSlice *expression) override // should not happen
{
return notSupported(expression);
}
Expand Down
2 changes: 1 addition & 1 deletion backends/p4tools/common/core/z3_solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ bool Z3Translator::recurseBinary(const IR::Operation_Binary *binary, Z3BinaryOp
/// Building ternary operations
bool Z3Translator::preorder(const IR::Mux *op) { return recurseTernary(op, z3::ite); }

bool Z3Translator::preorder(const IR::Slice *op) {
bool Z3Translator::preorder(const IR::AbstractSlice *op) {
return recurseTernary(op, [](const z3::expr &e0, const z3::expr &e1, const z3::expr &e2) {
return e0.extract(e1.simplify().get_numeral_uint(), e2.simplify().get_numeral_uint());
});
Expand Down
2 changes: 1 addition & 1 deletion backends/p4tools/common/core/z3_solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ class Z3Translator : public virtual Inspector {

// Translations for ternary operations.
bool preorder(const IR::Mux *op) override;
bool preorder(const IR::Slice *op) override;
bool preorder(const IR::AbstractSlice *op) override;

/// @returns the result of the translation.
z3::expr getResult();
Expand Down
2 changes: 1 addition & 1 deletion backends/p4tools/common/lib/symbolic_env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ bool SymbolicEnv::isSymbolicValue(const IR::Node *node) {
binary->is<IR::Concat>() || binary->is<IR::Mask>()) &&
isSymbolicValue(binary->left) && isSymbolicValue(binary->right);
}
if (const auto *slice = expr->to<IR::Slice>()) {
if (const auto *slice = expr->to<IR::AbstractSlice>()) {
return isSymbolicValue(slice->e0) && isSymbolicValue(slice->e1) &&
isSymbolicValue(slice->e2);
}
Expand Down
2 changes: 1 addition & 1 deletion backends/p4tools/modules/smith/common/statements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ void StatementGenerator::removeLval(const IR::Expression *left, const IR::Type *
lvalStr = path->path->name.name;
} else if (const auto *mem = left->to<IR::Member>()) {
lvalStr = mem->member.name;
} else if (const auto *slice = left->to<IR::Slice>()) {
} else if (const auto *slice = left->to<IR::AbstractSlice>()) {
lvalStr = slice->e0->to<IR::PathExpression>()->path->name.name;
} else if (const auto *arrIdx = left->to<IR::ArrayIndex>()) {
lvalStr = arrIdx->left->to<IR::PathExpression>()->path->name.name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ bool ExprStepper::preorder(const IR::StructExpression *structExpression) {
return stepSymbolicValue(structExpression);
}

bool ExprStepper::preorder(const IR::Slice *slice) {
bool ExprStepper::preorder(const IR::AbstractSlice *slice) {
logStep(slice);

if (!SymbolicEnv::isSymbolicValue(slice->e0)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ class ExprStepper : public AbstractStepper {
bool preorder(const IR::SelectExpression *selectExpression) override;
bool preorder(const IR::BaseListExpression *listExpression) override;
bool preorder(const IR::StructExpression *structExpression) override;
bool preorder(const IR::Slice *slice) override;
bool preorder(const IR::AbstractSlice *slice) override;
bool preorder(const IR::P4Table *table) override;
};

Expand Down
45 changes: 45 additions & 0 deletions frontends/common/constantFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,51 @@ const IR::Node *DoConstantFolding::postorder(IR::Slice *e) {
return new IR::Constant(e->srcInfo, resultType, value, cbase->base, true);
}

const IR::Node *DoConstantFolding::postorder(IR::PlusSlice *e) {
auto *e0 = getConstant(e->e0);
auto *lsb = getConstant(e->e1);
auto *width = getConstant(e->e2);
if (!width) {
if (typesKnown)
error(ErrorType::ERR_EXPECTED, "%1%: slice indexes must be compile-time constants",
e->e2);
return e;
}

if (!e0 || !lsb) return e;

auto clsb = lsb->to<IR::Constant>();
if (clsb == nullptr) {
error(ErrorType::ERR_EXPECTED, "%1%: expected an integer value", lsb);
return e;
}
auto cwidth = width->to<IR::Constant>();
if (cwidth == nullptr) {
error(ErrorType::ERR_EXPECTED, "%1%: expected an integer value", width);
return e;
}
auto cbase = e0->to<IR::Constant>();
if (cbase == nullptr) {
error(ErrorType::ERR_EXPECTED, "%1%: expected an integer value", e->e0);
return e;
}

int w = cwidth->asInt();
int l = clsb->asInt();
if (l < 0) {
::P4::error(ErrorType::ERR_EXPECTED, "%1%: expected slice indexes to be non-negative",
e->e2);
return e;
}
if (overflowWidth(e, l) || overflowWidth(e, l + w)) return e;
big_int value = cbase->value >> l;
big_int mask = 1;
mask = (mask << w) - 1;
value = value & mask;
auto resultType = IR::Type_Bits::get(w);
return new IR::Constant(e->srcInfo, resultType, value, cbase->base, true);
}

const IR::Node *DoConstantFolding::postorder(IR::Member *e) {
if (!typesKnown) return e;
auto orig = getOriginal<IR::Member>();
Expand Down
1 change: 1 addition & 0 deletions frontends/common/constantFolding.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ class DoConstantFolding : public Transform, public ResolutionContext {
const IR::Node *postorder(IR::LAnd *e) override;
const IR::Node *postorder(IR::LOr *e) override;
const IR::Node *postorder(IR::Slice *e) override;
const IR::Node *postorder(IR::PlusSlice *e) override;
const IR::Node *postorder(IR::Add *e) override;
const IR::Node *postorder(IR::AddSat *e) override;
const IR::Node *postorder(IR::Sub *e) override;
Expand Down
3 changes: 1 addition & 2 deletions frontends/p4-14/fromv1.0/converters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,7 @@ const IR::Node *ExpressionConverter::postorder(IR::Primitive *primitive) {
auto typeargs = new IR::Vector<IR::Type>();
typeargs->push_back(IR::Type_Bits::get(aval + bval));
auto lookahead = new IR::MethodCallExpression(method, typeargs);
auto result = new IR::Slice(primitive->srcInfo, lookahead, new IR::Constant(bval - 1),
new IR::Constant(0));
auto result = new IR::Slice(primitive->srcInfo, lookahead, bval - 1, 0);
result->type = IR::Type_Bits::get(bval);
return result;
} else if (primitive->name == "valid") {
Expand Down
2 changes: 1 addition & 1 deletion frontends/p4/alias.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class ReadsWrites : public Inspector, public ResolutionContext {
rw.emplace(expression, e0->join(e1)->join(e2));
}

void postorder(const IR::Slice *expression) override {
void postorder(const IR::AbstractSlice *expression) override {
auto e = ::P4::get(rw, expression->e0);
CHECK_NULL(e);
rw.emplace(expression, e);
Expand Down
2 changes: 1 addition & 1 deletion frontends/p4/def_use.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ bool ComputeWriteSet::preorder(const IR::Literal *expression) {
return false;
}

bool ComputeWriteSet::preorder(const IR::Slice *expression) {
bool ComputeWriteSet::preorder(const IR::AbstractSlice *expression) {
visit(expression->e0);
expressionWrites(expression, lhs ? getWrites(expression->e0) : LocationSet::empty);
return false;
Expand Down
2 changes: 1 addition & 1 deletion frontends/p4/def_use.h
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ class ComputeWriteSet : public Inspector, public IHasDbPrint {

// expressions
bool preorder(const IR::Literal *expression) override;
bool preorder(const IR::Slice *expression) override;
bool preorder(const IR::AbstractSlice *expression) override;
bool preorder(const IR::TypeNameExpression *expression) override;
bool preorder(const IR::PathExpression *expression) override;
bool preorder(const IR::Member *expression) override;
Expand Down
2 changes: 1 addition & 1 deletion frontends/p4/inlining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class FindLocationSets : public Inspector {
return false;
}

bool preorder(const IR::Slice *expression) {
bool preorder(const IR::AbstractSlice *expression) {
visit(expression->e0);
auto base = get(expression->e0);
set(expression, base);
Expand Down
2 changes: 1 addition & 1 deletion frontends/p4/sideEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ const IR::Node *DoSimplifyExpressions::preorder(IR::MethodCallExpression *mce) {

// If the parameter is out and the argument is a slice then
// also use a temporary; makes the job of def-use analysis easier
if (arg->expression->is<IR::Slice>() && p->hasOut()) {
if (arg->expression->is<IR::AbstractSlice>() && p->hasOut()) {
LOG3("Using temporary for " << dbp(mce) << " param " << dbp(p)
<< " since it is an out slice");
useTemporary.emplace(p);
Expand Down
14 changes: 7 additions & 7 deletions frontends/p4/simplifyDefUse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ class HasUses {
absl::flat_hash_set<const IR::Node *, Util::Hash> used;

class SliceTracker {
const IR::Slice *trackedSlice = nullptr;
const IR::AbstractSlice *trackedSlice = nullptr;
bool active = false;
bool overwritesPrevious(const IR::Slice *previous) {
bool overwritesPrevious(const IR::AbstractSlice *previous) {
if (trackedSlice->getH() >= previous->getH() &&
trackedSlice->getL() <= previous->getL())
// current overwrites the previous
Expand All @@ -49,7 +49,7 @@ class HasUses {

public:
SliceTracker() = default;
explicit SliceTracker(const IR::Slice *slice) : trackedSlice(slice), active(true) {}
explicit SliceTracker(const IR::AbstractSlice *slice) : trackedSlice(slice), active(true) {}
bool isActive() const { return active; }

// main logic of this class
Expand All @@ -58,7 +58,7 @@ class HasUses {
if (previous.isBeforeStart()) return false;
auto last = previous.last();
if (auto *assign_stmt = last->to<IR::AssignmentStatement>()) {
if (auto *slice_stmt = assign_stmt->left->to<IR::Slice>()) {
if (auto *slice_stmt = assign_stmt->left->to<IR::AbstractSlice>()) {
// two slice stmts writing to same location
// skip use of previous if it gets overwritten
if (overwritesPrevious(slice_stmt)) {
Expand Down Expand Up @@ -91,7 +91,7 @@ class HasUses {
}
bool hasUses(const IR::Node *node) const { return used.find(node) != used.end(); }

void watchForOverwrites(const IR::Slice *slice) {
void watchForOverwrites(const IR::AbstractSlice *slice) {
BUG_CHECK(!tracker.isActive(), "Call to SliceTracker, but it's already active");
tracker = SliceTracker(slice);
}
Expand Down Expand Up @@ -644,7 +644,7 @@ class FindUninitialized : public Inspector {
loc = new LocationSet(storage);
else
loc = LocationSet::empty;
} else if (auto slice = parent->to<IR::Slice>()) {
} else if (auto slice = parent->to<IR::AbstractSlice>()) {
loc = checkHeaderFieldWrite(expr, slice->e0);
} else {
BUG("%1%: unexpected expression on LHS", parent);
Expand Down Expand Up @@ -1380,7 +1380,7 @@ class FindUninitialized : public Inspector {
return false;
}

bool preorder(const IR::Slice *expression) override {
bool preorder(const IR::AbstractSlice *expression) override {
LOG3("FU Visiting [" << expression->id << "]: " << expression);

auto *slice_stmt = findContext<IR::AssignmentStatement>();
Expand Down
19 changes: 19 additions & 0 deletions frontends/p4/strengthReduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,4 +448,23 @@ const IR::Node *DoStrengthReduction::postorder(IR::Slice *expr) {
return expr;
}

const IR::Node *DoStrengthReduction::postorder(IR::PlusSlice *expr) {
if (expr->e1->is<IR::Constant>() && expr->e2->is<IR::Constant>()) {
auto *rv = new IR::Slice(expr->srcInfo, expr->e0, expr->getH(), expr->getL());
return postorder(rv);
}
if (auto sh = expr->e0->to<IR::Shr>()) {
if (!sh->left->type->is<IR::Type_Bits>()) return expr;
if (sh->left->type->to<IR::Type_Bits>()->isSigned) return expr;
expr->e0 = sh->left;
expr->e1 = new IR::Add(sh->srcInfo, expr->e1, sh->right);
}
if (auto sh = expr->e0->to<IR::Shl>()) {
if (!sh->left->type->is<IR::Type_Bits>()) return expr;
expr->e0 = sh->left;
expr->e1 = new IR::Sub(sh->srcInfo, expr->e1, sh->right);
}
return expr;
}

} // namespace P4
1 change: 1 addition & 0 deletions frontends/p4/strengthReduction.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class DoStrengthReduction final : public Transform {
const IR::Node *postorder(IR::Mod *expr) override;
const IR::Node *postorder(IR::Mux *expr) override;
const IR::Node *postorder(IR::Slice *expr) override;
const IR::Node *postorder(IR::PlusSlice *expr) override;
const IR::Node *postorder(IR::Mask *expr) override;
const IR::Node *postorder(IR::Range *expr) override;
const IR::Node *postorder(IR::Concat *expr) override;
Expand Down
2 changes: 1 addition & 1 deletion frontends/p4/tableKeyNames.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ void KeyNameGenerator::postorder(const IR::Constant *expression) {
name.emplace(expression, Util::toString(expression->value, 0, false, expression->base));
}

void KeyNameGenerator::postorder(const IR::Slice *expression) {
void KeyNameGenerator::postorder(const IR::AbstractSlice *expression) {
cstring e0 = getName(expression->e0);
cstring e1 = getName(expression->e1);
cstring e2 = getName(expression->e2);
Expand Down
2 changes: 1 addition & 1 deletion frontends/p4/tableKeyNames.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class KeyNameGenerator : public Inspector {
void postorder(const IR::Member *expression) override;
void postorder(const IR::ArrayIndex *expression) override;
void postorder(const IR::Constant *expression) override;
void postorder(const IR::Slice *expression) override;
void postorder(const IR::AbstractSlice *expression) override;
void postorder(const IR::BAnd *expression) override;
void postorder(const IR::MethodCallExpression *expression) override;
cstring getName(const IR::Expression *expression) { return ::P4::get(name, expression); }
Expand Down
3 changes: 2 additions & 1 deletion frontends/p4/toP4/toP4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ VECTOR_VISIT(IndexedVector, StatOrDecl)

///////////////////////////////////////////

bool ToP4::preorder(const IR::Slice *slice) {
bool ToP4::preorder(const IR::AbstractSlice *slice) {
int prec = expressionPrecedence;
bool useParens = prec > slice->getPrecedence();
if (useParens) builder.append("(");
Expand All @@ -782,6 +782,7 @@ bool ToP4::preorder(const IR::Slice *slice) {
builder.append("[");
expressionPrecedence = DBPrint::Prec_Low;
visit(slice->e1);
if (slice->is<IR::PlusSlice>()) builder.append("+");
builder.append(":");
expressionPrecedence = DBPrint::Prec_Low;
visit(slice->e2);
Expand Down
2 changes: 1 addition & 1 deletion frontends/p4/toP4/toP4.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class ToP4 : public Inspector, ResolutionContext {
bool preorder(const IR::Dots *e) override;
bool preorder(const IR::NamedDots *e) override;
bool preorder(const IR::Constant *c) override;
bool preorder(const IR::Slice *slice) override;
bool preorder(const IR::AbstractSlice *slice) override;
bool preorder(const IR::BoolLiteral *b) override;
bool preorder(const IR::StringLiteral *s) override;
bool preorder(const IR::PathExpression *p) override;
Expand Down
1 change: 1 addition & 0 deletions frontends/p4/typeChecking/readOnlyTypeInference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ DEFINE_POSTORDER(IR::Cmpl)
DEFINE_POSTORDER(IR::Cast)
DEFINE_POSTORDER(IR::Mux)
DEFINE_POSTORDER(IR::Slice)
DEFINE_POSTORDER(IR::PlusSlice)
DEFINE_POSTORDER(IR::PathExpression)
DEFINE_POSTORDER(IR::Member)
DEFINE_POSTORDER(IR::TypeNameExpression)
Expand Down
Loading

0 comments on commit 623c388

Please sign in to comment.