-
Notifications
You must be signed in to change notification settings - Fork 4
Use generated exprs to test expression evaluation against smt solver #499
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
399b540
bdb1f16
a31fd98
f6024d5
501aedd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| package test_util | ||
| import ir.* | ||
| import org.scalacheck.Gen | ||
|
|
||
| object ExprGen { | ||
|
|
||
| def arbBinOp = | ||
| Gen.oneOf( | ||
| BVAND, | ||
| BVOR, | ||
| BVADD, | ||
| BVMUL, | ||
| BVSHL, | ||
| BVLSHR, | ||
| BVNAND, | ||
| BVNOR, | ||
| BVXOR, | ||
| BVXNOR, | ||
| BVSUB, | ||
| BVASHR, // broken | ||
| BVUREM, // broken | ||
| BVSREM, // broken | ||
| BVSMOD, // broken | ||
| BVUDIV, // broken | ||
| BVSDIV // broken | ||
| ) | ||
|
|
||
| def arbBinComp = Gen.oneOf(BVULE, BVUGT, BVULT, BVUGE, BVSLT, BVSLE, BVSGT, BVSGE, EQ, NEQ, BVCOMP) | ||
|
|
||
| def genValue(givenSize: Option[Int] = None) = for { | ||
| genSize <- Gen.chooseNum(1, 70) | ||
| size = givenSize.getOrElse(genSize) | ||
| maxVal = BitVecType(size).maxValue | ||
| value <- Gen.chooseNum(BigInt(0), maxVal) | ||
| } yield (BitVecLiteral(value, size)) | ||
|
|
||
| def genUnExp(size: Option[Int] = None) = for { | ||
| v <- genValue(size) | ||
| op <- Gen.oneOf(BVNOT, BVNEG) | ||
| } yield (UnaryExpr(op, v)) | ||
|
|
||
| def genExt(givenSize: Option[Int] = None) = | ||
| if givenSize.exists(_ < 1) then { | ||
| genValue(givenSize) | ||
| } else | ||
| for { | ||
| genSize <- Gen.chooseNum(1, 70) | ||
| size = givenSize.getOrElse(genSize) | ||
| amount <- Gen.chooseNum(0, size - 1) | ||
| sizeLeft = size - amount | ||
| v <- if (sizeLeft > 1) then genExpr(Some(sizeLeft)) else genValue(Some(sizeLeft)) | ||
| vv <- genExpr(Some(amount)) | ||
| op <- Gen.oneOf(ZeroExtend(amount, v), SignExtend(amount, v), BinaryExpr(BVCONCAT, v, vv)) | ||
| } yield (op) | ||
|
|
||
| def genBinComp(depthLimit: Int) = for { | ||
| op <- arbBinComp | ||
| genSize <- Gen.chooseNum(1, 70) | ||
| l <- genExpr(Some(genSize), depthLimit) | ||
| r <- genExpr(Some(genSize), depthLimit) | ||
| } yield (BinaryExpr(op, l, r)) | ||
|
|
||
| def genBinExp(givenSize: Option[Int] = None, depthLimit: Int): Gen[Expr] = { | ||
| def genBV(min: BigInt, max: BigInt, size: Int) = for { | ||
| v <- Gen.chooseNum(min, max) | ||
| } yield BitVecLiteral(v, size) | ||
| for { | ||
| genSize <- Gen.chooseNum(1, 70) | ||
| size = givenSize.getOrElse(genSize) | ||
| op <- Gen.oneOf(arbBinOp, arbBinComp) | ||
| maxVal = (BigInt(2).pow(size) - 1) | ||
| smallMax = maxVal.min(255) | ||
| rhs <- op match { | ||
| case BVSDIV => genBV(BigInt(1), maxVal, size) | ||
| case BVUDIV => genBV(BigInt(1), maxVal, size) | ||
| case BVSREM => genBV(BigInt(1), maxVal, size) | ||
| case BVSMOD => genBV(BigInt(1), maxVal, size) | ||
| case BVSHL => genBV(BigInt(0), smallMax, size) | ||
| case BVLSHR => genBV(BigInt(0), smallMax, size) | ||
| case BVASHR => genBV(BigInt(0), smallMax, size) | ||
| case _ => genExpr(Some(size), depthLimit) | ||
| } | ||
| lhs <- genExpr(Some(size), depthLimit) | ||
| expr = BinaryExpr(op, lhs, rhs) | ||
| nexpr <- expr.getType match { | ||
| case BoolType if size != 1 => | ||
| Gen.oneOf(ZeroExtend(size - 1, UnaryExpr(BoolToBV1, expr)), SignExtend(size - 1, UnaryExpr(BoolToBV1, expr))) | ||
| case BoolType => Gen.const(UnaryExpr(BoolToBV1, expr)) | ||
| case BitVecType(bvsz) if size > bvsz => Gen.oneOf(ZeroExtend(size - bvsz, expr), SignExtend(size - bvsz, expr)) | ||
| case BitVecType(sz) if size == sz => Gen.const(expr) | ||
| case x => throw Exception(s"TYPE $x DOES NOT MATCH EXPECTED $size $expr") | ||
| } | ||
| // rhs <- Gen.chooseNum(BigInt(minBound), (BigInt(2).pow(sizeRhs) - 1)) | ||
| } yield nexpr | ||
| } | ||
|
|
||
| def genExpr(size: Option[Int] = None, depthLimit: Int = 10): Gen[Expr] = | ||
| if (size.exists(_ <= 1) || depthLimit <= 0) then genValue(size) | ||
| else Gen.oneOf(genBinExp(size, depthLimit - 1), genUnExp(size), genValue(size)) | ||
|
|
||
| def genNonLiteralExpr(size: Option[Int] = None, depthLimit: Int = 3): Gen[Expr] = | ||
| if (size.exists(_ <= 1)) then genValue(size) else Gen.oneOf(genBinExp(size, depthLimit), genUnExp(size)) | ||
|
Comment on lines
+97
to
+102
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ik it's not new in this pr, but what is this condition on
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its ugly but its because you can reliably generate width 1 bitvectors but the other options need more careful consideration as they sometimes try and partition it down further, e.g. bvconcat. I just didnt bother dealing with each possible leaf needed for the other cases. note size is option |
||
|
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use
.map. Options can be++-ed onto a sequence and they act like a sequence of zero or one items.