summaryrefslogtreecommitdiff
path: root/chapter14/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'chapter14/src/main/java')
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/Parser.java46
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java57
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/Node.java6
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/type/TypeFloat.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/type/TypeInteger.java13
5 files changed, 108 insertions, 16 deletions
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/Parser.java b/chapter14/src/main/java/com/seaofnodes/simple/Parser.java
index 032b4867..de5565ab 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/Parser.java
@@ -52,7 +52,9 @@ public class Parser {
* List of keywords disallowed as identifiers
*/
private static final HashSet<String> KEYWORDS = new HashSet<>(){{
+ add("bool");
add("break");
+ add("byte");
add("continue");
add("else");
add("false");
@@ -64,8 +66,11 @@ public class Parser {
add("return");
add("struct");
add("true");
- add("while");
+ add("u1");
+ add("u16");
+ add("u32");
add("u8");
+ add("while");
}};
@@ -85,9 +90,14 @@ public class Parser {
Node.reset();
IterPeeps.reset();
TYPES.clear();
- TYPES.put("int",TypeInteger.BOT);
- //TYPES.put("u8" ,TypeInteger.U8 );
- TYPES.put("flt",TypeFloat .BOT);
+ TYPES.put("bool",TypeInteger.U1 );
+ TYPES.put("byte",TypeInteger.U8 );
+ TYPES.put("flt" ,TypeFloat .BOT);
+ TYPES.put("int" ,TypeInteger.BOT);
+ TYPES.put("u1" ,TypeInteger.U1 );
+ TYPES.put("u8" ,TypeInteger.U8 );
+ TYPES.put("u16" ,TypeInteger.U16);
+ TYPES.put("u32" ,TypeInteger.U32);
SCHEDULED = false;
_lexer = new Lexer(source);
_scope = new ScopeNode();
@@ -435,6 +445,9 @@ public class Parser {
// Auto-widen int to float
if( expr._type instanceof TypeInteger && t instanceof TypeFloat )
expr = new ToFloatNode(expr).peephole();
+ // Auto-narrow wide ints to narrow ints
+ if( expr._type instanceof TypeInteger e0 && t instanceof TypeInteger t0 && !e0.isa(t) )
+ expr = new AndNode(expr,new ConstantNode(TypeInteger.constant(t0._max-t0._min)).peephole()).peephole();
// Auto-deepen forward ref types
Type e = expr._type;
if( e instanceof TypeMemPtr tmp && tmp._obj._fields==null )
@@ -476,7 +489,27 @@ public class Parser {
* </pre>
* @return an expression {@link Node}, never {@code null}
*/
- private Node parseExpression() { return parseComparison(); }
+ private Node parseExpression() { return parseBitwise(); }
+
+ /**
+ * Parse an bitwise expression
+ *
+ * <pre>
+ * bitwise : compareExpr (('&' | '|' | '^') compareExpr)*
+ * </pre>
+ * @return a bitwise expression {@link Node}, never {@code null}
+ */
+ private Node parseBitwise() {
+ Node lhs = parseComparison();
+ while( true ) {
+ if( false ) ;
+ else if( match("&") ) lhs = new AndNode(lhs,null);
+ else break;
+ lhs.setDef(2,parseComparison());
+ lhs = lhs.peephole();
+ }
+ return lhs;
+ }
/**
* Parse an expression of the form:
@@ -640,6 +673,9 @@ public class Parser {
else {
Node val = parseExpression();
Type glb = base._fields[idx]._type;
+ // Auto-truncate when storing to narrow fields
+ if( !val._type.isa(glb) && glb instanceof TypeInteger t0)
+ val = new AndNode(val,new ConstantNode(TypeInteger.constant(t0._max-t0._min)).peephole()).peephole();
memAlias(alias, new StoreNode(name, alias,glb, memAlias(alias), expr, val, false).peephole());
return expr; // "obj.a = expr" returns the expression while updating memory
}
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java
new file mode 100644
index 00000000..1a3995d4
--- /dev/null
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java
@@ -0,0 +1,57 @@
+package com.seaofnodes.simple.node;
+
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+
+import java.util.BitSet;
+
+public class AndNode extends Node {
+ public AndNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
+
+ @Override public String label() { return "And"; }
+
+ @Override public String glabel() { return "&"; }
+
+ @Override
+ StringBuilder _print1(StringBuilder sb, BitSet visited) {
+ in(1)._print0(sb.append("("), visited);
+ in(2)._print0(sb.append("&"), visited);
+ return sb.append(")");
+ }
+
+ @Override
+ public Type compute() {
+ 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());
+ }
+ return TypeInteger.BOT;
+ }
+
+ @Override
+ public Node idealize() {
+ Node lhs = in(1);
+ Node rhs = in(2);
+ Type t1 = lhs._type;
+ Type t2 = rhs._type;
+
+ // And of -1. We do not check for (0&x) because this will already
+ // canonicalize to (x&0)
+ if ( t2.isConstant() && t2 instanceof TypeInteger i && i.value()==-1 )
+ return rhs;
+
+ // Move constants to RHS: con*arg becomes arg*con
+ if ( t1.isConstant() && !t2.isConstant() )
+ return swap12();
+
+ // Do we have ((x & (phi cons)) & con) ?
+ // Do we have ((x & (phi cons)) & (phi cons)) ?
+ // Push constant up through the phi: x & (phi con0&con0 con1&con1...)
+ Node phicon = AddNode.phiCon(this,true);
+ if( phicon!=null ) return phicon;
+
+ return null;
+ }
+ @Override Node copy(Node lhs, Node rhs) { return new AndNode(lhs,rhs); }
+}
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter14/src/main/java/com/seaofnodes/simple/node/Node.java
index d846fcef..382f78ae 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/Node.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/Node.java
@@ -93,10 +93,8 @@ public abstract class Node implements OutNode {
@Override
public final String toString() { return print(); }
- // This is a *deep* print. This version will fail on cycles, which we will
- // correct later when we can parse programs with loops. We print with a
- // tik-tok style; the common _print0 calls the per-Node _print1, which
- // calls back to _print0;
+ // This is a *deep* print. We print with a tik-tok style; the common
+ // _print0 calls the per-Node _print1, which calls back to _print0;
public final String print() {
return _print0(new StringBuilder(), new BitSet()).toString();
}
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/type/TypeFloat.java b/chapter14/src/main/java/com/seaofnodes/simple/type/TypeFloat.java
index 0932a202..f40c7480 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/type/TypeFloat.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/type/TypeFloat.java
@@ -54,7 +54,7 @@ public class TypeFloat extends Type {
public StringBuilder typeName(StringBuilder sb) {
if( this==TOP ) return sb.append("FltTop");
if( this==BOT ) return sb.append("FltBot");
- return sb.append("Int");
+ return sb.append("Flt");
}
@Override public boolean isHigh() { return this==TOP; }
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 d3f9b66e..c84a4c13 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
@@ -15,6 +15,8 @@ public class TypeInteger extends Type {
public final static TypeInteger FALSE=ZERO;
public final static TypeInteger TRUE= make(1,1);
public final static TypeInteger U8 = make(0,255);
+ public final static TypeInteger U16 = make(0,65535);
+ public final static TypeInteger U32 = make(0,(1L<<32)-1);
/**
* Describes an integer *range* - everything from min to max; both min and
@@ -39,16 +41,15 @@ public class TypeInteger extends Type {
// FIXME this display format is problematic
// In visualizer '#' gets prepended if its a constant
@Override
- public StringBuilder print(StringBuilder sb) {
- if( this==TOP ) return sb.append("IntTop");
- if( this==BOT ) return sb.append("IntBot");
- if( isConstant() ) return sb.append(_min);
- return sb.append("[").append(_min).append("-").append(_max).append("]");
- }
+ public StringBuilder print(StringBuilder sb) { return sb.append(str()); }
@Override public String str() {
if( this==TOP ) return "~int";
if( this==BOT ) return "int";
+ if( this==BOOL) return ("bool");
+ if( this==U8 ) return ("u8");
+ if( this==U16 ) return ("u16");
+ if( this==U32 ) return ("u32");
if( isConstant() ) return ""+_min;
return "["+_min+"-"+_max+"]";
}