summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/node/MinusNode.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/seaofnodes/simple/node/MinusNode.java')
-rw-r--r--src/main/java/com/seaofnodes/simple/node/MinusNode.java70
1 files changed, 59 insertions, 11 deletions
diff --git a/src/main/java/com/seaofnodes/simple/node/MinusNode.java b/src/main/java/com/seaofnodes/simple/node/MinusNode.java
index 94c69785..e84eb611 100644
--- a/src/main/java/com/seaofnodes/simple/node/MinusNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/MinusNode.java
@@ -1,33 +1,81 @@
package com.seaofnodes.simple.node;
-import com.seaofnodes.simple.type.Type;
-import com.seaofnodes.simple.type.TypeInteger;
+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;
+
+public class MinusNode extends Node implements ModeNode {
+ // Mode is 0 for unknown, 1 for int, 2 for flt
+ byte _mode;
-public class MinusNode extends Node {
public MinusNode(Node in) { super(null, in); }
+ public MinusNode(Node in, byte mode) { super(null, in); _mode = mode; }
+ @Override public void packed(BAOS baos, HashMap<String,Integer> strs, HashMap<Type,Integer> types, IdentityHashMap<Node,Integer> anodes) {
+ baos.packed1(_mode);
+ }
+ @Override public Tag serialTag() { return Tag.Minus; }
- @Override public String label() { return "Minus"; }
+ @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 protected String format() { return "(-%1)"; }
@Override
public Type compute() {
- if( in(1)._type.isHigh() ) return TypeInteger.TOP;
- if( in(1)._type instanceof TypeInteger i0 &&
- i0._min != Long.MIN_VALUE && i0._max != Long.MIN_VALUE )
- return TypeInteger.make(-i0._max,-i0._min,i0._widen);
- return TypeInteger.BOT;
+ Type t = in(1)._type;
+ if( t==null )
+ return Type.TOP;
+ if( t.isHigh() )
+ return _mode==0 ? Type.TOP :
+ _mode==1 ? TypeInteger.TOP :
+ t instanceof TypeFloat ? t : TypeFloat.F64.dual();
+ byte mode = _mode;
+ if( mode==0 ) {
+ if( t instanceof TypeFloat ) mode=2;
+ if( t instanceof TypeInteger ) mode=1;
+ }
+ if( mode==0 )
+ return CodeGen.CODE._phase.ordinal() < CodeGen.Phase.Opto.ordinal() ? Type.BOTTOM : Type.TOP;
+ if( mode==1 ) {
+ if( t instanceof TypeInteger i0 &&
+ i0._min != Long.MIN_VALUE && i0._max != Long.MIN_VALUE )
+ return TypeInteger.make(-i0._max,-i0._min,i0._widen);
+ return TypeInteger.BOT;
+ }
+ if( t instanceof TypeFloat f )
+ return f.isConstant() ? TypeFloat.constant(-f.value()) : f;
+ return TypeFloat.F64;
}
@Override
public Node idealize() {
// -(-x) is x
- if( in(1) instanceof MinusNode minus && addDep(minus.in(1))._type instanceof TypeInteger )
+ if( in(1) instanceof MinusNode minus && addDep(minus.in(1))._type.isa(compute()) )
return minus.in(1);
+ // Can we decide int vs flt?
+ if( _mode==0 ) {
+ byte mode = (byte)(
+ in(1)._type instanceof TypeInteger ? 1 :
+ in(1)._type instanceof TypeFloat ? 2 : 0);
+ if( mode!=0 ) return setMode(mode).init();
+ }
+
return null;
}
- @Override Node copyF() { return new MinusFNode(null); }
+ @Override public Parser.ParseException err() {
+ return ArithNode.nodeErr(this,null,"-",_mode,true);
+ }
+ @Override public boolean eq( Node n ) { return _mode==((MinusNode)n)._mode; }
+ @Override public int hash() { return _mode; }
}