summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2024-09-04 09:56:17 -0700
committerThalia Archibald <thalia@archibald.dev>2024-09-07 10:54:48 -0700
commit32a45da280ddf0a25a24878399b6253d60b1fa84 (patch)
tree517ce8d660dceb56a64691c8306995da6bff08d1
parent29db69cb40c2fda992a704a50e9159a1a3e23ac9 (diff)
downloadSimple-32a45da280ddf0a25a24878399b6253d60b1fa84.tar.gz
Simple-32a45da280ddf0a25a24878399b6253d60b1fa84.zip
All the remaining narrow types
Narrow f32, requires a Round node.
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/Parser.java21
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java38
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/type/Type.java1
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/type/TypeFloat.java71
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/type/TypeInteger.java12
-rw-r--r--chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java26
6 files changed, 135 insertions, 34 deletions
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<Type> ts) { ts.add(ZERO); ts.add(BOT); }
+ public static void gather(ArrayList<Type> 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");
diff --git a/chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java b/chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java
index 268111d8..682eff15 100644
--- a/chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java
+++ b/chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java
@@ -115,4 +115,30 @@ return c; //
assertEquals(52501L, Evaluator.evaluate(stop, 0));
}
+ @Test
+ public void testTypes() {
+ Parser parser = new Parser(
+"""
+i8 xi8 = 123456789; if( xi8 != 21 ) return -8;
+i16 xi16 = 123456789; if( xi16 != -13035 ) return -16;
+i32 xi32 = 123456789; if( xi32 != 123456789 ) return -32;
+i64 xi64 = 123456789; if( xi64 != 123456789 ) return -64;
+int xint = 123456789; if( xint != 123456789 ) return -64;
+
+u1 ui1 = 123456789; if( ui1 != 1 ) return 1;
+u8 ui8 = 123456789; if( ui8 != 21 ) return 8;
+u16 ui16 = 123456789; if( ui16 != 52501 ) return 16;
+u32 ui32 = 123456789; if( ui32 != 123456789 ) return 32;
+
+flt fflt = 3.141592653589793; if( fflt != 3.141592653589793 ) return 3;
+f64 ff64 = 3.141592653589793; if( ff64 != 3.141592653589793 ) return 3;
+f32 ff32 = 3.141592653589793; if( ff32 != 3.1415927410125732) return 5;
+
+return 0;
+""");
+ StopNode stop = parser.parse(false).iterate(false);
+ assertEquals("return 0;", stop.toString());
+ assertEquals(0L, Evaluator.evaluate(stop, 0));
+ }
+
}