summaryrefslogtreecommitdiff
path: root/chapter14/src
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-09-22 11:25:05 -0700
committerCliff Click <cliffc@acm.org>2026-09-22 11:25:05 -0700
commit29fb671e69f90ad3b04c6fa8d746caf857f89e77 (patch)
tree2f39d082f8a6de6a2b60b66406f8c9f0190d25c2 /chapter14/src
parent1d961838cff168a101069d08a8ab6594f49f0911 (diff)
downloadSimple-29fb671e69f90ad3b04c6fa8d746caf857f89e77.tar.gz
Simple-29fb671e69f90ad3b04c6fa8d746caf857f89e77.zip
Add shared graph viewer to all chapters
Diffstat (limited to 'chapter14/src')
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/GraphVisualizer.java280
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/IterPeeps.java8
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/Parser.java23
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/AddFNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/AddNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/BoolNode.java3
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/DivFNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/DivNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/LoadNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/MinusFNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/MinusNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/MulFNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/MulNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/NewNode.java3
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/Node.java29
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/NotNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/OrNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/PhiNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/SarNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/ShlNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/ShrNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/StopNode.java9
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/StoreNode.java1
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/SubFNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/SubNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/node/XorNode.java2
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java62
-rw-r--r--chapter14/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java43
-rw-r--r--chapter14/src/test/java/com/seaofnodes/simple/Chapter10Test.java10
-rw-r--r--chapter14/src/test/java/com/seaofnodes/simple/Chapter11Test.java8
-rw-r--r--chapter14/src/test/java/com/seaofnodes/simple/Chapter12Test.java8
-rw-r--r--chapter14/src/test/java/com/seaofnodes/simple/Chapter13Test.java16
-rw-r--r--chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java38
36 files changed, 181 insertions, 402 deletions
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/GraphVisualizer.java b/chapter14/src/main/java/com/seaofnodes/simple/GraphVisualizer.java
deleted file mode 100644
index 604770a4..00000000
--- a/chapter14/src/main/java/com/seaofnodes/simple/GraphVisualizer.java
+++ /dev/null
@@ -1,280 +0,0 @@
-package com.seaofnodes.simple;
-
-import com.seaofnodes.simple.Parser;
-import com.seaofnodes.simple.node.*;
-
-import java.util.*;
-
-/**
- * Simple visualizer that outputs GraphViz dot format.
- * The dot output must be saved to a file and run manually via dot to generate the SVG output.
- * Currently, this is done manually.
- */
-public class GraphVisualizer {
-
- /**
- * If set to true we put the control nodes in a separate cluster from
- * data nodes.
- */
- boolean _separateControlCluster = false;
-
- public GraphVisualizer(boolean separateControlCluster) { this._separateControlCluster = separateControlCluster; }
- public GraphVisualizer() { this(false); }
-
- public String generateDotOutput(Parser parse) { return generateDotOutput(parse.STOP,parse._scope,parse._xScopes); }
- public String generateDotOutput(StopNode stop, Node scope, Stack<ScopeNode> xScopes) {
-
- // Since the graph has cycles, we need to create a flat list of all the
- // nodes in the graph.
- Collection<Node> all = findAll(stop, scope);
- StringBuilder sb = new StringBuilder();
- sb.append("digraph chapter11 {\n");
- sb.append("/*\n");
- sb.append(stop._src);
- sb.append("\n*/\n");
-
- // To keep the Scopes below the graph and pointing up into the graph we
- // need to group the Nodes in a subgraph cluster, and the scopes into a
- // different subgraph cluster. THEN we can draw edges between the
- // scopes and nodes. If we try to cross subgraph cluster borders while
- // still making the subgraphs DOT gets confused.
- sb.append("\trankdir=BT;\n"); // Force Nodes before Scopes
-
- // CNC - turned off Apr/8/2024, gives more flex in the layout and
- // removes some of the more ludicrous layout choices.
- // Preserve node input order
- //sb.append("\tordering=\"in\";\n");
-
- // Merge multiple edges hitting the same node. Makes common shared
- // nodes much prettier to look at.
- sb.append("\tconcentrate=\"true\";\n");
-
- // Force nested scopes to order
- sb.append("\tcompound=\"true\";\n");
-
- // Just the Nodes first, in a cluster no edges
- nodes(sb, all);
-
- // Now the scopes, in a cluster no edges
- if( xScopes != null )
- for( ScopeNode xscope : xScopes )
- if( !xscope.isDead() )
- scope( sb, xscope );
-
- // Walk the Node edges
- nodeEdges(sb, all);
-
- // Walk the active Scope edges
- if( xScopes != null )
- for( ScopeNode xscope : xScopes )
- if( !xscope.isDead() )
- scopeEdges( sb, xscope );
-
- sb.append("}\n");
- return sb.toString();
- }
-
- private void nodesByCluster(StringBuilder sb, boolean doCtrl, Collection<Node> all) {
- if (!_separateControlCluster && doCtrl) // all nodes in 1 cluster
- return;
- // Just the Nodes first, in a cluster no edges
- sb.append(doCtrl ? "\tsubgraph cluster_Controls {\n" : "\tsubgraph cluster_Nodes {\n"); // Magic "cluster_" in the subgraph name
- for (Node n : all) {
- if (n instanceof ProjNode || n instanceof CProjNode || n instanceof ScopeNode || n==Parser.XCTRL)
- continue; // Do not emit, rolled into MultiNode or Scope cluster already
- if (_separateControlCluster && doCtrl && !n.isCFG()) continue;
- if (_separateControlCluster && !doCtrl && n.isCFG()) continue;
- sb.append("\t\t").append(n.uniqueName()).append(" [ ");
- String lab = n.glabel();
- if (n instanceof MultiNode) {
- // Make a box with the MultiNode on top, and all the projections on the bottom
- sb.append("shape=plaintext label=<\n");
- sb.append("\t\t\t<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">\n");
- sb.append("\t\t\t<TR><TD BGCOLOR=\"yellow\">").append(lab).append("</TD></TR>\n");
- sb.append("\t\t\t<TR>");
- boolean doProjTable = false;
- for (Node use : n._outputs) {
- if (use instanceof ProjNode proj) {
- if (!doProjTable) {
- doProjTable = true;
- sb.append("<TD>").append("\n");
- sb.append("\t\t\t\t<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">").append("\n");
- sb.append("\t\t\t\t<TR>");
- }
- sb.append("<TD PORT=\"p").append(proj._idx).append("\">").append(proj.glabel()).append("</TD>");
- }
- if (use instanceof CProjNode proj) {
- if (!doProjTable) {
- doProjTable = true;
- sb.append("<TD>").append("\n");
- sb.append("\t\t\t\t<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">").append("\n");
- sb.append("\t\t\t\t<TR>");
- }
- sb.append("<TD PORT=\"p").append(proj._idx).append("\" BGCOLOR=\"yellow\">").append(proj.glabel()).append("</TD>");
- }
- }
- if (doProjTable) {
- sb.append("</TR>").append("\n");
- sb.append("\t\t\t\t</TABLE>").append("\n");
- sb.append("\t\t\t</TD>");
- }
- sb.append("</TR>\n");
- sb.append("\t\t\t</TABLE>>\n\t\t");
-
- } else {
- // control nodes have box shape
- // other nodes are ellipses, i.e. default shape
- if (n.isCFG()) sb.append("shape=box style=filled fillcolor=yellow ");
- else if (n instanceof PhiNode) sb.append("style=filled fillcolor=lightyellow ");
- sb.append("label=\"").append(lab).append("\" ");
- }
- sb.append("];\n");
- }
- if (!_separateControlCluster) {
- // Force Region & Phis to line up
- for (Node n : all) {
- if (n instanceof RegionNode region) {
- sb.append("\t\t{ rank=same; ");
- sb.append(region).append(";");
- for (Node phi : region._outputs)
- if (phi instanceof PhiNode) sb.append(phi.uniqueName()).append(";");
- sb.append("}\n");
- }
- }
- }
- sb.append("\t}\n"); // End Node cluster
- }
-
- private void nodes(StringBuilder sb, Collection<Node> all) {
- nodesByCluster(sb, true, all);
- nodesByCluster(sb, false, all);
- }
-
- // Build a nested scope display, walking the _prev edge
- private void scope( StringBuilder sb, ScopeNode scope ) {
- sb.append("\tnode [shape=plaintext];\n");
- int level=1;
- for( int idx = scope._scopes.size()-1; idx>=0; idx-- ) {
- var syms = scope._scopes.get(idx);
- String scopeName = makeScopeName(scope, level);
- sb.append("\tsubgraph cluster_").append(scopeName).append(" {\n"); // Magic "cluster_" in the subgraph name
- sb.append("\t\t").append(scopeName).append(" [label=<\n");
- sb.append("\t\t\t<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n");
- // Add the scope level
- int scopeLevel = scope._scopes.size()-level;
- sb.append("\t\t\t<TR><TD BGCOLOR=\"cyan\">").append(scopeLevel).append("</TD>");
- for(String name: syms.keySet())
- sb.append("<TD PORT=\"").append(makePortName(scopeName, name)).append("\">").append(name).append("</TD>");
- sb.append("</TR>\n");
- sb.append("\t\t\t</TABLE>>];\n");
- level++;
- }
- // Scope clusters nest, so the graphics shows the nested scopes, so
- // they are not closed as they are printed; so they just keep nesting.
- // We close them all at once here.
- sb.append( "\t}\n".repeat( level-1 ) ); // End all Scope clusters
- }
-
- private String makeScopeName(ScopeNode sn, int level) { return sn.uniqueName() + "_" + level; }
- private String makePortName(String scopeName, String varName) { return scopeName + "_" + varName; }
-
- // Walk the node edges
- private void nodeEdges(StringBuilder sb, Collection<Node> all) {
- // All them edge labels
- sb.append("\tedge [ fontname=Helvetica, fontsize=8 ];\n");
- for( Node n : all ) {
- // Do not display the Constant->Start edge;
- // ProjNodes handled by Multi;
- // ScopeNodes are done separately
- if( n instanceof ConstantNode || n instanceof ProjNode || n instanceof CProjNode || n instanceof ScopeNode || n==Parser.XCTRL )
- continue;
- for( int i=0; i<n.nIns(); i++ ) {
- Node def = n.in(i);
- if( n instanceof PhiNode && def instanceof RegionNode ) {
- // Draw a dotted use->def edge from Phi to Region.
- sb.append('\t').append(n.uniqueName());
- sb.append(" -> ");
- sb.append(def.uniqueName());
- sb.append(" [style=dotted taillabel=").append(i).append("];\n");
- } else if( def != null ) {
- // Most edges land here use->def
- sb.append('\t').append(n.uniqueName()).append(" -> ");
- if( def instanceof CProjNode proj ) {
- String mname = proj.ctrl().uniqueName();
- sb.append(mname).append(":p").append(proj._idx);
- } else if( def instanceof ProjNode proj ) {
- String mname = proj.in(0).uniqueName();
- sb.append(mname).append(":p").append(proj._idx);
- } else sb.append(def.uniqueName());
- // Number edges, so we can see how they track
- sb.append("[taillabel=").append(i);
- // The edge from New to ctrl is just for anchoring the New
- if ( n instanceof NewNode )
- sb.append(" color=green");
- // control edges are colored red
- else if( def.isCFG() )
- sb.append(" color=red");
- else if( def.isMem() )
- sb.append(" color=blue");
- // Backedges do not add a ranking constraint
- if( i==2 && (n instanceof PhiNode || n instanceof LoopNode) )
- sb.append(" constraint=false");
- sb.append("];\n");
- }
- }
- }
- }
-
- // Walk the scope edges
- private void scopeEdges( StringBuilder sb, ScopeNode scope ) {
- sb.append("\tedge [style=dashed color=cornflowerblue];\n");
- int level=1;
- for( int i = scope._scopes.size()-1; i>=0; i-- ) {
- var syms = scope._scopes.get(i);
- String scopeName = makeScopeName(scope, level);
- for( String name : syms.keySet() ) {
- int idx = syms.get(name);
- Node def = scope.in(idx);
- while( def instanceof ScopeNode lazy )
- def = lazy.in(idx);
- if( def==null ) continue;
- sb.append("\t")
- .append(scopeName).append(":")
- .append('"').append(makePortName(scopeName, name)).append('"') // wrap port name with quotes because $ctrl is not valid unquoted
- .append(" -> ");
- if( def instanceof CProjNode proj ) {
- String mname = proj.ctrl().uniqueName();
- sb.append(mname).append(":p").append(proj._idx);
- } else sb.append(def.uniqueName());
- sb.append(";\n");
- }
- level++;
- }
- }
-
- /**
- * Finds all nodes in the graph.
- */
- private Collection<Node> findAll(Node stop, Node scope) {
- final HashMap<Integer, Node> all = new HashMap<>();
- for( Node n : stop._inputs )
- walk(all, n);
- if( scope != null )
- for( Node n : scope._inputs )
- walk(all, n);
- return all.values();
- }
-
- /**
- * Walk a subgraph and populate distinct nodes in the all list.
- */
- private void walk(HashMap<Integer,Node> all, Node n) {
- if(n == null ) return;
- if (all.get(n._nid) != null) return; // Been there, done that
- all.put(n._nid, n);
- for (Node c : n._inputs)
- walk(all, c);
- for( Node c : n._outputs )
- walk(all, c);
- }
-}
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/IterPeeps.java b/chapter14/src/main/java/com/seaofnodes/simple/IterPeeps.java
index 783fc4f1..7075d526 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/IterPeeps.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/IterPeeps.java
@@ -65,9 +65,14 @@ public abstract class IterPeeps {
while( (n=WORK.pop()) != null ) {
if( n.isDead() ) continue;
cnt++; // Useful for debugging, searching which peephole broke things
+ var obs = Parser.PARSER == null ? null : Parser.PARSER._obs;
+ if( obs != null ) obs.before(n);
Node x = n.peepholeOpt();
if( x != null ) {
- if( x.isDead() ) continue;
+ if( x.isDead() ) {
+ if( obs != null ) obs.after(n, x, true);
+ continue;
+ }
// peepholeOpt can return brand-new nodes, needing an initial type set
if( x._type==null ) x.setType(x.compute());
// Changes require neighbors onto the worklist
@@ -90,6 +95,7 @@ public abstract class IterPeeps {
}
if( n.isUnused() && !(n instanceof StopNode) )
n.kill(); // Just plain dead
+ if( obs != null ) obs.after(n, x, true);
}
return stop;
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/Parser.java b/chapter14/src/main/java/com/seaofnodes/simple/Parser.java
index 9e4b9eb6..5d7d67da 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/Parser.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple;
+import com.seaofnodes.graph.GraphObserver;
+
import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.type.*;
@@ -14,6 +16,12 @@ import java.util.*;
*/
public class Parser {
+ // Current compilation context; the observer belongs to the parser.
+ public static Parser PARSER;
+ public GraphObserver<Node> _obs;
+ public int pos() { return _lexer._position; }
+
+
/**
* A Global Static, unique to each compilation. This is a public, so we
* can make constants everywhere without having to thread the StartNode
@@ -93,6 +101,7 @@ public class Parser {
public static HashMap<String, Type> TYPES = new HashMap<>();
public Parser(String source, TypeInteger arg) {
+ PARSER = this;
Node.reset();
IterPeeps.reset();
TYPES.clear();
@@ -136,8 +145,7 @@ public class Parser {
private Node ctrl(Node n) { return _scope.ctrl(n); }
- public StopNode parse() { return parse(false); }
- public StopNode parse(boolean show) {
+ public StopNode parse() {
_xScopes.push(_scope);
// Enter a new scope for the initial control and arguments
_scope.push();
@@ -150,7 +158,6 @@ public class Parser {
_xScopes.pop();
if (!_lexer.isEOF()) throw error("Syntax error, unexpected " + _lexer.getAnyNextToken());
STOP.peephole();
- if( show ) showGraph();
return STOP;
}
@@ -190,7 +197,6 @@ public class Parser {
else if (matchx("break") ) return parseBreak();
else if (matchx("continue")) return parseContinue();
else if (matchx("struct") ) return parseStruct();
- else if (matchx("#showGraph")) return require(showGraph(),";");
else if (matchx(";") ) return null; // Empty statement
// declarations of vars with struct type are handled in parseExpressionStatement due
// to ambiguity
@@ -409,14 +415,7 @@ public class Parser {
return ret;
}
- /**
- * Dumps out the node graph
- * @return {@code null}
- */
- Node showGraph() {
- System.out.println(new GraphVisualizer().generateDotOutput(STOP,_scope,_xScopes));
- return null;
- }
+
/**
* Parses an expression statement or a declaration statement where type is a struct
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/AddFNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/AddFNode.java
index 7d4e2910..5d0a473a 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/AddFNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/AddFNode.java
@@ -10,8 +10,6 @@ public class AddFNode extends Node {
@Override public String label() { return "AddF"; }
- @Override public String glabel() { return "+"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/AddNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/AddNode.java
index bd1a9dcd..31332722 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/AddNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/AddNode.java
@@ -9,8 +9,6 @@ public class AddNode extends Node {
@Override public String label() { return "Add"; }
- @Override public String glabel() { return "+"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java
index 350859db..8afb14b1 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/AndNode.java
@@ -10,8 +10,6 @@ public class AndNode extends Node {
@Override public String label() { return "And"; }
- @Override public String glabel() { return "&"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/BoolNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/BoolNode.java
index ae042f30..b504712f 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/BoolNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/BoolNode.java
@@ -22,9 +22,6 @@ abstract public class BoolNode extends Node {
public String label() { return getClass().getSimpleName(); }
@Override
- public String glabel() { return op(); }
-
- @Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
in(2)._print0(sb.append(op()), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/DivFNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/DivFNode.java
index 36fd4524..6c0c2eb3 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/DivFNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/DivFNode.java
@@ -10,8 +10,6 @@ public class DivFNode extends Node {
@Override public String label() { return "DivF"; }
- @Override public String glabel() { return "/"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/DivNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/DivNode.java
index da9571db..fd5fd1ed 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/DivNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/DivNode.java
@@ -10,8 +10,6 @@ public class DivNode extends Node {
@Override public String label() { return "Div"; }
- @Override public String glabel() { return "//"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/LoadNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/LoadNode.java
index 78ccc8a9..2db5e469 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/LoadNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/LoadNode.java
@@ -23,8 +23,6 @@ public class LoadNode extends MemOpNode {
}
@Override public String label() { return _name; }
- @Override public String glabel() { return "."+_name; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) { return sb.append(".").append(_name); }
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/MinusFNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/MinusFNode.java
index 9727f58b..7cacf2c9 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/MinusFNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/MinusFNode.java
@@ -10,8 +10,6 @@ public class MinusFNode extends Node {
@Override public String label() { return "MinusF"; }
- @Override public String glabel() { return "-"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("(-"), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/MinusNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/MinusNode.java
index 8ba45d26..27b4a478 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/MinusNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/MinusNode.java
@@ -10,8 +10,6 @@ public class MinusNode extends Node {
@Override public String label() { return "Minus"; }
- @Override public String glabel() { return "-"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("(-"), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/MulFNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/MulFNode.java
index 2d44a9fb..4b753ba7 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/MulFNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/MulFNode.java
@@ -10,8 +10,6 @@ public class MulFNode extends Node {
@Override public String label() { return "MulF"; }
- @Override public String glabel() { return "*"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/MulNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/MulNode.java
index 6f679462..f521f2ce 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/MulNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/MulNode.java
@@ -10,8 +10,6 @@ public class MulNode extends Node {
@Override public String label() { return "Mul"; }
- @Override public String glabel() { return "*"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/NewNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/NewNode.java
index c00fee62..1c82d5f5 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/NewNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/NewNode.java
@@ -18,9 +18,6 @@ public class NewNode extends Node {
public String label() { return "new"; }
@Override
- public String glabel() { return "new " + _ptr._obj._name; }
-
- @Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
sb.append("new ");
return sb.append(_ptr._obj.str());
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter14/src/main/java/com/seaofnodes/simple/node/Node.java
index 3956ed6b..d917893d 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/Node.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/Node.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.simple.Parser;
+
import com.seaofnodes.simple.IRPrinter;
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.Utils;
@@ -72,17 +74,11 @@ public abstract class Node implements OutNode {
// Easy reading label for debugger, e.g. "Add" or "Region" or "EQ"
public abstract String label();
- // Unique label for graph visualization, e.g. "Add12" or "Region30" or "EQ99"
+ // Unique label for debugging, e.g. "Add12" or "Region30" or "EQ99"
public String uniqueName() {
- // Get rid of $ as graphviz doesn't like it
- String label = label().replaceAll("\\$", "");
- return label + _nid;
+ return label() + _nid;
}
- // Graphical label, e.g. "+" or "Region" or "=="
- public String glabel() { return label(); }
-
-
// ------------------------------------------------------------------------
// Debugger Printing.
@@ -286,13 +282,14 @@ public abstract class Node implements OutNode {
* Try to peephole at this node and return a better replacement Node.
* Always returns some not-null Node (often this).
*/
- public final Node peephole( ) {
- if (_disablePeephole) {
- _type = compute();
- return this; // Peephole optimizations turned off
- }
+ public final Node peephole() {
+ if( _disablePeephole ) { _type = compute(); return this; }
+ var obs = IterPeeps.midAssert() ? null : Parser.PARSER == null ? null : Parser.PARSER._obs;
+ if( obs != null ) obs.before(this);
Node n = peepholeOpt();
- return n==null ? this : deadCodeElim(n.peephole()); // Cannot return null for no-progress
+ Node rez = n == null ? this : deadCodeElim(n.peephole());
+ if( obs != null ) obs.after(this, n == null ? null : rez, false);
+ return rez;
}
/**
@@ -450,6 +447,8 @@ public abstract class Node implements OutNode {
// retry the peephole. Track a set of Nodes dependent on `this`, and
// revisit them if `this` changes.
ArrayList<Node> _deps;
+ public int nDeps() { return _deps == null ? 0 : _deps.size(); }
+ public Node dep(int idx) { return _deps.get(idx); }
/**
* Add a node to the list of dependencies. Only add it if its not an input
@@ -460,6 +459,8 @@ public abstract class Node implements OutNode {
// Running peepholes during the big assert cannot have side effects
// like adding dependencies.
if( IterPeeps.midAssert() ) return this;
+ var obs = IterPeeps.midAssert() ? null : Parser.PARSER == null ? null : Parser.PARSER._obs;
+ if( obs != null ) obs.dep(this, dep);
if( _deps==null ) _deps = new ArrayList<>();
if( Utils.find(_deps ,dep) != -1 ) return this; // Already on list
if( Utils.find(_inputs,dep) != -1 ) return this; // No need for deps on immediate neighbors
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/NotNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/NotNode.java
index b3c77c45..3ef5d19e 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/NotNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/NotNode.java
@@ -9,8 +9,6 @@ public class NotNode extends Node {
@Override public String label() { return "Not"; }
- @Override public String glabel() { return "!"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("(!"), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/OrNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/OrNode.java
index e18996b7..fd5be78e 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/OrNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/OrNode.java
@@ -10,8 +10,6 @@ public class OrNode extends Node {
@Override public String label() { return "Or"; }
- @Override public String glabel() { return "|"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/PhiNode.java
index 42f8c86e..1d4b3fba 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/PhiNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/PhiNode.java
@@ -18,8 +18,6 @@ public class PhiNode extends Node {
@Override public String label() { return "Phi_"+_label; }
- @Override public String glabel() { return "&phi;_"+_label; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
if( !(region() instanceof RegionNode r) || r.inProgress() )
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java
index 44d3a587..3dd7cbf0 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java
@@ -10,8 +10,6 @@ public class RoundF32Node extends Node {
@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(")");
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/SarNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/SarNode.java
index 881a3812..6436cd64 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/SarNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/SarNode.java
@@ -10,8 +10,6 @@ public class SarNode extends Node {
@Override public String label() { return "Sar"; }
- @Override public String glabel() { return ">>"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/ShlNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/ShlNode.java
index 605c5d86..1bed5264 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/ShlNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/ShlNode.java
@@ -10,8 +10,6 @@ public class ShlNode extends Node {
@Override public String label() { return "Shl"; }
- @Override public String glabel() { return "<<"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/ShrNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/ShrNode.java
index bed18d2b..26442c29 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/ShrNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/ShrNode.java
@@ -10,8 +10,6 @@ public class ShrNode extends Node {
@Override public String label() { return "Shr"; }
- @Override public String glabel() { return ">>>"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/StopNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/StopNode.java
index d5b00011..aed4a8e6 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/StopNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/StopNode.java
@@ -3,7 +3,6 @@ package com.seaofnodes.simple.node;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.GlobalCodeMotion;
-import com.seaofnodes.simple.GraphVisualizer;
import java.util.BitSet;
@@ -69,18 +68,16 @@ public class StopNode extends CFGNode {
return addDef(node);
}
- public StopNode iterate( ) { return IterPeeps.iterate(this).typeCheck().GCM(false); }
- public StopNode iterate(boolean show) { return IterPeeps.iterate(this).typeCheck().GCM(show ); }
+ public StopNode iterate() { return IterPeeps.iterate(this).typeCheck().GCM(); }
StopNode typeCheck() {
String err = walk( Node::err );
if( err != null ) throw new RuntimeException(err);
return this;
}
- StopNode GCM(boolean show) {
+ StopNode GCM() {
// Break infinite loops, forcing a Never-branch to exit
GlobalCodeMotion.fixLoops(this);
- if( show )
- System.out.println(new GraphVisualizer().generateDotOutput(this,null,null));
+
GlobalCodeMotion.buildCFG(this);
return this;
}
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/StoreNode.java
index 57e8b3ad..142aebc3 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/StoreNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/StoreNode.java
@@ -25,7 +25,6 @@ public class StoreNode extends MemOpNode {
}
@Override public String label() { return "." +_name+"="; }
- @Override public String glabel() { return "." +_name+"="; }
@Override public boolean isMem() { return true; }
public Node val() { return in(3); }
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/SubFNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/SubFNode.java
index b591718d..27bbda8d 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/SubFNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/SubFNode.java
@@ -10,8 +10,6 @@ public class SubFNode extends Node {
@Override public String label() { return "SubF"; }
- @Override public String glabel() { return "-"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/SubNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/SubNode.java
index 6d2f1711..45c4817c 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/SubNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/SubNode.java
@@ -11,8 +11,6 @@ public class SubNode extends Node {
@Override public String label() { return "Sub"; }
- @Override public String glabel() { return "-"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
index 1d147cf6..fde483d6 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
@@ -11,8 +11,6 @@ public class ToFloatNode extends Node {
@Override public String label() { return "ToFloat"; }
- @Override public String glabel() { return "(flt)"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
return in(1)._print0(sb.append("(flt)"), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/XorNode.java b/chapter14/src/main/java/com/seaofnodes/simple/node/XorNode.java
index 3978f048..6b3bbec5 100644
--- a/chapter14/src/main/java/com/seaofnodes/simple/node/XorNode.java
+++ b/chapter14/src/main/java/com/seaofnodes/simple/node/XorNode.java
@@ -10,8 +10,6 @@ public class XorNode extends Node {
@Override public String label() { return "Xor"; }
- @Override public String glabel() { return "^"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
in(1)._print0(sb.append("("), visited);
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java b/chapter14/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
new file mode 100644
index 00000000..39f79e69
--- /dev/null
+++ b/chapter14/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
@@ -0,0 +1,62 @@
+package com.seaofnodes.simple.print;
+
+import com.seaofnodes.graph.GraphAdapter;
+import com.seaofnodes.graph.GraphSnapshot;
+import com.seaofnodes.graph.GraphSnapshot.*;
+import com.seaofnodes.simple.node.*;
+import com.seaofnodes.simple.node.Node;
+import com.seaofnodes.simple.type.TypeMem;
+import java.util.ArrayList;
+
+/** Chapter 14's view of the IR; browser, transport and layout are shared. */
+public class SimpleGraphAdapter extends GraphAdapter<Node> {
+ @Override protected boolean dead(Node n) { return n.isDead(); }
+ @Override protected int id(Node n) { return n._nid; }
+ @Override protected int nIns(Node n) { return n.nIns(); }
+ @Override protected Node in(Node n, int idx) { return n.in(idx); }
+ @Override protected int nOuts(Node n) { return n.nOuts(); }
+ @Override protected Node out(Node n, int idx) { return n.out(idx); }
+ @Override protected int nDeps(Node n) { return n.nDeps(); }
+ @Override protected Node dep(Node n, int idx) { return n.dep(idx); }
+
+ private ArrayList<Edge> edges(Node n) {
+ var edges = new ArrayList<Edge>();
+ String[] names = n instanceof ScopeNode scope && n.nIns() != 0 ? scope.reverseNames() : null;
+ for( int i = 0; i < n.nIns(); i++ ) {
+ String name = names == null || i >= names.length ? null : names[i];
+ edges.add(new Edge(i, ref(n.in(i)), role(n, i), name));
+ }
+ return edges;
+ }
+
+ @Override protected GraphSnapshot.Node desc(Node n) {
+ Projection proj = n instanceof ProjNode p ? new Projection(ref(n.in(0)), p._idx)
+ : n instanceof CProjNode p ? new Projection(ref(n.in(0)), p._idx) : null;
+ String label = n.label();
+ return new GraphSnapshot.Node(n._nid, label == null ? n.getClass().getSimpleName() : label,
+ n._type == null ? null : n._type.toString(), kind(n), edges(n), proj);
+ }
+
+ private Kind kind(Node n) {
+ if( n instanceof ScopeNode ) return Kind.SCOPE;
+ if( n instanceof StartNode ) return Kind.CTRL;
+ if( n instanceof LoopNode ) return Kind.LOOP;
+ if( n instanceof RegionNode ) return Kind.REGION;
+ if( n instanceof PhiNode ) return Kind.PHI;
+ return n.isCFG() ? Kind.CTRL : isMem(n) ? Kind.MEM : Kind.DATA;
+ }
+
+ private Role role(Node n, int i) {
+ if( n instanceof ScopeNode || n instanceof ConstantNode || n instanceof XCtrlNode ) return Role.ASSOC;
+ if( n instanceof PhiNode ) return i == 0 ? Role.ASSOC : isMem(n) ? Role.MEM : Role.DATA;
+ if( n instanceof ProjNode || n instanceof CProjNode ) return n.isCFG() ? Role.CTRL : isMem(n) ? Role.MEM : Role.DATA;
+ if( n instanceof RegionNode && i == 0 ) return Role.ASSOC;
+ if( i == 0 || n instanceof RegionNode || n instanceof StopNode ) return Role.CTRL;
+ if( i == 1 && (n instanceof MemOpNode || n instanceof ReturnNode) ) return Role.MEM;
+ Node def = n.in(i);
+ if( def != null && isMem(def) ) return Role.MEM;
+ return Role.DATA;
+ }
+
+ private boolean isMem(Node n) { return n.isMem() || n._type instanceof TypeMem; }
+}
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java b/chapter14/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java
new file mode 100644
index 00000000..5db8c01e
--- /dev/null
+++ b/chapter14/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java
@@ -0,0 +1,43 @@
+package com.seaofnodes.simple.print;
+
+import com.seaofnodes.graph.GraphCapture;
+import com.seaofnodes.graph.GraphViewer;
+import com.seaofnodes.simple.Parser;
+import com.seaofnodes.simple.node.Node;
+import java.util.ArrayList;
+import java.io.IOException;
+
+/** Chapter 14's compilation context; capture and event bookkeeping are shared. */
+public class SimpleGraphObserver extends GraphCapture<Node> {
+ private Parser _parser;
+ private Node _ret;
+ private String _phase;
+ public SimpleGraphObserver() { super(new SimpleGraphAdapter()); }
+ public static void main(String[] args) throws IOException {
+ GraphViewer.run(new SimpleGraphObserver());
+ }
+ @Override protected void compile(String src) {
+ _parser = new Parser(src);
+ _parser._obs = this;
+ _phase = "Parse";
+ _ret = _parser.parse();
+ phase(_phase);
+ _phase = "Iter";
+ com.seaofnodes.simple.IterPeeps.iterate(_parser.STOP);
+ phase(_phase);
+ }
+ @Override protected String phase() { return _phase; }
+ @Override protected int pos() { return "Parse".equals(_phase) ? _parser.pos() : -1; }
+ @Override protected void detach() {
+ if( _parser != null ) _parser._obs = null;
+ _parser = null;
+ _ret = null;
+ }
+ @Override protected void roots(ArrayList<Node> roots) {
+ roots.add(Parser.START);
+ roots.add(_parser.STOP);
+ roots.add(_parser._scope);
+ roots.addAll(_parser._xScopes);
+ roots.add(_ret);
+ }
+}
diff --git a/chapter14/src/test/java/com/seaofnodes/simple/Chapter10Test.java b/chapter14/src/test/java/com/seaofnodes/simple/Chapter10Test.java
index 31220334..cfe677ec 100644
--- a/chapter14/src/test/java/com/seaofnodes/simple/Chapter10Test.java
+++ b/chapter14/src/test/java/com/seaofnodes/simple/Chapter10Test.java
@@ -81,7 +81,7 @@ if( (arg/13)==0 ) {
int r = g+h;
return p-r;
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return 0;", stop.toString());
}
@@ -101,7 +101,7 @@ bar.a = 1;
bar.a = 2;
return bar.a;
""");
- StopNode stop = parser.parse(false).iterate();
+ StopNode stop = parser.parse().iterate();
assertEquals("return 2;", stop.toString());
}
@@ -155,7 +155,7 @@ while (arg) {
}
return bar.a;
""");
- StopNode stop = parser.parse(false).iterate();
+ StopNode stop = parser.parse().iterate();
assertEquals("return Phi(Loop12,0,(Phi_a+2));", stop.toString());
}
@@ -207,7 +207,7 @@ if (arg) bar = null;
if( bar ) bar.a = 1;
return bar;
""");
- StopNode stop = parser.parse(false).iterate();
+ StopNode stop = parser.parse().iterate();
assertEquals("return Phi(Region31,(*void)Phi(Region19,null,new Bar),null);", stop.toString());
}
@@ -223,7 +223,7 @@ if( !bar ) rez=4;
else bar.a = 1;
return rez;
""");
- StopNode stop = parser.parse(false).iterate();
+ StopNode stop = parser.parse().iterate();
assertEquals("return Phi(Region37,4,3);", stop.toString());
}
diff --git a/chapter14/src/test/java/com/seaofnodes/simple/Chapter11Test.java b/chapter14/src/test/java/com/seaofnodes/simple/Chapter11Test.java
index 4bfc25f4..58a11ba5 100644
--- a/chapter14/src/test/java/com/seaofnodes/simple/Chapter11Test.java
+++ b/chapter14/src/test/java/com/seaofnodes/simple/Chapter11Test.java
@@ -306,7 +306,7 @@ else {
}
}
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("Stop[ return 9; return 0; return 0; return 0; ]", stop.toString());
}
@@ -466,7 +466,7 @@ while (arg) {
}
return i;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return .f;", stop.toString());
}
@@ -486,7 +486,7 @@ while(arg) {
}
return arg;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return Phi(Loop15,arg,Phi(Region37,.f,0));", stop.toString());
}
@@ -504,7 +504,7 @@ if (arg) {
}
return v;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return new S;", stop.toString());
}
diff --git a/chapter14/src/test/java/com/seaofnodes/simple/Chapter12Test.java b/chapter14/src/test/java/com/seaofnodes/simple/Chapter12Test.java
index 61b1f490..c8802f4c 100644
--- a/chapter14/src/test/java/com/seaofnodes/simple/Chapter12Test.java
+++ b/chapter14/src/test/java/com/seaofnodes/simple/Chapter12Test.java
@@ -28,7 +28,7 @@ public class Chapter12Test {
"""
return 3.14;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return 3.14;", stop.toString());
assertEquals(3.14, Evaluator.evaluate(stop, 0));
}
@@ -39,7 +39,7 @@ return 3.14;
"""
return 3.14;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return 3.14;", stop.toString());
assertEquals(3.14, Evaluator.evaluate(stop, 0));
}
@@ -56,7 +56,7 @@ while( 1 ) {
}
return guess;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return Phi(Loop9,(flt)arg,(((ToFloat/Phi_guess)+Phi_guess)/2.0));", stop.toString());
assertEquals(3.0, Evaluator.evaluate(stop, 9));
assertEquals(1.414213562373095, Evaluator.evaluate(stop, 2));
@@ -69,7 +69,7 @@ return guess;
flt x = arg;
return x+1==x;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return ((flt)arg==(ToFloat+1.0));", stop.toString());
assertEquals(0L, Evaluator.evaluate(stop, 1));
}
diff --git a/chapter14/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/chapter14/src/test/java/com/seaofnodes/simple/Chapter13Test.java
index 807badd5..66ed1073 100644
--- a/chapter14/src/test/java/com/seaofnodes/simple/Chapter13Test.java
+++ b/chapter14/src/test/java/com/seaofnodes/simple/Chapter13Test.java
@@ -14,7 +14,7 @@ public class Chapter13Test {
"""
return 3.14;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return 3.14;", stop.toString());
assertEquals(3.14, Evaluator.evaluate(stop, 0));
}
@@ -56,7 +56,7 @@ LLI? next = head.next;
if( next==null ) return 1;
return next.i;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("Stop[ return 0; return 1; return .i; ]", stop.toString());
assertEquals(2L, Evaluator.evaluate(stop, 3));
}
@@ -75,7 +75,7 @@ i0.f = f0;
f0.i = i0;
return f0.i.f.i.i;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return 17;", stop.toString());
}
@@ -87,7 +87,7 @@ struct N { N next; int i; }
N n = new N;
return n.next;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return null;", stop.toString());
}
@@ -100,7 +100,7 @@ N n = new N;
n.next = new N;
return n.next;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return new N;", stop.toString());
}
@@ -149,7 +149,7 @@ return n.i;
"""
struct S{};
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return 0;", stop.toString());
assertEquals(0L, Evaluator.evaluate(stop, 0));
}
@@ -173,7 +173,7 @@ struct S1 { S2? s; }
struct S2 { int x; }
return new S1.s=new S2;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return new S1;", stop.toString());
}
@@ -190,7 +190,7 @@ p2.pi.i = 2;
if (arg) p1 = new P;
return p1.pi.i + 1;
""");
- try { parser.parse(false).iterate(); fail(); }
+ try { parser.parse().iterate(); fail(); }
catch( Exception e ) { assertEquals("Might be null accessing 'i'",e.getMessage()); }
}
diff --git a/chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java b/chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java
index fcb7fa24..c4768fb3 100644
--- a/chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java
+++ b/chapter14/src/test/java/com/seaofnodes/simple/Chapter14Test.java
@@ -15,7 +15,7 @@ public class Chapter14Test {
"""
return 3.14;
""");
- StopNode stop = parser.parse(false).iterate();
+ StopNode stop = parser.parse().iterate();
assertEquals("return 3.14;", stop.toString());
assertEquals(3.14, Evaluator.evaluate(stop, 0));
}
@@ -31,7 +31,7 @@ if( b < 0 ) c = -1;
if( b > 2 ) c = 1;
return c;
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return 99;", stop.toString());
assertEquals(99L, Evaluator.evaluate(stop, 0));
}
@@ -44,7 +44,7 @@ u8 b = 123;
b = b + 456;// Truncate
return b;
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return 67;", stop.toString());
assertEquals(67L, Evaluator.evaluate(stop, 0));
}
@@ -58,7 +58,7 @@ u8 b = 123;
while( b ) b = b + 456;// Truncate
return b;
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return Phi(Loop9,123,((Phi_b+456)&255));", stop.toString());
}
@@ -71,7 +71,7 @@ b = b + 456;// Truncate
u1 c = b; // No more truncate needed
return c;
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return 1;", stop.toString());
assertEquals(1L, Evaluator.evaluate(stop, 0));
}
@@ -84,7 +84,7 @@ int b = 123;
b = b+456 & 31; // Precedence
return b;
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return 3;", stop.toString());
assertEquals(3L, Evaluator.evaluate(stop, 0));
}
@@ -98,7 +98,7 @@ Foo f = new Foo;
f.b = 123;
return f.b;
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return 1;", stop.toString());
assertEquals(1L, Evaluator.evaluate(stop, 0));
}
@@ -110,7 +110,7 @@ return f.b;
i8 b = 255; // Chopped
return b; // Sign extend
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return -1;", stop.toString());
assertEquals(-1L, Evaluator.evaluate(stop, 0));
}
@@ -123,7 +123,7 @@ i8 b = arg;
b = b + 1;// Truncate
return b;
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return (((((arg<<56)>>56)+1)<<56)>>56);", stop.toString());
assertEquals(1L, Evaluator.evaluate(stop, 0));
}
@@ -136,7 +136,7 @@ u16 mask = (1<<16)-1; // AND mask
int c = 123456789 & mask;
return c; //
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return 52501;", stop.toString());
assertEquals(52501L, Evaluator.evaluate(stop, 0));
}
@@ -151,7 +151,7 @@ int j = -i; // Negating Long.MIN_VALUE wraps, cannot constant fold
if (arg) j = 1;
return j;
""");
- StopNode stop = parser.parse(false).iterate();
+ StopNode stop = parser.parse().iterate();
assertEquals("return Phi(Region28,1,(-((arg&9223372036854775807)+-9223372036854775808)));", stop.toString());
assertEquals(-9223372036854775808L, Evaluator.evaluate(stop, 0));
assertEquals(1L, Evaluator.evaluate(stop, 1));
@@ -163,7 +163,7 @@ return j;
"""
return (arg >>> 1)==0;
""");
- StopNode stop = parser.parse(false).iterate();
+ StopNode stop = parser.parse().iterate();
assertEquals("return (!(arg>>>1));", stop.toString());
assertEquals(1L, Evaluator.evaluate(stop, 0));
assertEquals(1L, Evaluator.evaluate(stop, 1));
@@ -176,7 +176,7 @@ return (arg >>> 1)==0;
"""
return (arg | 123 ^ 456) >>> 1;
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return (((arg|123)^456)>>>1);", stop.toString());
assertEquals(217L, Evaluator.evaluate(stop, 0));
}
@@ -208,7 +208,7 @@ if (arg) i = a.i;
else i = b.i;
return i;
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return Phi(Region31,.i,.i);", stop.toString());
assertEquals(0L, Evaluator.evaluate(stop, 0));
}
@@ -228,7 +228,7 @@ while (1) {
return j+1;
}
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return ((arg>>Phi(Region32,2,3))+1);", stop.toString());
assertEquals(1L, Evaluator.evaluate(stop, 0));
assertEquals(1L, Evaluator.evaluate(stop, 1));
@@ -247,7 +247,7 @@ else b = f == 2.0;
if (arg&5) b = arg == 1;
return b;
""");
- StopNode stop = parser.parse(false).iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return Phi(Region37,(arg==1),((flt)arg==Phi(Region23,1.0,2.0)));", stop.toString());
assertEquals(1L, Evaluator.evaluate(stop, 1));
assertEquals(0L, Evaluator.evaluate(stop, 2));
@@ -263,7 +263,7 @@ if (arg&7) i=3;
else i=2;
return (arg == i) == 1;
""");
- StopNode stop = parser.parse(false).iterate();
+ StopNode stop = parser.parse().iterate();
assertEquals("return (arg==Phi(Region18,3,2));", stop.toString());
assertEquals(0L, Evaluator.evaluate(stop, 0));
assertEquals(0L, Evaluator.evaluate(stop, 1));
@@ -282,7 +282,7 @@ while (1) {
return i + -1;
}
""");
- StopNode stop = parser.parse(false).iterate();
+ StopNode stop = parser.parse().iterate();
assertEquals("return (Phi(Region43,((arg&3)+9223372036854775804),((arg&7)+9223372036854775800))+-1);", stop.toString());
assertEquals(0x7FFFFFFFFFFFFFF7L, Evaluator.evaluate(stop, 0));
assertEquals(0x7FFFFFFFFFFFFFFCL, Evaluator.evaluate(stop, 1));
@@ -309,7 +309,7 @@ f32 ff32 = 3.141592653589793; if( ff32 != 3.1415927410125732) return 5;
return 0;
""");
- StopNode stop = parser.parse().iterate(false);
+ StopNode stop = parser.parse().iterate();
assertEquals("return 0;", stop.toString());
assertEquals(0L, Evaluator.evaluate(stop, 0));
}