summaryrefslogtreecommitdiff
path: root/chapter14
diff options
context:
space:
mode:
Diffstat (limited to 'chapter14')
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java9
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/type/TypeInteger.java19
-rw-r--r--chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java13
3 files changed, 38 insertions, 3 deletions
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java
index f4933d9c..91bb13db 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java
@@ -21,10 +21,13 @@ public class AndNode extends Node {
@Override
public Type compute() {
- if (in(1)._type instanceof TypeInteger i0 &&
- in(2)._type instanceof TypeInteger i1) {
- if (i0.isConstant() && i1.isConstant())
+ if( in(1)._type instanceof TypeInteger i0 &&
+ in(2)._type instanceof TypeInteger i1 ) {
+ if( i0.isConstant() && i1.isConstant() )
return TypeInteger.constant(i0.value()&i1.value());
+ // Sharpen allowed bits if either value is narrowed
+ long mask = i0.mask() & i1.mask();
+ return mask < 0 ? TypeInteger.BOT : TypeInteger.make(0,mask);
}
return TypeInteger.BOT;
}
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/type/TypeInteger.java b/chapter14/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
index 403cc7bf..aca3e06b 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
@@ -77,6 +77,25 @@ public class TypeInteger extends Type {
public long value() { assert isConstant(); return _min; }
+ // AND-mask of forced zeros. e.g. unsigned types will return their mask;
+ // u8 will return 0xFF. But also a range of 16-18 (0x10-0x12) will return
+ // 0x13 - no value in the range {16,17,18} will allow bit 0x04 to be set.
+ public long mask() {
+ if( isHigh() ) return 0;
+ if( isConstant() ) return _min;
+ //if( _min<0 ) return -1L;
+ //if( _max==Long.MAX_VALUE ) return -1L;
+ // Those bit positions which differ min to max
+ long x = _min ^ _max;
+ // Highest '1' bit in the differ set. Since the range is from min to
+ // max, all values below here are possible.
+ long ff1 = Long.highestOneBit(x);
+ // Make a all-1's mask from ff1, and set over the same bits (either min
+ // or max is ok).
+ long mask = _min | (ff1-1) | ff1;
+ return mask;
+ }
+
@Override
public Type xmeet(Type other) {
// Invariant from caller: 'this' != 'other' and same class (TypeInteger)
diff --git a/chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java b/chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java
index 682eff15..8b3c3c9a 100644
--- a/chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java
+++ b/chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java
@@ -49,6 +49,19 @@ return b;
assertEquals(67L, Evaluator.evaluate(stop, 0));
}
+
+ @Test
+ public void testU8While() {
+ Parser parser = new Parser(
+"""
+u8 b = 123;
+while( b ) b = b + 456;// Truncate
+return b;
+""");
+ StopNode stop = parser.parse(false).iterate(false);
+ assertEquals("return Phi(Loop9,123,((Phi_b+456)&255));", stop.toString());
+ }
+
@Test
public void testU1() {
Parser parser = new Parser(