From 32a45da280ddf0a25a24878399b6253d60b1fa84 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Wed, 4 Sep 2024 09:56:17 -0700 Subject: All the remaining narrow types Narrow f32, requires a Round node. --- .../main/java/com/seaofnodes/simple/Parser.java | 21 ++++++- .../com/seaofnodes/simple/node/RoundF32Node.java | 38 ++++++++++++ .../main/java/com/seaofnodes/simple/type/Type.java | 1 + .../java/com/seaofnodes/simple/type/TypeFloat.java | 71 +++++++++++++--------- .../com/seaofnodes/simple/type/TypeInteger.java | 12 +++- 5 files changed, 109 insertions(+), 34 deletions(-) create mode 100644 chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java (limited to 'chapter14/src/main/java') diff --git a/chapter14/src/main/java/com/seaofnodes/simple/Parser.java b/chapter14/src/main/java/com/seaofnodes/simple/Parser.java index b249b0a4..b6ff4724 100644 --- a/chapter14/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter14/src/main/java/com/seaofnodes/simple/Parser.java @@ -57,8 +57,13 @@ public class Parser { add("byte"); add("continue"); add("else"); + add("f32"); + add("f64"); add("false"); add("flt"); + add("i16"); + add("i32"); + add("i64"); add("i8"); add("if"); add("int"); @@ -93,7 +98,12 @@ public class Parser { TYPES.clear(); TYPES.put("bool",TypeInteger.U1 ); TYPES.put("byte",TypeInteger.U8 ); + TYPES.put("f32" ,TypeFloat .B32); + TYPES.put("f64" ,TypeFloat .BOT); TYPES.put("flt" ,TypeFloat .BOT); + TYPES.put("i16" ,TypeInteger.I16); + TYPES.put("i32" ,TypeInteger.I32); + TYPES.put("i64" ,TypeInteger.BOT); TYPES.put("i8" ,TypeInteger.I8 ); TYPES.put("int" ,TypeInteger.BOT); TYPES.put("u1" ,TypeInteger.U1 ); @@ -712,10 +722,15 @@ public class Parser { // zero/sign extend. "i" is limited to either classic unsigned (min==0) or // classic signed (min=minus-power-of-2); max=power-of-2-minus-1. private Node zsMask(Node val, Type t ) { - if( !(val._type instanceof TypeInteger tval && t instanceof TypeInteger t0 && !tval.isa(t0)) ) - return val; - if( t0._min==0 ) + if( !(val._type instanceof TypeInteger tval && t instanceof TypeInteger t0 && !tval.isa(t0)) ) { + if( !(val._type instanceof TypeFloat tval && t instanceof TypeFloat t0 && !tval.isa(t0)) ) + return val; + // Float rounding + return new RoundF32Node(val).peephole(); + } + if( t0._min==0 ) // Unsigned return new AndNode(val,new ConstantNode(TypeInteger.constant(t0._max)).peephole()).peephole(); + // Signed extension int shift = Long.numberOfLeadingZeros(t0._max)-1; Node shf = new ConstantNode(TypeInteger.constant(shift)).peephole(); if( shf._type==TypeInteger.ZERO ) diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java new file mode 100644 index 00000000..44d3a587 --- /dev/null +++ b/chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -0,0 +1,38 @@ +package com.seaofnodes.simple.node; + +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeFloat; + +import java.util.BitSet; + +public class RoundF32Node extends Node { + public RoundF32Node(Node lhs) { super(null, lhs); } + + @Override public String label() { return "RoundF32"; } + + @Override public String glabel() { return "(f32)"; } + + @Override + StringBuilder _print1(StringBuilder sb, BitSet visited) { + return in(1)._print0(sb.append("((f32)"), visited).append(")"); + } + + @Override + public Type compute() { + if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) + return TypeFloat.constant((float)i0.value()); + return in(1)._type; + } + + @Override + public Node idealize() { + Node lhs = in(1); + Type t1 = lhs._type; + + // RoundF32 of float + if( t1 instanceof TypeFloat tf && tf._sz==32 ) + return lhs; + + return null; + } +} diff --git a/chapter14/src/main/java/com/seaofnodes/simple/type/Type.java b/chapter14/src/main/java/com/seaofnodes/simple/type/Type.java index 9c938ef8..49dc090a 100644 --- a/chapter14/src/main/java/com/seaofnodes/simple/type/Type.java +++ b/chapter14/src/main/java/com/seaofnodes/simple/type/Type.java @@ -56,6 +56,7 @@ public class Type { ts.add(CONTROL); Field.gather(ts); TypeInteger.gather(ts); + TypeFloat.gather(ts); TypeMem.gather(ts); TypeMemPtr.gather(ts); TypeStruct.gather(ts); 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 f40c7480..975c1a9e 100644 --- a/chapter14/src/main/java/com/seaofnodes/simple/type/TypeFloat.java +++ b/chapter14/src/main/java/com/seaofnodes/simple/type/TypeFloat.java @@ -7,44 +7,50 @@ import java.util.ArrayList; */ public class TypeFloat extends Type { - public final static TypeFloat TOP = make(false, 0); - public final static TypeFloat BOT = make(false, 1); - public final static TypeFloat ZERO= make(true , 0); + public final static TypeFloat TOP = make((byte)-64, 0); + public final static TypeFloat T32 = make((byte)-32, 0); + public final static TypeFloat ZERO= make((byte) 0, 0); + public final static TypeFloat B32 = make((byte) 32, 0); + public final static TypeFloat BOT = make((byte) 64, 0); - public final boolean _is_con; + /** +/-64 for double; +/-32 for float, or 0 for constants */ + public final byte _sz; /** - * The constant value or - * if not constant then 1=bottom, 0=top. + * The constant value or 0 */ public final double _con; - private TypeFloat(boolean is_con, double con) { + private TypeFloat(byte sz, double con) { super(TFLT); - _is_con = is_con; + _sz = sz ; _con = con; } - public static TypeFloat make(boolean is_con, double con) { - return new TypeFloat(is_con,con).intern(); + private static TypeFloat make(byte sz, double con) { + return new TypeFloat(sz,con).intern(); } - public static TypeFloat constant(double con) { return make(true, con); } + public static TypeFloat constant(double con) { return make((byte)0, con); } - public static void gather(ArrayList ts) { ts.add(ZERO); ts.add(BOT); } + public static void gather(ArrayList ts) { ts.add(ZERO); ts.add(BOT); ts.add(B32); ts.add(constant(3.141592653589793)); } // 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("FltTop"); + if( this==T32 ) return sb.append("F32Top"); + if( this==B32 ) return sb.append("F32Bot"); if( this==BOT ) return sb.append("FltBot"); return sb.append(_con); } @Override public String str() { if( this==TOP ) return "~flt"; + if( this==T32 ) return "~f32"; + if( this==B32 ) return "f32"; if( this==BOT ) return "flt"; - return ""+_con; + return ""+_con+(isF32() ? "f" : ""); } /** @@ -53,13 +59,16 @@ public class TypeFloat extends Type { @Override public StringBuilder typeName(StringBuilder sb) { if( this==TOP ) return sb.append("FltTop"); + if( this==T32 ) return sb.append("F32Top"); + if( this==B32 ) return sb.append("F32Bot"); if( this==BOT ) return sb.append("FltBot"); - return sb.append("Flt"); + return sb.append(isF32() ? "F32" : "Flt"); } - @Override public boolean isHigh() { return this==TOP; } - @Override public boolean isHighOrConst() { return _is_con || _con==0; } - @Override public boolean isConstant() { return _is_con; } + boolean isF32() { return ((float)_con)==_con; } + @Override public boolean isHigh() { return _sz< 0; } + @Override public boolean isHighOrConst() { return _sz<=0; } + @Override public boolean isConstant() { return _sz==0; } public double value() { return _con; } @@ -67,21 +76,27 @@ public class TypeFloat extends Type { public Type xmeet(Type other) { // Invariant from caller: 'this' != 'other' and same class (TypeFloat) TypeFloat i = (TypeFloat)other; // Contract - // BOT wins - if ( this==BOT ) return this; - if ( i ==BOT ) return i ; - // TOP loses - if ( i ==TOP ) return this; - if ( this==TOP ) return i ; + // Larger size in i1, smaller in i0 + TypeFloat i0 = _sz < i._sz ? this : i; + TypeFloat i1 = _sz < i._sz ? i : this; + + if( i1._sz== 64 ) return BOT; + if( i0._sz==-64 ) return i1; + if( i1._sz== 32 ) + return i0._sz==0 && !i0.isF32() ? BOT : B32; + if( i1._sz!= 0 ) return i1; + // i1 is a constant + if( i0._sz==-32 ) + return i1.isF32() ? i1 : BOT; // Since both are constants, and are never equals (contract) unequals // constants fall to bottom - return BOT; + return i0.isF32() && i1.isF32() ? B32 : BOT; } @Override public Type dual() { - if( isConstant() ) return this; // Constants are a self-dual - return _con==0 ? BOT : TOP; + if( _sz==0 ) return this; // Constants are a self-dual + return make((byte)-_sz,0); } @Override @@ -90,10 +105,10 @@ public class TypeFloat extends Type { @Override public TypeFloat makeInit() { return ZERO; } @Override - int hash() { return (int)(Double.hashCode(_con) ^ (_is_con ? 0 : 0x4000)); } + int hash() { return (int)(Double.hashCode(_con) ^ _sz); } @Override public boolean eq( Type t ) { TypeFloat i = (TypeFloat)t; // Contract - return _con==i._con && _is_con==i._is_con; + return _con==i._con && _sz==i._sz; } } 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 0221da7a..403cc7bf 100644 --- a/chapter14/src/main/java/com/seaofnodes/simple/type/TypeInteger.java +++ b/chapter14/src/main/java/com/seaofnodes/simple/type/TypeInteger.java @@ -14,10 +14,13 @@ public class TypeInteger extends Type { public final static TypeInteger BOOL= U1; public final static TypeInteger FALSE=ZERO; public final static TypeInteger TRUE= make(1,1); + public final static TypeInteger I8 = make(-128,127); + public final static TypeInteger I16 = make(-32768,32767); + public final static TypeInteger I32 = make(-1L<<31,(1L<<31)-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); - public final static TypeInteger I8 = make(-128,127); /** * Describes an integer *range* - everything from min to max; both min and @@ -31,8 +34,8 @@ public class TypeInteger extends Type { private TypeInteger(long min, long max) { super(TINT); _min = min; _max = max; } public static TypeInteger make(long lo, long hi) { return new TypeInteger(lo,hi).intern(); } public static TypeInteger make(boolean is_con, long con) { - return make(is_con ? con : (con==0 ? Integer.MAX_VALUE : Integer.MIN_VALUE), - is_con ? con : (con==0 ? Integer.MIN_VALUE : Integer.MAX_VALUE)); + return make(is_con ? con : (con==0 ? Long.MAX_VALUE : Long.MIN_VALUE), + is_con ? con : (con==0 ? Long.MIN_VALUE : Long.MAX_VALUE)); } public static TypeInteger constant(long con) { return make(true, con); } @@ -48,6 +51,9 @@ public class TypeInteger extends Type { if( this==TOP ) return "~int"; if( this==BOT ) return "int"; if( this==BOOL) return ("bool"); + if( this==I8 ) return ("i8"); + if( this==I16 ) return ("i16"); + if( this==I32 ) return ("i32"); if( this==U8 ) return ("u8"); if( this==U16 ) return ("u16"); if( this==U32 ) return ("u32"); -- cgit v1.2.3