summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/node/BoolNode.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/seaofnodes/simple/node/BoolNode.java')
-rw-r--r--src/main/java/com/seaofnodes/simple/node/BoolNode.java119
1 files changed, 77 insertions, 42 deletions
diff --git a/src/main/java/com/seaofnodes/simple/node/BoolNode.java b/src/main/java/com/seaofnodes/simple/node/BoolNode.java
index 0d82c5b9..73e786e3 100644
--- a/src/main/java/com/seaofnodes/simple/node/BoolNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/BoolNode.java
@@ -3,21 +3,27 @@ package com.seaofnodes.simple.node;
import com.seaofnodes.print.ExprPrinter;
import com.seaofnodes.simple.Parser;
+import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.type.*;
+import com.seaofnodes.simple.util.BAOS;
import com.seaofnodes.simple.util.Utils;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
import static com.seaofnodes.simple.type.TypeInteger.*;
-abstract public class BoolNode extends Node {
+abstract public class BoolNode extends Node implements ModeNode {
- public BoolNode(Node lhs, Node rhs) {
- super(null, lhs, rhs);
+ // Mode is 0 for unknown, 1 for int, 2 for flt
+ byte _mode;
+
+ public BoolNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
+ public BoolNode(Node lhs, Node rhs, byte mode) { super(null, lhs, rhs); _mode = mode; }
+ @Override public void packed(BAOS baos, HashMap<String,Integer> strs, HashMap<Type,Integer> types, IdentityHashMap<Node,Integer> anodes) {
+ baos.packed1(_mode);
}
abstract public String op(); // String opcode name
- @Override
- public String label() { return getClass().getSimpleName(); }
-
@Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
return p.open().n(in(1)).p(op()).n(in(2)).close();
}
@@ -26,15 +32,25 @@ abstract public class BoolNode extends Node {
public TypeInteger compute() {
Type t1 = in(1)._type;
Type t2 = in(2)._type;
+ if( t1==null || t2==null )
+ return BOOL;
// Exactly equals?
if( t1.isHigh() || t2.isHigh() )
return (TypeInteger)BOOL.dual();
if( in(1)==in(2) )
// LT fails, both EQ and LE succeed
return this instanceof LT ? FALSE : TRUE;
- if( t1 instanceof TypeInteger i1 &&
- t2 instanceof TypeInteger i2 )
- return doOp(i1,i2);
+ byte mode = _mode==0 ? ArithNode.mode(t1,t2) : _mode;
+ if( mode==0 )
+ return BOOL;
+ // Handle integer compares
+ if( mode==1 ) {
+ if( t1 instanceof TypeInteger i1 &&
+ t2 instanceof TypeInteger i2 )
+ return doOp(i1,i2);
+ return BOOL;
+ }
+ // Floating compare. Mixed inputs are converted in idealize().
if( t1 instanceof TypeFloat f1 &&
t2 instanceof TypeFloat f2 &&
f1.isConstant() && f2.isConstant() )
@@ -44,22 +60,41 @@ abstract public class BoolNode extends Node {
TypeInteger doOp(TypeInteger t1, TypeInteger t2) { throw Utils.TODO(); }
boolean doOp(double lhs, double rhs) { throw Utils.TODO(); }
- Node copyF(Node lhs, Node rhs) { return null; }
- public boolean isFloat() { return false; }
+ public boolean isFloat() { assert _mode!=0; return _mode==2; }
+ @Override public byte mode() { return _mode; }
+ @Override public Node setMode(byte mode) {
+ assert _mode==0 && (mode==1 || mode==2);
+ unlock(); // _mode participates in GVN hash and equality
+ _mode = mode;
+ return this;
+ }
@Override
public Node idealize() {
// Compare of same
if( in(1)==in(2) )
- return this instanceof LT ? Parser.ZERO : new ConstantNode(TRUE);
+ return this instanceof LT ? CodeGen.CODE.ZERO : ConstantNode.make(TRUE);
+ // Can we decide int vs flt?
+ Type t1 = in(1)._type, t2 = in(2)._type;
+ if( t1==null || t2==null )
+ return null;
+ if( _mode==0 ) {
+ byte mode = ArithNode.mode(t1,t2);
+ if( mode!=0 ) return setMode(mode).init();
+ }
+ if( _mode==2 ) {
+ if( t1 instanceof TypeInteger ) return copy(new ToFloatNode(in(1)).peephole(),in(2));
+ if( t2 instanceof TypeInteger ) return copy(in(1),new ToFloatNode(in(2)).peephole());
+ }
+
// Equals pushes constant to the right; 5==X becomes X==5.
if( this instanceof EQ ) {
if( !(in(2) instanceof ConstantNode) ) {
// con==noncon becomes noncon==con
if( in(1) instanceof ConstantNode || in(1)._nid > in(2)._nid )
- // Equals sorts by NID otherwise: non.high == non.low becomes non.low == non.high
- return in(1)._type instanceof TypeFloat ? new EQF(in(2),in(1)) : new EQ(in(2),in(1));
+ // Equals sorts by NID otherwise: non.high == non.low becomes non.low == non.high
+ return new EQ(in(2),in(1));
}
// Equals X==0 becomes a !X
if( (in(2)._type == ZERO || in(2)._type == Type.NIL) )
@@ -75,76 +110,76 @@ abstract public class BoolNode extends Node {
return null;
}
+ @Override public boolean eq( Node n ) { return _mode==((BoolNode)n)._mode; }
+ @Override public int hash() { return _mode; }
+ @Override public Parser.ParseException err() {
+ return ArithNode.nodeErr(this,null,op(),_mode,!(this instanceof ULT));
+ }
+
public static class EQ extends BoolNode {
public EQ(Node lhs, Node rhs) { super(lhs,rhs); }
+ public EQ(Node lhs, Node rhs, byte mode) { super(lhs,rhs, mode); }
+ @Override public Tag serialTag() { return Tag.EQ; }
public String op() { return "=="; }
TypeInteger doOp(TypeInteger i1, TypeInteger i2) {
if( i1==i2 && i1.isConstant() ) return TRUE;
if( i1._max < i2._min || i1._min > i2._max ) return FALSE;
return BOOL;
}
- Node copy(Node lhs, Node rhs) { return new EQ(lhs,rhs); }
- Node copyF() { return new EQF(null,null); }
+ @Override boolean doOp(double lhs, double rhs) { return lhs==rhs; }
+ Node copy(Node lhs, Node rhs) { return new EQ(lhs,rhs,_mode); }
}
public static class NE extends BoolNode {
public NE(Node lhs, Node rhs) { super(lhs,rhs); }
+ public NE(Node lhs, Node rhs, byte mode) { super(lhs,rhs,mode); }
+ @Override public Tag serialTag() { return Tag.NE; }
public String op() { return "!="; }
TypeInteger doOp(TypeInteger i1, TypeInteger i2) {
if( i1==i2 && i1.isConstant() ) return TRUE;
if( i1._max < i2._min || i1._min > i2._max ) return FALSE;
return BOOL;
}
- Node copy(Node lhs, Node rhs) { return new NE(lhs,rhs); }
- Node copyF() { throw Utils.TODO(); }
+ @Override boolean doOp(double lhs, double rhs) { return lhs!=rhs; }
+ Node copy(Node lhs, Node rhs) { return new NE(lhs,rhs,_mode); }
}
public static class LT extends BoolNode {
public LT(Node lhs, Node rhs) { super(lhs,rhs); }
+ public LT(Node lhs, Node rhs, byte mode) { super(lhs,rhs, mode); }
+ @Override public Tag serialTag() { return Tag.LT; }
public String op() { return "<" ; }
TypeInteger doOp(TypeInteger i1, TypeInteger i2) {
if( i1._max < i2._min ) return TRUE;
if( i1._min >= i2._max ) return FALSE;
return BOOL;
}
- Node copy(Node lhs, Node rhs) { return new LT(lhs,rhs); }
- Node copyF() { return new LTF(null,null); }
+ @Override boolean doOp(double lhs, double rhs) { return lhs<rhs; }
+ Node copy(Node lhs, Node rhs) { return new LT(lhs,rhs,_mode); }
}
public static class LE extends BoolNode {
public LE(Node lhs, Node rhs) { super(lhs,rhs); }
+ public LE(Node lhs, Node rhs, byte mode) { super(lhs,rhs,mode); }
+ @Override public Tag serialTag() { return Tag.LE; }
public String op() { return "<="; }
TypeInteger doOp(TypeInteger i1, TypeInteger i2) {
if( i1._max <= i2._min ) return TRUE;
if( i1._min > i2._max ) return FALSE;
return BOOL;
}
- Node copy(Node lhs, Node rhs) { return new LE(lhs,rhs); }
- Node copyF() { return new LEF(null,null); }
- }
-
- public static class EQF extends EQ {
- public EQF(Node lhs, Node rhs) { super(lhs,rhs); }
- @Override boolean doOp(double lhs, double rhs) { return lhs == rhs; }
- @Override public boolean isFloat() { return true; }
- @Override Node copy(Node lhs, Node rhs) { return new EQF(lhs,rhs); }
- }
- public static class LTF extends LT {
- public LTF(Node lhs, Node rhs) { super(lhs,rhs); }
- @Override boolean doOp(double lhs, double rhs) { return lhs < rhs; }
- @Override public boolean isFloat() { return true; }
- @Override Node copy(Node lhs, Node rhs) { return new LTF(lhs,rhs); }
- }
- public static class LEF extends LE {
- public LEF(Node lhs, Node rhs) { super(lhs,rhs); }
- @Override boolean doOp(double lhs, double rhs) { return lhs <= rhs; }
- @Override public boolean isFloat() { return true; }
- @Override Node copy(Node lhs, Node rhs) { return new LEF(lhs,rhs); }
+ @Override boolean doOp(double lhs, double rhs) { return lhs<=rhs; }
+ Node copy(Node lhs, Node rhs) { return new LE(lhs,rhs,_mode); }
}
// Unsigned less that, for range checks. Not directly user writable.
public static class ULT extends BoolNode {
- public ULT(Node lhs, Node rhs) { super(lhs,rhs); }
+ public ULT(Node lhs, Node rhs) { super(lhs,rhs,(byte)1); }
+ public ULT(Node lhs, Node rhs, byte mode) {
+ super(lhs,rhs,(byte)1);
+ assert mode==1;
+ }
+ @Override public Tag serialTag() { return Tag.ULT; }
public String op() { return "u<" ; }
TypeInteger doOp(TypeInteger i1, TypeInteger i2) {
if( Long.compareUnsigned(i1._max,i2._min) < 0 ) return TRUE;