From 5400096ec10da839cf2006a8a02e11ffeff521dd Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sun, 29 Dec 2024 16:06:07 -0800 Subject: More precise error reporting Demand CFG cleanup, even if peeps are off; cleans up some tests & a lot of fuzzer bugs related to trying to find infinite loops in dead code. Logical subclass for better error reporting on &,|,^,>>,<<,>>> More precise error reporting on multi returns and trinaries Fuzzer uses new Eval2 --- .../main/java/com/seaofnodes/simple/CodeGen.java | 5 ++- .../com/seaofnodes/simple/GlobalCodeMotion.java | 7 ++-- .../main/java/com/seaofnodes/simple/Parser.java | 23 +++++++---- .../java/com/seaofnodes/simple/node/AndNode.java | 17 ++------- .../com/seaofnodes/simple/node/LogicalNode.java | 25 ++++++++++++ .../java/com/seaofnodes/simple/node/LoopNode.java | 31 +++++++++------ .../main/java/com/seaofnodes/simple/node/Node.java | 17 ++++++--- .../java/com/seaofnodes/simple/node/OrNode.java | 17 ++------- .../java/com/seaofnodes/simple/node/PhiNode.java | 38 +++++++++++++++++-- .../com/seaofnodes/simple/node/RegionNode.java | 3 +- .../com/seaofnodes/simple/node/ReturnNode.java | 44 +++++++++++++++++++++- .../java/com/seaofnodes/simple/node/SarNode.java | 17 ++------- .../java/com/seaofnodes/simple/node/ShlNode.java | 17 ++------- .../java/com/seaofnodes/simple/node/ShrNode.java | 12 ++---- .../java/com/seaofnodes/simple/node/XorNode.java | 17 ++------- .../java/com/seaofnodes/simple/type/TypeMem.java | 1 + 16 files changed, 175 insertions(+), 116 deletions(-) create mode 100644 chapter18/src/main/java/com/seaofnodes/simple/node/LogicalNode.java (limited to 'chapter18/src/main') diff --git a/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java b/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java index 79d817f8..394b6d1c 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java @@ -57,7 +57,10 @@ public class CodeGen { } public CodeGen typeCheck() { - assert _phase == Phase.Opto || _phase == Phase.Parse; + // Demand phase Opto for cleaning up dead control flow at least, + // required for the following GCM. Note that peeps can be disabled, + // but still the dead CFG will get cleaned. + assert _phase == Phase.Opto; _phase = Phase.TypeCheck; // Type check diff --git a/chapter18/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java b/chapter18/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java index 6b0956ca..f1593a81 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java @@ -107,6 +107,8 @@ public abstract class GlobalCodeMotion { if( n instanceof LoadNode ld ) for( Node memuse : ld.mem()._outputs ) if( late[memuse._nid]==null && + // New makes new memory, never crushes load memory + !(memuse instanceof NewNode) && // Load-use directly defines memory (memuse._type instanceof TypeMem || // Load-use indirectly defines memory @@ -188,10 +190,6 @@ public abstract class GlobalCodeMotion { assert late[st._nid]!=null; lca = anti_dep(load,late[st._nid],st.cfg0(),lca,st); break; - case NewNode st: - assert late[st._nid]!=null; - lca = anti_dep(load,late[st._nid],st.cfg0(),lca,st); - break; case PhiNode phi: // Repeat anti-dep for matching Phi inputs. // No anti-dep edges but may raise the LCA. @@ -199,6 +197,7 @@ public abstract class GlobalCodeMotion { if( phi.in(i)==load.mem() ) lca = anti_dep(load,phi.region().cfg(i),load.mem().cfg0(),lca,null); break; + case NewNode st: break; case LoadNode ld: break; // Loads do not cause anti-deps on other loads case ReturnNode ret: break; // Load must already be ahead of Return case ScopeMinNode ret: break; // Mem uses now on ScopeMin diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java index ac497fe8..235d2414 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java @@ -226,7 +226,7 @@ public class Parser { } // Parse the body - Node last=null; + Node last=ZERO; while (!peek('}') && !_lexer.isEOF()) last = parseStatement(); @@ -562,6 +562,9 @@ public class Parser { RegionNode r = ctrl(tScope.mergeScopes(fScope)); Node ret = peep(new PhiNode("",lhs._type.meet(rhs._type),r,lhs.unkeep(),rhs.unkeep())); + // Immediately fail e.g. `arg ? 7 : ptr` + if( !stmt && ret.err() !=null ) + throw error(ret.err()); r.peephole(); return ret; } @@ -938,6 +941,8 @@ public class Parser { else if( match(">>") ) lhs = new SarNode(lhs,null); else break; lhs.setDef(2,parseAddition()); + if( lhs.err() != null ) + throw error(lhs.err()); lhs = peep(lhs.widen()); } return lhs; @@ -973,7 +978,7 @@ public class Parser { * @return a multiply expression {@link Node}, never {@code null} */ private Node parseMultiplication() { - var lhs = parseUnary(); boolean mul; + var lhs = parseUnary(); while( true ) { if( false ) ; else if( match("*") ) lhs = new MulNode(lhs,null); @@ -1004,7 +1009,9 @@ public class Parser { if( n != null ) { if( n._final ) throw error("Cannot reassign final '"+n._name+"'"); - Node expr = zsMask(peep(new AddNode(_scope.in(n),con(delta))),n.type()); + Node expr = n.type() instanceof TypeFloat + ? peep(new AddFNode(_scope.in(n),con(TypeFloat.constant(-1)))) + : zsMask(peep(new AddNode(_scope.in(n),con(delta))),n.type()); _scope.update(n,expr); return expr; } @@ -1054,7 +1061,7 @@ public class Parser { // Widen RHS int to a RHS float rhs = widenInt(rhs,n.type()); // Complain a RHS float into a LHS int - if( !rhs._type.isa(n.type()) ) + if( !(rhs._type instanceof TypeInteger) && !rhs._type.isa(n.type()) ) throw error("Type " + rhs._type.str() + " is not of declared type " + n.type().str()); Node op = switch(ch) { @@ -1124,7 +1131,7 @@ public class Parser { } // Check that all fields are initialized for( int i=idx; i>"; } @Override public String glabel() { return ">>"; } - @Override - StringBuilder _print1(StringBuilder sb, BitSet visited) { - in(1)._print0(sb.append("("), visited); - in(2)._print0(sb.append(">>"), visited); - return sb.append(")"); - } - @Override public Type compute() { Type t1 = in(1)._type, t2 = in(2)._type; @@ -52,9 +46,4 @@ public class SarNode extends Node { return null; } @Override Node copy(Node lhs, Node rhs) { return new SarNode(lhs,rhs); } - @Override public String err() { - if( !(in(1)._type instanceof TypeInteger) ) return "Cannot '>>' " + in(1)._type; - if( !(in(2)._type instanceof TypeInteger) ) return "Cannot '>>' " + in(2)._type; - return null; - } } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/ShlNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/ShlNode.java index e454362a..24dff5e2 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/ShlNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ShlNode.java @@ -5,20 +5,14 @@ import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeInteger; import java.util.BitSet; -public class ShlNode extends Node { - public ShlNode(Node lhs, Node rhs) { super(null, lhs, rhs); } +public class ShlNode extends LogicalNode { + public ShlNode(Node lhs, Node rhs) { super(lhs, rhs); } @Override public String label() { return "Shl"; } + @Override public String op() { return "<<"; } @Override public String glabel() { return "<<"; } - @Override - StringBuilder _print1(StringBuilder sb, BitSet visited) { - in(1)._print0(sb.append("("), visited); - in(2)._print0(sb.append("<<"), visited); - return sb.append(")"); - } - @Override public Type compute() { Type t1 = in(1)._type, t2 = in(2)._type; @@ -56,9 +50,4 @@ public class ShlNode extends Node { return null; } @Override Node copy(Node lhs, Node rhs) { return new ShlNode(lhs,rhs); } - @Override public String err() { - if( !(in(1)._type instanceof TypeInteger) ) return "Cannot '<<' " + in(1)._type; - if( !(in(2)._type instanceof TypeInteger) ) return "Cannot '<<' " + in(2)._type; - return null; - } } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/ShrNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/ShrNode.java index 6f4a2c6c..52d2971d 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/ShrNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ShrNode.java @@ -4,20 +4,14 @@ import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeInteger; import java.util.BitSet; -public class ShrNode extends Node { - public ShrNode(Node lhs, Node rhs) { super(null, lhs, rhs); } +public class ShrNode extends LogicalNode { + public ShrNode(Node lhs, Node rhs) { super(lhs, rhs); } @Override public String label() { return "Shr"; } + @Override public String op() { return ">>>"; } @Override public String glabel() { return ">>>"; } - @Override - StringBuilder _print1(StringBuilder sb, BitSet visited) { - in(1)._print0(sb.append("("), visited); - in(2)._print0(sb.append(">>>"), visited); - return sb.append(")"); - } - @Override public Type compute() { Type t1 = in(1)._type, t2 = in(2)._type; diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/XorNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/XorNode.java index c140ba83..a23e1304 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/XorNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/XorNode.java @@ -5,20 +5,14 @@ import com.seaofnodes.simple.type.TypeInteger; import java.util.BitSet; -public class XorNode extends Node { - public XorNode(Node lhs, Node rhs) { super(null, lhs, rhs); } +public class XorNode extends LogicalNode { + public XorNode(Node lhs, Node rhs) { super(lhs, rhs); } @Override public String label() { return "Xor"; } + @Override public String op() { return "^"; } @Override public String glabel() { return "^"; } - @Override - StringBuilder _print1(StringBuilder sb, BitSet visited) { - in(1)._print0(sb.append("("), visited); - in(2)._print0(sb.append("^"), visited); - return sb.append(")"); - } - @Override public Type compute() { Type t1 = in(1)._type, t2 = in(2)._type; @@ -57,9 +51,4 @@ public class XorNode extends Node { return null; } @Override Node copy(Node lhs, Node rhs) { return new XorNode(lhs,rhs); } - @Override public String err() { - if( !(in(1)._type instanceof TypeInteger) ) return "Cannot '^' " + in(1)._type; - if( !(in(2)._type instanceof TypeInteger) ) return "Cannot '^' " + in(2)._type; - return null; - } } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMem.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMem.java index 60b3612f..9438abe2 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMem.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMem.java @@ -44,6 +44,7 @@ public class TypeMem extends Type { return make(_alias,_t.dual()); } + @Override public boolean isHigh() { return _t.isHigh(); } @Override public Type glb() { return make(_alias,_t.glb()); } @Override int hash() { return 9876543 + _alias + _t.hashCode(); } -- cgit v1.2.3