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 <cdodd@nvidia.com>
  • Loading branch information
ChrisDodd committed Sep 20, 2024
1 parent 90a9a01 commit 7ad797d
Show file tree
Hide file tree
Showing 29 changed files with 421 additions and 85 deletions.
2 changes: 1 addition & 1 deletion backends/dpdk/dpdkArch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ const IR::Node *AlignHdrMetaField::preorder(IR::Member *m) {
// two different headers have field with same name.
if (memVec.headerStr != hdrStrName) continue;
auto mem = new IR::Member(m->expr, IR::ID(memVec.modifiedName));
auto sliceMem = new IR::Slice(mem->clone(), memVec.msb, memVec.lsb);
auto sliceMem = new IR::AbsSlice(mem->clone(), memVec.msb, memVec.lsb);
return sliceMem;
}
}
Expand Down
4 changes: 2 additions & 2 deletions backends/p4tools/modules/smith/common/expressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ IR::Expression *ExpressionGenerator::constructTernaryBitExpr(const IR::Type_Bits
auto margin = newTypeSize - typeWidth;
auto high = Utils::getRandInt(0, margin) + typeWidth - 1;
auto low = high - typeWidth + 1;
expr = new IR::Slice(sliceExpr, high, low);
expr = new IR::AbsSlice(sliceExpr, high, low);
break;
}
case 1: {
Expand Down Expand Up @@ -1268,7 +1268,7 @@ IR::Expression *ExpressionGenerator::pickLvalOrSlice(const IR::Type *tp) {
new IR::PathExpression(IR::Type_Bits::get(candidateSize), lval->second);
auto low = Utils::getRandInt(0, candidateSize - targetWidth);
auto high = low + targetWidth - 1;
expr = new IR::Slice(sliceExpr, high, low);
expr = new IR::AbsSlice(sliceExpr, high, low);
} break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -454,9 +454,9 @@ const Constraint *CmdStepper::startParser(const IR::P4Parser *parser, ExecutionS
result = new IR::LAnd(
boolType, result,
new IR::Equ(boolType,
new IR::Slice(threeBitType, ExecutionState::getInputPacketSizeVar(),
IR::Constant::get(parserCursorVarType, 2),
IR::Constant::get(parserCursorVarType, 0)),
new IR::AbsSlice(threeBitType, ExecutionState::getInputPacketSizeVar(),
IR::Constant::get(parserCursorVarType, 2),
IR::Constant::get(parserCursorVarType, 0)),
IR::Constant::get(threeBitType, 0)));

// Call the implementation for the specific target.
Expand Down
10 changes: 5 additions & 5 deletions backends/p4tools/modules/testgen/lib/execution_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ const IR::Expression *ExecutionState::peekPacketBuffer(int amount) {
// If the buffer was not empty, append the data we have consumed to the newly generated
// content and reset the buffer.
if (bufferSize > 0) {
auto *slice = new IR::Slice(buffer, bufferSize - 1, 0);
auto *slice = new IR::AbsSlice(buffer, bufferSize - 1, 0);
slice->type = IR::Type_Bits::get(amount);
newVar = new IR::Concat(amountType, slice, newVar);
resetPacketBuffer();
Expand All @@ -435,7 +435,7 @@ const IR::Expression *ExecutionState::peekPacketBuffer(int amount) {
return newVar;
}
// The buffer is large enough and we can grab a slice
auto *slice = new IR::Slice(buffer, bufferSize - 1, bufferSize - amount);
auto *slice = new IR::AbsSlice(buffer, bufferSize - 1, bufferSize - amount);
slice->type = amountType;
return slice;
}
Expand Down Expand Up @@ -466,7 +466,7 @@ const IR::Expression *ExecutionState::slicePacketBuffer(int amount) {
// If the buffer was not empty, append the data we have consumed to the newly generated
// content and reset the buffer.
if (bufferSize > 0) {
auto *slice = new IR::Slice(buffer, bufferSize - 1, 0);
auto *slice = new IR::AbsSlice(buffer, bufferSize - 1, 0);
slice->type = IR::Type_Bits::get(amount);
newVar = new IR::Concat(amountType, slice, newVar);
resetPacketBuffer();
Expand All @@ -476,11 +476,11 @@ const IR::Expression *ExecutionState::slicePacketBuffer(int amount) {
return newVar;
}
// The buffer is large enough and we can grab a slice
auto *slice = new IR::Slice(buffer, bufferSize - 1, bufferSize - amount);
auto *slice = new IR::AbsSlice(buffer, bufferSize - 1, bufferSize - amount);
slice->type = amountType;
// If the buffer is larger, update the buffer with its remainder.
if (diff < 0) {
auto *remainder = new IR::Slice(buffer, bufferSize - amount - 1, 0);
auto *remainder = new IR::AbsSlice(buffer, bufferSize - amount - 1, 0);
remainder->type = IR::Type_Bits::get(bufferSize - amount);
env.set(&PacketVars::PACKET_BUFFER_LABEL, remainder);
}
Expand Down
12 changes: 6 additions & 6 deletions backends/p4tools/modules/testgen/targets/ebpf/expr_stepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,15 @@ const EBPFExprStepper::ExternMethodImpls<EBPFExprStepper> EBPFExprStepper::EBPF_
new IR::Cast(bt32, new IR::Concat(bt16, ttl, protocol)));
checksum = new IR::Add(bt32, checksum, new IR::Cast(bt32, hdrChecksum));
checksum =
new IR::Add(bt32, checksum, new IR::Cast(bt32, new IR::Slice(srcAddr, 31, 16)));
new IR::Add(bt32, checksum, new IR::Cast(bt32, new IR::AbsSlice(srcAddr, 31, 16)));
checksum =
new IR::Add(bt32, checksum, new IR::Cast(bt32, new IR::Slice(srcAddr, 15, 0)));
new IR::Add(bt32, checksum, new IR::Cast(bt32, new IR::AbsSlice(srcAddr, 15, 0)));
checksum =
new IR::Add(bt32, checksum, new IR::Cast(bt32, new IR::Slice(dstAddr, 31, 16)));
new IR::Add(bt32, checksum, new IR::Cast(bt32, new IR::AbsSlice(dstAddr, 31, 16)));
checksum =
new IR::Add(bt32, checksum, new IR::Cast(bt32, new IR::Slice(dstAddr, 15, 0)));
checksum =
new IR::Add(bt16, new IR::Slice(checksum, 31, 16), new IR::Slice(checksum, 15, 0));
new IR::Add(bt32, checksum, new IR::Cast(bt32, new IR::AbsSlice(dstAddr, 15, 0)));
checksum = new IR::Add(bt16, new IR::AbsSlice(checksum, 31, 16),
new IR::AbsSlice(checksum, 15, 0));
const auto *calcResult = new IR::Cmpl(bt16, checksum);
const auto *comparison = new IR::Equ(calcResult, IR::Constant::get(bt16, 0));
auto &nextState = stepper.state.clone();
Expand Down
60 changes: 30 additions & 30 deletions backends/p4tools/modules/testgen/test/lib/taint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ TEST_F(TaintTest, Taint02) {
{
const auto *expr =
new IR::Concat(IR::Type_Bits::get(16), IR::Constant::get(typeBits, 2), taintExpression);
const auto *slicedExpr = new IR::Slice(expr, 15, 8);
const auto *slicedExpr = new IR::AbsSlice(expr, 15, 8);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = IR::Constant::get(typeBits, 0);
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
}
{
const auto *expr =
new IR::Concat(IR::Type_Bits::get(16), taintExpression, IR::Constant::get(typeBits, 2));
const auto *slicedExpr = new IR::Slice(expr, 7, 0);
const auto *slicedExpr = new IR::AbsSlice(expr, 7, 0);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = IR::Constant::get(typeBits, 0);
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
Expand All @@ -87,15 +87,15 @@ TEST_F(TaintTest, Taint03) {
{
const auto *expr =
new IR::Concat(IR::Type_Bits::get(16), IR::Constant::get(typeBits, 2), taintExpression);
const auto *slicedExpr = new IR::Slice(expr, 7, 0);
const auto *slicedExpr = new IR::AbsSlice(expr, 7, 0);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = taintExpression;
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
}
{
const auto *expr =
new IR::Concat(IR::Type_Bits::get(16), taintExpression, IR::Constant::get(typeBits, 2));
const auto *slicedExpr = new IR::Slice(expr, 15, 8);
const auto *slicedExpr = new IR::AbsSlice(expr, 15, 8);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = taintExpression;
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
Expand All @@ -114,15 +114,15 @@ TEST_F(TaintTest, Taint04) {
{
const auto *expr =
new IR::Concat(IR::Type_Bits::get(16), IR::Constant::get(typeBits, 2), taintExpression);
const auto *slicedExpr = new IR::Slice(expr, 11, 4);
const auto *slicedExpr = new IR::AbsSlice(expr, 11, 4);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = taintExpression;
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
}
{
const auto *expr =
new IR::Concat(IR::Type_Bits::get(16), taintExpression, IR::Constant::get(typeBits, 2));
const auto *slicedExpr = new IR::Slice(expr, 11, 4);
const auto *slicedExpr = new IR::AbsSlice(expr, 11, 4);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = taintExpression;
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
Expand All @@ -142,15 +142,15 @@ TEST_F(TaintTest, Taint05) {
{
const auto *expr = new IR::Concat(IR::Type_Bits::get(16), taintExpression, constantVar);
expr = new IR::Concat(IR::Type_Bits::get(24), taintExpression, expr);
const auto *slicedExpr = new IR::Slice(expr, 11, 4);
const auto *slicedExpr = new IR::AbsSlice(expr, 11, 4);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = taintExpression;
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
}
{
const auto *expr = new IR::Concat(IR::Type_Bits::get(16), taintExpression, constantVar);
expr = new IR::Concat(IR::Type_Bits::get(24), taintExpression, expr);
const auto *slicedExpr = new IR::Slice(expr, 19, 12);
const auto *slicedExpr = new IR::AbsSlice(expr, 19, 12);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = taintExpression;
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
Expand All @@ -170,15 +170,15 @@ TEST_F(TaintTest, Taint06) {
{
const auto *expr = new IR::Concat(IR::Type_Bits::get(16), constantVar, taintExpression);
expr = new IR::Concat(IR::Type_Bits::get(24), expr, constantVar);
const auto *slicedExpr = new IR::Slice(expr, 11, 4);
const auto *slicedExpr = new IR::AbsSlice(expr, 11, 4);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = taintExpression;
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
}
{
const auto *expr = new IR::Concat(IR::Type_Bits::get(16), constantVar, taintExpression);
expr = new IR::Concat(IR::Type_Bits::get(24), expr, constantVar);
const auto *slicedExpr = new IR::Slice(expr, 19, 12);
const auto *slicedExpr = new IR::AbsSlice(expr, 19, 12);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = taintExpression;
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
Expand All @@ -199,17 +199,17 @@ TEST_F(TaintTest, Taint07) {
{
const auto *expr = new IR::Concat(IR::Type_Bits::get(16), taintExpression, constantVar);
expr = new IR::Concat(IR::Type_Bits::get(24), expr, taintExpression);
const auto *slicedExpr = new IR::Slice(expr, 11, 4);
slicedExpr = new IR::Slice(slicedExpr, 9, 8);
const auto *slicedExpr = new IR::AbsSlice(expr, 11, 4);
slicedExpr = new IR::AbsSlice(slicedExpr, 9, 8);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = IR::Constant::get(IR::Type_Bits::get(2), 0);
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
}
{
const auto *expr = new IR::Concat(IR::Type_Bits::get(16), constantVar, taintExpression);
expr = new IR::Concat(IR::Type_Bits::get(24), expr, taintExpression);
const auto *slicedExpr = new IR::Slice(expr, 19, 12);
slicedExpr = new IR::Slice(slicedExpr, 7, 5);
const auto *slicedExpr = new IR::AbsSlice(expr, 19, 12);
slicedExpr = new IR::AbsSlice(slicedExpr, 7, 5);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = IR::Constant::get(IR::Type_Bits::get(3), 0);
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
Expand All @@ -229,17 +229,17 @@ TEST_F(TaintTest, Taint08) {
{
const auto *expr = new IR::Concat(IR::Type_Bits::get(16), taintExpression, constantVar);
expr = new IR::Concat(IR::Type_Bits::get(24), expr, taintExpression);
const auto *slicedExpr = new IR::Slice(expr, 11, 4);
slicedExpr = new IR::Slice(slicedExpr, 4, 3);
const auto *slicedExpr = new IR::AbsSlice(expr, 11, 4);
slicedExpr = new IR::AbsSlice(slicedExpr, 4, 3);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = ToolsVariables::getTaintExpression(IR::Type_Bits::get(2));
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
}
{
const auto *expr = new IR::Concat(IR::Type_Bits::get(16), constantVar, taintExpression);
expr = new IR::Concat(IR::Type_Bits::get(24), expr, taintExpression);
const auto *slicedExpr = new IR::Slice(expr, 19, 12);
slicedExpr = new IR::Slice(slicedExpr, 2, 0);
const auto *slicedExpr = new IR::AbsSlice(expr, 19, 12);
slicedExpr = new IR::AbsSlice(slicedExpr, 2, 0);
const auto *taintedExpr = Taint::propagateTaint(slicedExpr);
const auto *expectedExpr = ToolsVariables::getTaintExpression(IR::Type_Bits::get(3));
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
Expand All @@ -258,30 +258,30 @@ TEST_F(TaintTest, Taint09) {
const auto *taint64b = ToolsVariables::getTaintExpression(IR::Type_Bits::get(64));
ASSERT_TRUE(Taint::hasTaint(taint64b));

ASSERT_TRUE(Taint::hasTaint(new IR::Slice(taint64b, 0, 0)));
ASSERT_TRUE(Taint::hasTaint(new IR::Slice(new IR::Slice(taint64b, 0, 0), 0, 0)));
ASSERT_TRUE(Taint::hasTaint(new IR::AbsSlice(taint64b, 0, 0)));
ASSERT_TRUE(Taint::hasTaint(new IR::AbsSlice(new IR::AbsSlice(taint64b, 0, 0), 0, 0)));

// 64w0 ++ taint<64>
const auto *taint128bLowerQ = new IR::Cast(IR::Type_Bits::get(128), taint64b);
ASSERT_TRUE(Taint::hasTaint(taint128bLowerQ));
ASSERT_TRUE(!Taint::hasTaint(new IR::Slice(taint128bLowerQ, 71, 64)));
ASSERT_TRUE(!Taint::hasTaint(new IR::AbsSlice(taint128bLowerQ, 71, 64)));

ASSERT_TRUE(Taint::hasTaint(new IR::Slice(taint128bLowerQ, 63, 0)));
ASSERT_TRUE(!Taint::hasTaint(new IR::Slice(taint128bLowerQ, 127, 64)));
ASSERT_TRUE(Taint::hasTaint(new IR::AbsSlice(taint128bLowerQ, 63, 0)));
ASSERT_TRUE(!Taint::hasTaint(new IR::AbsSlice(taint128bLowerQ, 127, 64)));

// 32w0 ++ taint<64> ++ 32w0
const auto *taint128bMiddleQ = new IR::Shl(taint128bLowerQ, new IR::Constant(32));
ASSERT_TRUE(!Taint::hasTaint(new IR::Slice(taint128bMiddleQ, 127, 96)));
ASSERT_TRUE(Taint::hasTaint(new IR::Slice(taint128bMiddleQ, 95, 32)));
ASSERT_TRUE(!Taint::hasTaint(new IR::Slice(taint128bMiddleQ, 31, 0)));
ASSERT_TRUE(!Taint::hasTaint(new IR::AbsSlice(taint128bMiddleQ, 127, 96)));
ASSERT_TRUE(Taint::hasTaint(new IR::AbsSlice(taint128bMiddleQ, 95, 32)));
ASSERT_TRUE(!Taint::hasTaint(new IR::AbsSlice(taint128bMiddleQ, 31, 0)));

// (32w0 ++ Taint64b ++ 32w0) & 128w0
// The bitwise and should not have any effect on taint.
const auto *taint128bMiddleQ2 =
new IR::BAnd(taint128bMiddleQ, IR::Constant::get(IR::Type::Bits::get(128), 0));
ASSERT_TRUE(!Taint::hasTaint(new IR::Slice(taint128bMiddleQ2, 127, 96)));
ASSERT_TRUE(Taint::hasTaint(new IR::Slice(taint128bMiddleQ2, 95, 32)));
ASSERT_TRUE(!Taint::hasTaint(new IR::Slice(taint128bMiddleQ2, 31, 0)));
ASSERT_TRUE(!Taint::hasTaint(new IR::AbsSlice(taint128bMiddleQ2, 127, 96)));
ASSERT_TRUE(Taint::hasTaint(new IR::AbsSlice(taint128bMiddleQ2, 95, 32)));
ASSERT_TRUE(!Taint::hasTaint(new IR::AbsSlice(taint128bMiddleQ2, 31, 0)));
}

/// Check that taint propagation is not too aggressive.
Expand All @@ -293,7 +293,7 @@ TEST_F(TaintTest, Taint10) {
{
const auto *constantVar1 = IR::Constant::get(typeBits, 2);
const auto *constantVar2 = IR::Constant::get(typeBits, 2);
const auto *expr = new IR::Slice(new IR::Add(constantVar1, constantVar2), 3, 0);
const auto *expr = new IR::AbsSlice(new IR::Add(constantVar1, constantVar2), 3, 0);
const auto *taintedExpr = Taint::propagateTaint(expr);
const auto *expectedExpr = IR::Constant::get(IR::Type_Bits::get(4), 0);
ASSERT_TRUE(taintedExpr->equiv(*expectedExpr));
Expand Down
47 changes: 46 additions & 1 deletion frontends/common/constantFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ static bool overflowWidth(const IR::Node *node, int width) {
return false;
}

const IR::Node *DoConstantFolding::postorder(IR::Slice *e) {
const IR::Node *DoConstantFolding::postorder(IR::AbsSlice *e) {
const IR::Expression *msb = getConstant(e->e1);
const IR::Expression *lsb = getConstant(e->e2);
if (msb == nullptr) {
Expand Down 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
3 changes: 2 additions & 1 deletion frontends/common/constantFolding.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ class DoConstantFolding : public Transform, public ResolutionContext {
const IR::Node *postorder(IR::LNot *e) override;
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::AbsSlice *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
Loading

0 comments on commit 7ad797d

Please sign in to comment.