summaryrefslogtreecommitdiff
path: root/chapter14/src/main/java/com/seaofnodes
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2024-09-07 09:22:29 -0700
committerThalia Archibald <thalia@archibald.dev>2024-09-07 10:54:48 -0700
commiteccda096c2e8e30f76e4c4a21421243159cd9026 (patch)
treed94f7ba3f46cd2c877e000d260406d084d27fb6f /chapter14/src/main/java/com/seaofnodes
parent22a129078b27d5244fac5bddd44a1b50cbb79839 (diff)
downloadSimple-eccda096c2e8e30f76e4c4a21421243159cd9026.tar.gz
Simple-eccda096c2e8e30f76e4c4a21421243159cd9026.zip
README includes more design decisions for type names.
Add Or,Xor for completeness.
Diffstat (limited to 'chapter14/src/main/java/com/seaofnodes')
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/Parser.java4
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java6
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/OrNode.java62
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/XorNode.java62
4 files changed, 130 insertions, 4 deletions
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/Parser.java b/chapter14/src/main/java/com/seaofnodes/simple/Parser.java
index b6ff4724..bea06a19 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/Parser.java
@@ -516,6 +516,8 @@ public class Parser {
while( true ) {
if( false ) ;
else if( match("&") ) lhs = new AndNode(lhs,null);
+ else if( match("|") ) lhs = new OrNode(lhs,null);
+ else if( match("^") ) lhs = new XorNode(lhs,null);
else break;
lhs.setDef(2,parseComparison());
lhs = lhs.peephole();
@@ -566,8 +568,8 @@ public class Parser {
while( true ) {
if( false ) ;
else if( match("<<") ) lhs = new ShlNode(lhs,null);
- else if( match(">>") ) lhs = new SarNode(lhs,null);
else if( match(">>>")) lhs = new ShrNode(lhs,null);
+ else if( match(">>") ) lhs = new SarNode(lhs,null);
else break;
lhs.setDef(2,parseAddition());
lhs = lhs.widen().peephole();
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 06e02d9a..7e4b898b 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java
@@ -39,10 +39,10 @@ public class AndNode extends Node {
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)
+ // And of -1. We do not check for (-1&x) because this will already
+ // canonicalize to (x&-1)
if( t2.isConstant() && t2 instanceof TypeInteger i && i.value()==-1 )
- return rhs;
+ return lhs;
// Move constants to RHS: con*arg becomes arg*con
if ( t1.isConstant() && !t2.isConstant() )
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/OrNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/OrNode.java
new file mode 100644
index 00000000..24577b16
--- /dev/null
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/OrNode.java
@@ -0,0 +1,62 @@
+package com.seaofnodes.simple.node;
+
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+
+import java.util.BitSet;
+
+public class OrNode extends Node {
+ public OrNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
+
+ @Override public String label() { return "Or"; }
+
+ @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;
+
+ // Or of 0. We do not check for (0&x) because this will already
+ // canonicalize to (x&0)
+ if( t2.isConstant() && t2 instanceof TypeInteger i && i.value()==0 )
+ return lhs;
+
+ // 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 OrNode(lhs,rhs); }
+ @Override String err() {
+ if( !(in(1)._type instanceof TypeInteger) ) return "Cannot '|' " + in(1)._type;
+ if( !(in(2)._type instanceof TypeInteger) ) return "Cannot '|' " + in(2)._type;
+ return null;
+ }
+}
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/XorNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/XorNode.java
new file mode 100644
index 00000000..0e235eae
--- /dev/null
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/XorNode.java
@@ -0,0 +1,62 @@
+package com.seaofnodes.simple.node;
+
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeInteger;
+
+import java.util.BitSet;
+
+public class XorNode extends Node {
+ public XorNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
+
+ @Override public String label() { return "Xor"; }
+
+ @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;
+
+ // Xor of 0. We do not check for (0&x) because this will already
+ // canonicalize to (x&0)
+ if( t2.isConstant() && t2 instanceof TypeInteger i && i.value()==0 )
+ return lhs;
+
+ // 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 XorNode(lhs,rhs); }
+ @Override String err() {
+ if( !(in(1)._type instanceof TypeInteger) ) return "Cannot '^' " + in(1)._type;
+ if( !(in(2)._type instanceof TypeInteger) ) return "Cannot '^' " + in(2)._type;
+ return null;
+ }
+}