summaryrefslogtreecommitdiff
path: root/chapter18/src/main/java/com/seaofnodes
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2025-01-07 15:31:54 -0800
committerCliff Click <cliffc@acm.org>2025-01-15 15:07:30 -0800
commite0d7b4f8ef0e886f8efae62b77402007e6b2476c (patch)
tree042c6df4fc96b6f3bd128f03f1cfda4c1f66704e /chapter18/src/main/java/com/seaofnodes
parentc2169787d92da57aa0e11cd026e398b3d5fcda12 (diff)
downloadSimple-e0d7b4f8ef0e886f8efae62b77402007e6b2476c.tar.gz
Simple-e0d7b4f8ef0e886f8efae62b77402007e6b2476c.zip
Forward Ref type to Bottom
So FRefs can strictly lift when defined. Parser can support forward refs in more cases, by upcasting now and proving the cast is correct later. Monotonic for some float ops.
Diffstat (limited to 'chapter18/src/main/java/com/seaofnodes')
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/Parser.java22
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/CastNode.java10
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/FRefNode.java2
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/StoreNode.java1
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java7
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java1
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java11
7 files changed, 39 insertions, 15 deletions
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java
index 2d98287d..d888f17e 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java
@@ -651,7 +651,7 @@ public class Parser {
// Auto-narrow wide ints to narrow ints
expr = zsMask(expr,t);
// Type is sane
- if( !expr._type.isa(t) )
+ if( expr._type!=Type.BOTTOM && !expr._type.isa(t) )
throw error("Type " + expr._type.str() + " is not of declared type " + t.str());
return expr;
}
@@ -711,14 +711,16 @@ public class Parser {
if( inferType && !_scope.inCon() )
throw errorSyntax("=expression");
// Initial value for uninitialized struct fields.
- expr = t instanceof TypeMemPtr tn
+ expr = switch( t ) {
// Nullable pointers get a NIL; not-null get a TOP which
// signals that they *must* be initialized in the constructor.
- ? (tn.nullable() ? NIL : con(Type.TOP))
- // Bottom signals type inference: they must be initialized in
- // the constructor and that's when we'll discover the type.
- // Otherwise, its an Integer and use 0.
- : (t==Type.BOTTOM ? con(t) : (t instanceof TypeInteger ? ZERO : con(TypeFloat.FZERO)));
+ case TypeNil tn -> tn.nullable() ? NIL : con(Type.TOP);
+ case TypeInteger ti -> ZERO;
+ case TypeFloat tf -> con(TypeFloat.FZERO);
+ // Bottom signals type inference: they must be initialized in
+ // the constructor and that's when we'll discover the type.
+ case Type tt -> { assert tt==Type.BOTTOM; yield con(tt); }
+ };
}
// Lift expression, based on type
@@ -727,6 +729,10 @@ public class Parser {
if( xfinal && t instanceof TypeMemPtr tmp )
t = tmp.makeRO();
+ // Lift type to the declaration. This will report as an error later if
+ // we cannot lift the type.
+ if( !lift._type.isa(t) )
+ lift = peep(new CastNode(t,null,lift));
// Define a new name
if( !_scope.define(name,t,xfinal,lift, loc) )
throw error("Redefining name '" + name + "'", loc);
@@ -1356,7 +1362,7 @@ public class Parser {
private Node functionCall(Node expr) {
if( expr._type == Type.NIL )
throw error("Calling a null function pointer");
- if( !expr._type.isa(TypeFunPtr.BOT) )
+ if( !(expr instanceof FRefNode) && !expr._type.isa(TypeFunPtr.BOT) )
throw error("Expected a function but got "+expr._type.glb().str());
expr.keep(); // Keep while parsing args
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/CastNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/CastNode.java
index 98d0ac71..d8a968c1 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/CastNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/CastNode.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.simple.Parser;
+import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;
import java.util.BitSet;
@@ -45,4 +47,12 @@ public class CastNode extends Node {
@Override
int hash() { return _t.hashCode(); }
+
+ @Override
+ public Parser.ParseException err() {
+ // Has a condition to test, so OK
+ if( in(0) != null ) return null;
+ // No condition to test, so this must optimize away
+ throw Utils.TODO();
+ }
}
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/FRefNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/FRefNode.java
index beb14870..f0c4045d 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/FRefNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/FRefNode.java
@@ -11,7 +11,7 @@ import java.util.BitSet;
* peepholes to the Def.
*/
public class FRefNode extends ConstantNode {
- public static final Type FREF_TYPE = Type.TOP;
+ public static final Type FREF_TYPE = Type.BOTTOM;
public final Var _n;
public FRefNode( Var n ) { super(FREF_TYPE); _n = n; }
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/StoreNode.java
index 576f8d92..ccabadb4 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/StoreNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/StoreNode.java
@@ -43,6 +43,7 @@ public class StoreNode extends MemOpNode {
public Type compute() {
Type val = val()._type;
TypeMem mem = (TypeMem)mem()._type; // Invariant
+ if( mem == TypeMem.TOP ) return TypeMem.TOP;
Type t = Type.BOTTOM; // No idea on field contents
// Same alias, lift val to the declared type and then meet into other fields
if( mem._alias == _alias ) {
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
index 0661ac2c..1f4d67e0 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
@@ -21,8 +21,11 @@ public class ToFloatNode extends Node {
@Override
public Type compute() {
if( in(1)._type == Type.NIL ) return TypeFloat.FZERO;
- if (in(1)._type instanceof TypeInteger i0 && i0.isConstant() )
- return TypeFloat.constant(i0.value());
+ if (in(1)._type instanceof TypeInteger i0 ) {
+ if( i0.isHigh() ) return TypeFloat.F64.dual();
+ if( i0.isConstant() )
+ return TypeFloat.constant(i0.value());
+ }
return TypeFloat.F64;
}
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java
index 258cda03..aa205149 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java
@@ -47,6 +47,7 @@ public class TypeFloat extends Type {
}
private boolean isF32() { return ((float)_con)==_con; }
+ @Override public boolean isHigh () { return _sz< 0; }
@Override public boolean isConstant() { return _sz==0; }
@Override public int log_size() { return _sz==32 || _sz==-32 ? 2 : 3; }
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java
index 78a94dff..5799fea9 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java
@@ -63,7 +63,7 @@ public class TypeFunPtr extends TypeNil {
@Override
Type xmeet(Type t) {
TypeFunPtr that = (TypeFunPtr) t;
- return TypeFunPtr.make(xmeet0(that),(TypeTuple)_sig.meet(that._sig), _ret.meet(that._ret),_fidxs | that._fidxs);
+ return TypeFunPtr.make(xmeet0(that),(TypeTuple)_sig.meet(that._sig), _ret.meet(that._ret), _fidxs | that._fidxs);
}
@Override
@@ -94,8 +94,9 @@ public class TypeFunPtr extends TypeNil {
public TypeFunPtr setName(String name) {
if( name==null ) return this;
- assert _name==null || _name.equals(name);
assert _fidxs > 0 && Long.bitCount(_fidxs) == 1;
+ // Name can be set to different things, just for debug
+ //assert _name==null || _name.equals(name);
_name = name;
return this;
}
@@ -109,9 +110,11 @@ public class TypeFunPtr extends TypeNil {
sb.p(x()).p("{ ");
if( n && _name!=null ) sb.p(_name);
else {
- for( Type t : _sig._types )
- _print(sb,g,t).p(" ");
+ if( _sig._types!=null )
+ for( Type t : _sig._types )
+ _print(sb,g,t).p(" ");
_print(sb.p(g ? "&rarr; " : "-> "),g,_ret).p(" #");
+ if( isHigh() ) sb.p("~");
long fidxs = isHigh() ? ~_fidxs : _fidxs;
String fidx = fidxs==0 ? ""
: Long.bitCount(fidxs) == 1 ? ""+Long.numberOfTrailingZeros(fidxs)