From e0d7b4f8ef0e886f8efae62b77402007e6b2476c Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Tue, 7 Jan 2025 15:31:54 -0800 Subject: 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. --- .../main/java/com/seaofnodes/simple/Parser.java | 22 ++++++++++++++-------- .../java/com/seaofnodes/simple/node/CastNode.java | 10 ++++++++++ .../java/com/seaofnodes/simple/node/FRefNode.java | 2 +- .../java/com/seaofnodes/simple/node/StoreNode.java | 1 + .../com/seaofnodes/simple/node/ToFloatNode.java | 7 +++++-- .../java/com/seaofnodes/simple/type/TypeFloat.java | 1 + .../com/seaofnodes/simple/type/TypeFunPtr.java | 11 +++++++---- 7 files changed, 39 insertions(+), 15 deletions(-) (limited to 'chapter18/src/main') 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 ? "→ " : "-> "),g,_ret).p(" #"); + if( isHigh() ) sb.p("~"); long fidxs = isHigh() ? ~_fidxs : _fidxs; String fidx = fidxs==0 ? "" : Long.bitCount(fidxs) == 1 ? ""+Long.numberOfTrailingZeros(fidxs) -- cgit v1.2.3