diff options
Diffstat (limited to 'chapter18/src/main/java/com')
6 files changed, 40 insertions, 26 deletions
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java index f1cbf446..2d98287d 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java @@ -217,7 +217,6 @@ public class Parser { // All args, "as-if" called externally for( int i=0; i<ids.length; i++ ) { Type t = sig.arg(i); - assert t==t.glb(); // Expect args declared type not be lifted _scope.define(ids[i], t, false, new ParmNode(ids[i],i+2,t,fun,con(t)).peephole(), loc); } @@ -625,7 +624,9 @@ public class Parser { // TOP fields are for late-initialized fields; these have never // been written to, and this must be the final write. Other writes // outside the constructor need to check the final bit. - if( _scope.in(def._idx)._type!=Type.TOP && def._final && !_scope.inCon() ) + if( _scope.in(def._idx)._type!=Type.TOP && def._final && + // Inside a constructor, final assign is OK, outside nope + !(_scope.inCon() && def._idx >= _scope._lexSize.last()) ) throw error("Cannot reassign final '"+name+"'"); // Lift expression, based on type @@ -1281,8 +1282,10 @@ public class Parser { if( matchx("++") || matchx("--") ) { if( f._final && !f._fname.equals("[]") ) throw error("Cannot reassign final '"+f._fname+"'"); - Node inc = peep(new AddNode(load,con( _lexer.peek(-1)=='+' ? 1 : -1))); - Node val = zsMask(inc,tf); + int delta = _lexer.peek(-1)=='+' ? 1 : -1; // Pre vs post + Node val = f._type instanceof TypeFloat + ? peep(new AddFNode(load,con(TypeFloat.constant(delta)))) + : zsMask(peep(new AddNode(load,con(delta))),f._type); Node st = new StoreNode(loc(), name, f._alias, tf, memAlias(f._alias), expr.unkeep(), off, val, false); // Arrays include control, as a proxy for a safety range check. // Structs don't need this; they only need a NPE check which is diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/CallEndNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/CallEndNode.java index 578d7f87..c9ea2f1f 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/CallEndNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/CallEndNode.java @@ -48,21 +48,27 @@ public class CallEndNode extends CFGNode implements MultiNode { if( !_folding && nIns()==2 ) { CallNode call = call(); Node fptr = call.fptr(); - if( fptr.nOuts() == 1 ) { // Only user is this call + if( fptr.nOuts() == 1 && // Only user is this call + // Function is being called, and its not-null + fptr._type instanceof TypeFunPtr tfp && tfp.notNull()) { ReturnNode ret = (ReturnNode)in(1); FunNode fun = ret.fun(); - assert fun.nIns()==3; // Expecting Start, and the Call - assert fun.in(1) instanceof StartNode && fun.in(2)==call; + // Expecting Start, and the Call + if( fun.nIns()==3 ) { + assert fun.in(1) instanceof StartNode && fun.in(2)==call; - // Trivial inline: rewrite - _folding = true; - // Rewrite Fun so the normal RegionNode ideal collapses - fun._folding = true; - fun.setDef(1,Parser.XCTRL); // No default/unknown StartNode caller - fun.setDef(2,call.ctrl()); // Bypass the Call; - fun.ret().setDef(3,null); // Return is folding also - IterPeeps.addAll(fun._outputs); - return this; + // Trivial inline: rewrite + _folding = true; + // Rewrite Fun so the normal RegionNode ideal collapses + fun._folding = true; + fun.setDef(1,Parser.XCTRL); // No default/unknown StartNode caller + fun.setDef(2,call.ctrl()); // Bypass the Call; + fun.ret().setDef(3,null); // Return is folding also + IterPeeps.addAll(fun._outputs); + return this; + } else { + fun.addDep(this); + } } else { // Function ptr has multiple users (so maybe multiple call sites) fptr.addDep(this); } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/CallNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/CallNode.java index 6963ff2b..246398ee 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/CallNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/CallNode.java @@ -1,6 +1,7 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.CodeGen; +import com.seaofnodes.simple.IterPeeps; import com.seaofnodes.simple.Parser; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.type.Type; @@ -37,9 +38,11 @@ public class CallNode extends CFGNode { Node ctrl() { return in(0); } Node mem () { return in(1); } - // Args mapped 1-to-1 on inputs + // Args mapped 1-to-1 on inputs, so conceptually start at 2 Node arg(int idx) { return in(idx); } - // args from input 2 to last + // Same arg accounting as TFPs, although the numbering starts at 2 + int nargs() { return nIns()-3; } // Minus control, memory, fptr + // args from input 2 to last; last is function input public Node fptr() { return _inputs.last(); } // Find the Call End from the Call @@ -79,7 +82,7 @@ public class CallNode extends CFGNode { // Link: call calls target function. Linking makes the target FunNode // point to this Call, and all his Parms point to the call arguments; // also the CallEnd points to the Return. - if( fptr()._type instanceof TypeFunPtr tfp ) { + if( fptr()._type instanceof TypeFunPtr tfp && tfp.nargs() == nargs() ) { // If fidxs is negative, then infinite unknown functions long fidxs = tfp.fidxs(); if( fidxs > 0 ) { @@ -115,7 +118,7 @@ public class CallNode extends CFGNode { if( use instanceof ParmNode parm ) parm.addDef(parm._idx==0 ? cend() : arg(parm._idx)); // Call end points to function return - cend().addDef(fun.ret()); + IterPeeps.add(cend()).addDef(fun.ret()); assert linked(fun); } @@ -125,6 +128,9 @@ public class CallNode extends CFGNode { throw Utils.TODO(); if( !tfp.notNull() ) return Parser.error( "Might be null calling "+tfp, _loc); + if( nargs() != tfp.nargs() ) + return Parser.error( "Expecting "+tfp.nargs()+" arguments, but found "+nargs(), _loc); + // Check for args for( int i=0; i<tfp.nargs(); i++ ) if( !arg(i+2)._type.isa(tfp.arg(i)) ) 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 4adc81ff..98d0ac71 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/CastNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/CastNode.java @@ -2,8 +2,6 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeInteger; -import com.seaofnodes.simple.IterPeeps; - import java.util.BitSet; // Upcast (join) the input to a t. Used after guard test to lift an input. diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/LoadNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/LoadNode.java index ce481f49..7c5a0e66 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/LoadNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/LoadNode.java @@ -84,7 +84,6 @@ public class LoadNode extends MemOpNode { phi.addDep(this); break outer; case ConstantNode top: break outer; // Assume shortly dead - case ProjNode mproj: // Memory projection switch( mproj.in(0) ) { case NewNode nnn1: @@ -99,6 +98,8 @@ public class LoadNode extends MemOpNode { default: throw Utils.TODO(); } break; + case MemMergeNode merge: mem = merge.alias(_alias); break; + default: throw Utils.TODO(); } 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 4814539f..78a94dff 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java @@ -37,9 +37,9 @@ public class TypeFunPtr extends TypeNil { static TypeFunPtr make( byte nil, TypeTuple sig, Type ret, long fidxs ) { return new TypeFunPtr(nil,sig,ret,fidxs).intern(); } public static TypeFunPtr make( boolean nil, TypeTuple sig, Type ret ) { return make((byte)(nil ? 3 : 2),sig,ret,-1); } - @Override TypeFunPtr makeFrom( byte nil ) { return nil ==_nil ? this : make( nil,_sig,_ret, _fidxs).setName(_name); } - public TypeFunPtr makeFrom( int fidx ) { return 1L<<fidx==_fidxs ? this : make(_nil,_sig,_ret,1L<<fidx ).setName(_name); } - public TypeFunPtr makeFrom( Type ret ) { return ret ==_ret ? this : make(_nil,_sig, ret, _fidxs).setName(_name); } + @Override TypeFunPtr makeFrom( byte nil ) { return nil ==_nil ? this : make( nil,_sig,_ret, _fidxs).setName(_name); } + public TypeFunPtr makeFrom( Type ret ) { return ret ==_ret ? this : make( _nil,_sig, ret, _fidxs).setName(_name); } + public TypeFunPtr makeFrom( int fidx ) { return make((byte)2, _sig,_ret,1L<<fidx ).setName(_name); } // Compute "function indices": FIDX private static final HashMap<TypeTuple,Integer> FIDXS = new HashMap<>(); |
