Skip to content

Commit aafb6d8

Browse files
authored
Merge pull request #62 from ftsrg/bitvector-extras
Additional bitvector operations
2 parents d4519c9 + 001d25b commit aafb6d8

File tree

25 files changed

+813
-331
lines changed

25 files changed

+813
-331
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ buildscript {
1010

1111
allprojects {
1212
group = "hu.bme.mit.inf.theta"
13-
version = "1.4.2"
13+
version = "1.4.3"
1414

1515
apply(from = rootDir.resolve("gradle/shared-with-buildSrc/mirrors.gradle.kts"))
1616
}

subprojects/cfa/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ Expressions of the CFA include the following.
5151
- Arithmetic, e.g., `+`, `-`, `/`, `*`, `mod`, `rem`.
5252
- Conditional: `if . then . else .`
5353
- Array read (`a[i]`) and write (`a[i <- v]`).
54-
- Bitvector specific operators, e.g., `&`, `|`, `^`, `<<`, `>>`, `~`. _This is an experimental feature with currently limited algorithmic support. See the [details](doc/bitvectors.md) for more information._
54+
- Bitvector specific operators, e.g., `&`, `|`, `^`, `<<`, `>>`, `>>>`, `<<~`, `~>>`, `~`. _This is an experimental feature with currently limited algorithmic support. See the [details](doc/bitvectors.md) for more information._
5555

5656
### Textual representation (DSL)
5757

subprojects/cfa/doc/bitvectors.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,11 @@ These operations are specific to bitvectors only. These operations require that
8181
- **Bitwise and**: Ands two bitvectors; `a & b`
8282
- **Bitwise or**: Ors two bitvectors; `a | b`
8383
- **Bitwise xor**: XORs two bitvectors; `a ^ b`
84-
- **Bitwise shift left**: Shifts a to left with b; `a << b`
85-
- **Bitwise shift right**: Shifts a to right with b; `a >> b`
84+
- **Bitwise shift left**: Shifts *a* to the left with *b*; `a << b`
85+
- **Bitwise arithmetic shift right**: Shifts *a* arithmetically to the right with *b*; `a >> b`
86+
- **Bitwise logical shift right**: Shifts *a* logically to the right with *b*; `a >>> b`
87+
- **Bitwise rotate left**: Rotates *a* to the left with *b*; `a <<~ b`
88+
- **Bitwise rotate right**: Rotates *a* to the right with *b*; `a ~>> b`
8689
- **Bitwise not:** Negates all the bits in bitvectors; `~a`
8790

8891
### Relational operations

subprojects/cfa/src/main/antlr/CfaDsl.g4

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ bitwiseAndExpr
223223
;
224224

225225
bitwiseShiftExpr
226-
: leftOp=additiveExpr (oper=(BITWISE_SHIFT_LEFT | BITWISE_SHIFT_RIGHT) rightOp=additiveExpr)?
226+
: leftOp=additiveExpr (oper=(BITWISE_SHIFT_LEFT | BITWISE_ARITH_SHIFT_RIGHT | BITWISE_LOGIC_SHIFT_RIGHT | BITWISE_ROTATE_LEFT | BITWISE_ROTATE_RIGHT) rightOp=additiveExpr)?
227227
;
228228

229229
additiveExpr
@@ -410,10 +410,22 @@ BITWISE_SHIFT_LEFT
410410
: LT LT
411411
;
412412

413-
BITWISE_SHIFT_RIGHT
413+
BITWISE_ARITH_SHIFT_RIGHT
414414
: GT GT
415415
;
416416

417+
BITWISE_LOGIC_SHIFT_RIGHT
418+
: GT GT GT
419+
;
420+
421+
BITWISE_ROTATE_LEFT
422+
: LT LT BITWISE_NOT
423+
;
424+
425+
BITWISE_ROTATE_RIGHT
426+
: BITWISE_NOT GT GT
427+
;
428+
417429
BITWISE_NOT
418430
: '~'
419431
;

subprojects/cfa/src/main/java/hu/bme/mit/theta/cfa/dsl/CfaExpression.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,8 +366,14 @@ public Expr<?> visitBitwiseShiftExpr(final BitwiseShiftExprContext ctx) {
366366
switch (ctx.oper.getType()) {
367367
case BITWISE_SHIFT_LEFT:
368368
return BvExprs.ShiftLeft(leftOp, rightOp);
369-
case BITWISE_SHIFT_RIGHT:
370-
return BvExprs.ShiftRight(leftOp, rightOp);
369+
case BITWISE_ARITH_SHIFT_RIGHT:
370+
return BvExprs.ArithShiftRight(leftOp, rightOp);
371+
case BITWISE_LOGIC_SHIFT_RIGHT:
372+
return BvExprs.LogicShiftRight(leftOp, rightOp);
373+
case BITWISE_ROTATE_LEFT:
374+
return BvExprs.RotateLeft(leftOp, rightOp);
375+
case BITWISE_ROTATE_RIGHT:
376+
return BvExprs.RotateRight(leftOp, rightOp);
371377
default:
372378
throw new AssertionError();
373379
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
main process cfa {
2+
var x : bv[4]
3+
4+
init loc L0
5+
loc L1
6+
loc L2
7+
loc L3
8+
final loc END
9+
error loc ERR
10+
11+
L0 -> L1 { x := 4'b0001 ~>> 4'd1 }
12+
L1 -> L2 { assume x = 4'b1000 }
13+
L1 -> ERR { assume not (x = 4'b1000) }
14+
L2 -> L3 { x := (x >> 4'd1) >>> 4'd1 }
15+
L3 -> END { assume x = 4'b0110 }
16+
L3 -> ERR { assume not (x = 4'b0110) }
17+
}

subprojects/core/src/main/antlr/CoreDsl.g4

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ bitwiseAndExpr
171171
;
172172

173173
bitwiseShiftExpr
174-
: leftOp=additiveExpr (oper=(BITWISE_SHIFT_LEFT | BITWISE_SHIFT_RIGHT) rightOp=additiveExpr)?
174+
: leftOp=additiveExpr (oper=(BITWISE_SHIFT_LEFT | BITWISE_ARITH_SHIFT_RIGHT | BITWISE_LOGIC_SHIFT_RIGHT | BITWISE_ROTATE_LEFT | BITWISE_ROTATE_RIGHT) rightOp=additiveExpr)?
175175
;
176176

177177
additiveExpr
@@ -344,10 +344,22 @@ BITWISE_SHIFT_LEFT
344344
: LT LT
345345
;
346346

347-
BITWISE_SHIFT_RIGHT
347+
BITWISE_ARITH_SHIFT_RIGHT
348348
: GT GT
349349
;
350350

351+
BITWISE_LOGIC_SHIFT_RIGHT
352+
: GT GT GT
353+
;
354+
355+
BITWISE_ROTATE_LEFT
356+
: LT LT BITWISE_NOT
357+
;
358+
359+
BITWISE_ROTATE_RIGHT
360+
: BITWISE_NOT GT GT
361+
;
362+
351363
BITWISE_NOT
352364
: '~'
353365
;

subprojects/core/src/main/java/hu/bme/mit/theta/core/dsl/impl/ExprCreatorVisitor.java

Lines changed: 87 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static com.google.common.base.Preconditions.checkState;
2121
import static hu.bme.mit.theta.common.Utils.singleElementOf;
2222
import static hu.bme.mit.theta.core.decl.Decls.Param;
23+
import static hu.bme.mit.theta.core.dsl.gen.CoreDslParser.*;
2324
import static hu.bme.mit.theta.core.type.abstracttype.AbstractExprs.Add;
2425
import static hu.bme.mit.theta.core.type.abstracttype.AbstractExprs.Div;
2526
import static hu.bme.mit.theta.core.type.abstracttype.AbstractExprs.Eq;
@@ -47,13 +48,17 @@
4748
import static hu.bme.mit.theta.core.type.inttype.IntExprs.Mod;
4849
import static hu.bme.mit.theta.core.type.inttype.IntExprs.Rem;
4950
import static hu.bme.mit.theta.core.type.rattype.RatExprs.Rat;
51+
import static hu.bme.mit.theta.core.utils.TypeUtils.castBv;
5052
import static java.util.stream.Collectors.toList;
5153

5254
import java.util.Collection;
5355
import java.util.Collections;
5456
import java.util.List;
5557
import java.util.stream.Stream;
5658

59+
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.*;
60+
import hu.bme.mit.theta.core.type.bvtype.BvExprs;
61+
import hu.bme.mit.theta.core.type.bvtype.BvType;
5762
import org.antlr.v4.runtime.Token;
5863

5964
import com.google.common.collect.ImmutableList;
@@ -66,31 +71,6 @@
6671
import hu.bme.mit.theta.core.dsl.DeclSymbol;
6772
import hu.bme.mit.theta.core.dsl.gen.CoreDslBaseVisitor;
6873
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser;
69-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.AccessContext;
70-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.AccessorExprContext;
71-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.AdditiveExprContext;
72-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.AndExprContext;
73-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.ArrayAccessContext;
74-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.DeclListContext;
75-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.EqualityExprContext;
76-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.ExistsExprContext;
77-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.FalseExprContext;
78-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.ForallExprContext;
79-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.FuncAccessContext;
80-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.FuncLitExprContext;
81-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.IdExprContext;
82-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.IffExprContext;
83-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.ImplyExprContext;
84-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.IntLitExprContext;
85-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.IteExprContext;
86-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.MultiplicativeExprContext;
87-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.NegExprContext;
88-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.NotExprContext;
89-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.OrExprContext;
90-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.ParenExprContext;
91-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.RatLitExprContext;
92-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.RelationExprContext;
93-
import hu.bme.mit.theta.core.dsl.gen.CoreDslParser.TrueExprContext;
9474
import hu.bme.mit.theta.core.type.Expr;
9575
import hu.bme.mit.theta.core.type.Type;
9676
import hu.bme.mit.theta.core.type.abstracttype.AddExpr;
@@ -308,6 +288,88 @@ public Expr<?> visitRelationExpr(final RelationExprContext ctx) {
308288

309289
////
310290

291+
@Override
292+
public Expr<?> visitBitwiseOrExpr(final BitwiseOrExprContext ctx) {
293+
if (ctx.rightOp != null) {
294+
final Expr<BvType> leftOp = castBv(ctx.leftOp.accept(this));
295+
final Expr<BvType> rightOp = castBv(ctx.rightOp.accept(this));
296+
297+
switch (ctx.oper.getType()) {
298+
case BITWISE_OR:
299+
return BvExprs.Or(List.of(leftOp, rightOp));
300+
default:
301+
throw new AssertionError();
302+
}
303+
304+
} else {
305+
return visitChildren(ctx);
306+
}
307+
}
308+
309+
@Override
310+
public Expr<?> visitBitwiseXorExpr(final BitwiseXorExprContext ctx) {
311+
if (ctx.rightOp != null) {
312+
final Expr<BvType> leftOp = castBv(ctx.leftOp.accept(this));
313+
final Expr<BvType> rightOp = castBv(ctx.rightOp.accept(this));
314+
315+
switch (ctx.oper.getType()) {
316+
case BITWISE_XOR:
317+
return BvExprs.Xor(List.of(leftOp, rightOp));
318+
default:
319+
throw new AssertionError();
320+
}
321+
322+
} else {
323+
return visitChildren(ctx);
324+
}
325+
}
326+
327+
@Override
328+
public Expr<?> visitBitwiseAndExpr(final BitwiseAndExprContext ctx) {
329+
if (ctx.rightOp != null) {
330+
final Expr<BvType> leftOp = castBv(ctx.leftOp.accept(this));
331+
final Expr<BvType> rightOp = castBv(ctx.rightOp.accept(this));
332+
333+
switch (ctx.oper.getType()) {
334+
case BITWISE_AND:
335+
return BvExprs.And(List.of(leftOp, rightOp));
336+
default:
337+
throw new AssertionError();
338+
}
339+
340+
} else {
341+
return visitChildren(ctx);
342+
}
343+
}
344+
345+
@Override
346+
public Expr<?> visitBitwiseShiftExpr(final BitwiseShiftExprContext ctx) {
347+
if (ctx.rightOp != null) {
348+
final Expr<BvType> leftOp = castBv(ctx.leftOp.accept(this));
349+
final Expr<BvType> rightOp = castBv(ctx.rightOp.accept(this));
350+
351+
switch (ctx.oper.getType()) {
352+
case BITWISE_SHIFT_LEFT:
353+
return BvExprs.ShiftLeft(leftOp, rightOp);
354+
case BITWISE_ARITH_SHIFT_RIGHT:
355+
return BvExprs.ArithShiftRight(leftOp, rightOp);
356+
case BITWISE_LOGIC_SHIFT_RIGHT:
357+
return BvExprs.LogicShiftRight(leftOp, rightOp);
358+
case BITWISE_ROTATE_LEFT:
359+
return BvExprs.RotateLeft(leftOp, rightOp);
360+
case BITWISE_ROTATE_RIGHT:
361+
return BvExprs.RotateRight(leftOp, rightOp);
362+
default:
363+
throw new AssertionError();
364+
}
365+
366+
} else {
367+
return visitChildren(ctx);
368+
}
369+
}
370+
371+
////
372+
311373
@Override
312374
public Expr<?> visitAdditiveExpr(final AdditiveExprContext ctx) {
313375
if (ctx.ops.size() > 1) {

subprojects/core/src/main/java/hu/bme/mit/theta/core/type/bvtype/BvShiftRightExpr.java renamed to subprojects/core/src/main/java/hu/bme/mit/theta/core/type/bvtype/BvArithShiftRightExpr.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,23 @@
66

77
import static hu.bme.mit.theta.core.utils.TypeUtils.*;
88

9-
public class BvShiftRightExpr extends BinaryExpr<BvType, BvType> {
9+
public class BvArithShiftRightExpr extends BinaryExpr<BvType, BvType> {
1010
private static final int HASH_SEED = 965;
1111
private static final String OPERATOR_LABEL = ">>";
1212

13-
private BvShiftRightExpr(final Expr<BvType> leftOp, final Expr<BvType> rightOp) {
13+
private BvArithShiftRightExpr(final Expr<BvType> leftOp, final Expr<BvType> rightOp) {
1414
super(leftOp, rightOp);
1515
checkAllTypesEqual(leftOp, rightOp);
1616
}
1717

18-
public static BvShiftRightExpr of(final Expr<BvType> leftOp, final Expr<BvType> rightOp) {
19-
return new BvShiftRightExpr(leftOp, rightOp);
18+
public static BvArithShiftRightExpr of(final Expr<BvType> leftOp, final Expr<BvType> rightOp) {
19+
return new BvArithShiftRightExpr(leftOp, rightOp);
2020
}
2121

22-
public static BvShiftRightExpr create(final Expr<?> leftOp, final Expr<?> rightOp) {
22+
public static BvArithShiftRightExpr create(final Expr<?> leftOp, final Expr<?> rightOp) {
2323
final Expr<BvType> newLeftOp = castBv(leftOp);
2424
final Expr<BvType> newRightOp = castBv(rightOp);
25-
return BvShiftRightExpr.of(newLeftOp, newRightOp);
25+
return BvArithShiftRightExpr.of(newLeftOp, newRightOp);
2626
}
2727

2828
@Override
@@ -34,34 +34,34 @@ public BvType getType() {
3434
public BvLitExpr eval(final Valuation val) {
3535
final BvLitExpr leftOpVal = (BvLitExpr) getLeftOp().eval(val);
3636
final BvLitExpr rightOpVal = (BvLitExpr) getRightOp().eval(val);
37-
return leftOpVal.shiftRight(rightOpVal);
37+
return leftOpVal.arithShiftRight(rightOpVal);
3838
}
3939

4040
@Override
41-
public BvShiftRightExpr with(final Expr<BvType> leftOp, final Expr<BvType> rightOp) {
41+
public BvArithShiftRightExpr with(final Expr<BvType> leftOp, final Expr<BvType> rightOp) {
4242
if (leftOp == getLeftOp() && rightOp == getRightOp()) {
4343
return this;
4444
} else {
45-
return BvShiftRightExpr.of(leftOp, rightOp);
45+
return BvArithShiftRightExpr.of(leftOp, rightOp);
4646
}
4747
}
4848

4949
@Override
50-
public BvShiftRightExpr withLeftOp(final Expr<BvType> leftOp) {
50+
public BvArithShiftRightExpr withLeftOp(final Expr<BvType> leftOp) {
5151
return with(leftOp, getRightOp());
5252
}
5353

5454
@Override
55-
public BvShiftRightExpr withRightOp(final Expr<BvType> rightOp) {
55+
public BvArithShiftRightExpr withRightOp(final Expr<BvType> rightOp) {
5656
return with(getLeftOp(), rightOp);
5757
}
5858

5959
@Override
6060
public boolean equals(final Object obj) {
6161
if (this == obj) {
6262
return true;
63-
} else if (obj instanceof BvShiftRightExpr) {
64-
final BvShiftRightExpr that = (BvShiftRightExpr) obj;
63+
} else if (obj instanceof BvArithShiftRightExpr) {
64+
final BvArithShiftRightExpr that = (BvArithShiftRightExpr) obj;
6565
return this.getLeftOp().equals(that.getLeftOp()) && this.getRightOp().equals(that.getRightOp());
6666
} else {
6767
return false;

subprojects/core/src/main/java/hu/bme/mit/theta/core/type/bvtype/BvExprs.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,20 @@ public static BvShiftLeftExpr ShiftLeft(final Expr<BvType> leftOp, final Expr<Bv
6666
return BvShiftLeftExpr.of(leftOp, rightOp);
6767
}
6868

69-
public static BvShiftRightExpr ShiftRight(final Expr<BvType> leftOp, final Expr<BvType> rightOp) {
70-
return BvShiftRightExpr.of(leftOp, rightOp);
69+
public static BvArithShiftRightExpr ArithShiftRight(final Expr<BvType> leftOp, final Expr<BvType> rightOp) {
70+
return BvArithShiftRightExpr.of(leftOp, rightOp);
71+
}
72+
73+
public static BvLogicShiftRightExpr LogicShiftRight(final Expr<BvType> leftOp, final Expr<BvType> rightOp) {
74+
return BvLogicShiftRightExpr.of(leftOp, rightOp);
75+
}
76+
77+
public static BvRotateLeftExpr RotateLeft(final Expr<BvType> leftOp, final Expr<BvType> rightOp) {
78+
return BvRotateLeftExpr.of(leftOp, rightOp);
79+
}
80+
81+
public static BvRotateRightExpr RotateRight(final Expr<BvType> leftOp, final Expr<BvType> rightOp) {
82+
return BvRotateRightExpr.of(leftOp, rightOp);
7183
}
7284

7385
public static BvEqExpr Eq(final Expr<BvType> leftOp, final Expr<BvType> rightOp) {

0 commit comments

Comments
 (0)