summaryrefslogtreecommitdiff
path: root/chapter13
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-10-01 12:01:57 -0700
committerCliff Click <cliffc@acm.org>2026-10-01 12:01:57 -0700
commit5ea32e69433d0c850d02bbc1e6c4a260bc095fec (patch)
treeba4917ded278097332ee8f9f33227be74d3ac104 /chapter13
parentbf7f603dd4e8ec781fe578243cdc18180322420b (diff)
downloadSimple-5ea32e69433d0c850d02bbc1e6c4a260bc095fec.tar.gz
Simple-5ea32e69433d0c850d02bbc1e6c4a260bc095fec.zip
Move debug printing into shared space
Same as the graph viewer, moves a lot of code out of all Nodes
Diffstat (limited to 'chapter13')
-rw-r--r--chapter13/Makefile3
-rw-r--r--chapter13/pom.xml1
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/IRPrinter.java311
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/AddFNode.java9
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/AddNode.java9
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/BoolNode.java10
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/CProjNode.java5
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/CastNode.java10
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/ConstantNode.java16
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/DivFNode.java9
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/DivNode.java9
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/IfNode.java7
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/LoadNode.java5
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java13
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/MinusFNode.java8
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/MinusNode.java8
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/MulFNode.java9
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/MulNode.java9
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/NeverNode.java5
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/NewNode.java9
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/Node.java64
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/NotNode.java8
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/PhiNode.java19
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/ProjNode.java5
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/RegionNode.java7
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/ReturnNode.java11
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/ScopeNode.java15
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/StartNode.java7
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/StopNode.java13
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/StoreNode.java7
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/SubFNode.java9
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/SubNode.java9
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java7
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/XCtrlNode.java5
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java33
35 files changed, 151 insertions, 533 deletions
diff --git a/chapter13/Makefile b/chapter13/Makefile
index 77df7182..3f1e53ff 100644
--- a/chapter13/Makefile
+++ b/chapter13/Makefile
@@ -37,6 +37,7 @@ main_javas := $(wildcard $(SRC)/$(SIMPLE)/*java $(SRC)/$(SIMPLE)/*/*java)
test_javas := $(wildcard $(TST)/$(SIMPLE)/*java $(TST)/$(SIMPLE)/*/*java)
main_classes := $(patsubst $(SRC)/%java,$(CLZDIR)/main/%class,$(main_javas))
include $(firstword $(wildcard ../graph/graph.mk graph/graph.mk))
+include $(firstword $(wildcard ../print/print.mk print/print.mk))
test_classes := $(patsubst $(TST)/%java,$(CLZDIR)/test/%class,$(test_javas))
test_cp := $(patsubst $(TST)/$(SIMPLE)/%.java,com.seaofnodes.simple.%,$(wildcard $(TST)/$(SIMPLE)/*Test.java))
classes = $(main_classes) $(test_classes)
@@ -54,7 +55,7 @@ endif
default: $(default_targets)
# Compile just the out-of-date files
-$(main_classes): build/classes/main/%class: $(SRC)/%java $(graph_javas)
+$(main_classes): build/classes/main/%class: $(SRC)/%java $(graph_javas) $(print_javas)
@echo "compiling " $@ " because " $?
@[ -d $(CLZDIR)/main ] || mkdir -p $(CLZDIR)/main
@javac $(JAVAC_ARGS) -cp "$(CLZDIR)/main$(SEP)$(jars)" -sourcepath $(SRC) -d $(CLZDIR)/main $(main_javas)
diff --git a/chapter13/pom.xml b/chapter13/pom.xml
index 138c3d2e..f8369496 100644
--- a/chapter13/pom.xml
+++ b/chapter13/pom.xml
@@ -13,5 +13,6 @@
<name>Chapter 13</name>
<properties>
<simple.graph.directory>${project.basedir}/../graph</simple.graph.directory>
+ <simple.print.directory>${project.basedir}/../print</simple.print.directory>
</properties>
</project>
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/IRPrinter.java b/chapter13/src/main/java/com/seaofnodes/simple/IRPrinter.java
index 3410ab64..7e93e9da 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/IRPrinter.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/IRPrinter.java
@@ -1,288 +1,33 @@
package com.seaofnodes.simple;
+import com.seaofnodes.print.IRAdapter;
import com.seaofnodes.simple.node.*;
-import java.lang.StringBuilder;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.HashMap;
-import java.util.IdentityHashMap;
-
-public class IRPrinter {
-
- // Print a node on 1 line, columnar aligned, as:
- // NNID NNAME DDEF DDEF [[ UUSE UUSE ]] TYPE
- // 1234 sssss 1234 1234 1234 1234 1234 1234 tttttt
- public static void _printLine( Node n, StringBuilder sb ) {
- sb.append("%4d %-7.7s ".formatted(n._nid,n.label()));
- if( n.isDead() ) {
- sb.append("DEAD\n");
- return;
- }
- for( Node def : n._inputs )
- sb.append(def==null ? "____ " : "%4d ".formatted(def._nid));
- for( int i = n._inputs.size(); i<4; i++ )
- sb.append(" ");
- sb.append(" [[ ");
- for( Node use : n._outputs )
- sb.append(use==null ? "____ " : "%4d ".formatted(use._nid));
- int lim = 6 - Math.max(n._inputs.size(),4);
- for( int i = n._outputs.size(); i<lim; i++ )
- sb.append(" ");
- sb.append(" ]] ");
- if( n._type!= null ) sb.append(n._type.str());
- sb.append("\n");
- }
-
- private static StringBuilder nodeId(StringBuilder sb, Node n) {
- sb.append("%%%d".formatted(n._nid));
- if (n instanceof ProjNode proj) {
- sb.append(".").append(proj._idx);
- }
- return sb;
- }
-
- // Print a node on 1 line, format is inspired by LLVM
- // %id: TYPE = NODE(inputs ....)
- // Nodes as referred to as %id
- public static void _printLineLlvmFormat( Node n, StringBuilder sb ) {
- nodeId(sb, n).append(": ");
- if( n.isDead() ) {
- sb.append("DEAD\n");
- return;
- }
- if( n._type!= null ) n._type.typeName(sb);
- sb.append(" = ").append( n.label() ).append( "(" );
- for( int i = 0; i < n._inputs.size(); i++ ) {
- Node def = n.in(i);
- if (i > 0)
- sb.append(", ");
- if (def == null) sb.append("_");
- else nodeId(sb, def);
- }
- sb.append(")").append("\n");
- }
-
- public static void printLine( Node n, StringBuilder sb, boolean llvmFormat ) {
- if (llvmFormat) _printLineLlvmFormat( n, sb );
- else _printLine ( n, sb );
- }
-
- public static String prettyPrint(Node node, int depth) {
- return Parser.SCHEDULED
- ? prettyPrintScheduled( node, depth, false )
- : prettyPrint( node, depth, false );
- }
-
- // Another bulk pretty-printer. Makes more effort at basic-block grouping.
- public static String prettyPrint( Node node, int depth, boolean llvmFormat ) {
- // First, a Breadth First Search at a fixed depth.
- BFS bfs = new BFS(node,depth);
- // Convert just that set to a post-order
- ArrayList<Node> rpos = new ArrayList<>();
- BitSet visit = new BitSet();
- for( int i=bfs._lim; i< bfs._bfs.size(); i++ )
- postOrd( bfs._bfs.get(i), rpos, visit, bfs._bs);
- // Reverse the post-order walk
- StringBuilder sb = new StringBuilder();
- boolean gap=false;
- for( int i=rpos.size()-1; i>=0; i-- ) {
- Node n = rpos.get(i);
- if( n.isCFG() || n.isMultiHead() ) {
- if( !gap ) sb.append("\n"); // Blank before multihead
- printLine( n, sb, llvmFormat ); // Print head
- while( --i >= 0 ) {
- Node t = rpos.get(i);
- if( !t.isMultiTail() ) { i++; break; }
- printLine( t, sb, llvmFormat );
- }
- sb.append("\n"); // Blank after multitail
- gap = true;
- } else {
- printLine( n, sb, llvmFormat );
- gap = false;
- }
- }
- return sb.toString();
- }
-
- private static void postOrd(Node n, ArrayList<Node> rpos, BitSet visit, BitSet bfs) {
- if( !bfs.get(n._nid) )
- return; // Not in the BFS visit
- if( visit.get(n._nid) ) return; // Already post-order walked
- visit.set(n._nid);
- // First walk the CFG, then everything
- if( n.isCFG() ) {
- for( Node use : n._outputs )
- if( use!=null && use.isCFG() && use.nOuts()>=1 && !(use._outputs.get(0) instanceof LoopNode) )
- postOrd(use, rpos,visit,bfs);
- for( Node use : n._outputs )
- if( use!=null && use.isCFG() )
- postOrd(use,rpos,visit,bfs);
- }
- for( Node use : n._outputs )
- if( use != null )
- postOrd(use, rpos,visit,bfs);
- // Post-order
- rpos.add(n);
- }
-
- // Breadth-first search, broken out in a class to keep in more independent.
- // Maintains a root-set of Nodes at the limit (or past by 1 if MultiHead).
- public static class BFS {
- // A breadth first search, plus MultiHeads for any MultiTails
- public final ArrayList<Node> _bfs;
- public final BitSet _bs; // Visited members by node id
- public final int _depth; // Depth limit
- public final int _lim; // From here to _bfs._len can be roots for a reverse search
- public BFS( Node base, int d ) {
- _depth = d;
- _bfs = new ArrayList<>();
- _bs = new BitSet();
-
- add(base); // Prime the pump
- int idx=0, lim=1; // Limit is where depth counter changes
- while( idx < _bfs.size() ) { // Ran out of nodes below depth
- Node n = _bfs.get(idx++);
- for( Node def : n._inputs )
- if( def!=null && !_bs.get(def._nid) )
- add(def);
- if( idx==lim ) { // Depth counter changes at limit
- if( --d < 0 )
- break; // Ran out of depth
- lim = _bfs.size(); // New depth limit
- }
- }
- // Toss things past the limit except multi-heads
- while( idx < _bfs.size() ) {
- Node n = _bfs.get(idx);
- if( n.isMultiHead() ) idx++;
- else del(idx);
- }
- // Root set is any node with no inputs in the visited set
- lim = _bfs.size();
- for( int i=_bfs.size()-1; i>=0; i-- )
- if( !any_visited(_bfs.get(i)) )
- swap( i,--lim);
- _lim = lim;
- }
- void swap( int x, int y ) {
- if( x==y ) return;
- Node tx = _bfs.get(x);
- Node ty = _bfs.get(y);
- _bfs.set(x,ty);
- _bfs.set(y,tx);
- }
- void add(Node n) {
- _bfs.add(n);
- _bs.set(n._nid);
- }
- void del(int idx) {
- Node n = Utils.del(_bfs, idx);
- _bs.clear(n._nid);
- }
- boolean any_visited( Node n ) {
- for( Node def : n._inputs )
- if( def!=null && _bs.get(def._nid) )
- return true;
- return false;
- }
- }
-
- // Diagnostic block ordering from raw control edges. Do not call idepth():
- // it fills compiler caches (and can walk lazy dominator accessors).
- private static int _idepth(CFGNode cfg, HashMap<Integer,Integer> depths) {
- if( cfg == null || cfg instanceof StartNode ) return 0;
- Integer old = depths.get(cfg._nid);
- if( old != null ) return old;
- depths.put(cfg._nid,0); // Break cycles in partially constructed graphs.
- int d = 0;
- if( cfg instanceof LoopNode ) {
- d = _idepth((CFGNode)cfg.in(1),depths)+1;
- } else if( cfg instanceof RegionNode || cfg instanceof StopNode ) {
- for( Node n : cfg._inputs )
- if( n instanceof CFGNode pred ) d = Math.max(d,_idepth(pred,depths)+1);
- } else if( cfg.in(0) instanceof CFGNode pred ) {
- d = _idepth(pred,depths)+1;
- }
- depths.put(cfg._nid,d);
- return d;
- }
-
- // Bulk pretty printer, knowing scheduling information is available
- public static String prettyPrintScheduled( Node node, int depth, boolean llvmFormat ) {
- // Backwards DFS walk to depth.
- IdentityHashMap<Node,Integer> ds = new IdentityHashMap<>();
- _walk(ds,node,depth);
- // Print by block with least diagnostic depth
- HashMap<Integer,Integer> depths = new HashMap<>();
- StringBuilder sb = new StringBuilder();
- ArrayList<Node> bns = new ArrayList<>();
- while( !ds.isEmpty() ) {
- CFGNode blk = null;
- for( Node n : ds.keySet() ) {
- CFGNode cfg = n instanceof CFGNode cfg0 && cfg0.blockHead() ? cfg0 : (CFGNode)n.in(0);
- if( blk==null || _idepth(cfg,depths) < _idepth(blk,depths) )
- blk = cfg;
- }
- ds.remove(blk);
-
- // Print block header
- sb.append("%-13.13s".formatted(label(blk)+":"));
- sb.append( " ".repeat(4) ).append(" [[ ");
- if( blk instanceof RegionNode || blk instanceof StopNode )
- for( int i=(blk instanceof StopNode ? 0 : 1); i<blk.nIns(); i++ )
- label(sb,blk.cfg(i));
- else if( !(blk instanceof StartNode) )
- label(sb,blk.cfg(0));
- sb.append(" ]] \n");
-
- // Collect block contents that are in the depth limit
- bns.clear();
- int xd = Integer.MAX_VALUE;
- for( Node use : blk._outputs ) {
- Integer i = ds.get(use);
- if( i!=null && !(use instanceof CFGNode cfg && cfg.blockHead()) ) {
- bns.add(use);
- xd = Math.min(xd,i);
- }
- }
- // Print Phis up front, if any
- for( int i=0; i<bns.size(); i++ )
- if( bns.get(i) instanceof PhiNode phi )
- printLine( phi, sb, llvmFormat,bns,i--,ds);
-
- // Print block contents in depth order, bumping depth until whole block printed
- for( ; !bns.isEmpty(); xd++ )
- for( int i=0; i<bns.size(); i++ )
- if( ds.get(bns.get(i))==xd )
- printLine( bns.get(i), sb, llvmFormat, bns, i--, ds );
- sb.append("\n");
- }
- return sb.toString();
- }
-
- private static void _walk( IdentityHashMap<Node,Integer> ds, Node node, int d ) {
- Integer nd = ds.get(node);
- if( nd!=null && d <= nd ) return; // Been there, done that
- ds.put(node,d);
- if( d == 0 ) return; // Depth cutoff
- for( Node def : node._inputs )
- if( def != null )
- _walk(ds,def,d-1);
- }
-
- static String label( CFGNode blk ) {
- if( blk instanceof StartNode ) return "START";
- return (blk instanceof LoopNode ? "LOOP" : "L")+blk._nid;
- }
- static void label( StringBuilder sb, CFGNode blk ) {
- if( !blk.blockHead() ) blk = blk.cfg(0);
- sb.append( "%-9.9s ".formatted( label( blk ) ) );
- }
- static void printLine( Node n, StringBuilder sb, boolean llvmFormat, ArrayList<Node> bns, int i, IdentityHashMap<Node,Integer> ds ) {
- printLine( n, sb, llvmFormat );
- Utils.del(bns,i);
- ds.remove(n);
- }
+/** This chapter's read-only IR facts and the familiar debugger entry points. */
+public final class IRPrinter extends IRAdapter<Node> {
+ private static final com.seaofnodes.print.IRPrinter<Node> PRINT =
+ new com.seaofnodes.print.IRPrinter<>(new IRPrinter());
+ @Override public String type(Node n) { return n._type==null ? "" : n._type.str(); }
+ @Override public String inputMark(Node n, Node def) { return n instanceof MemMergeNode && def instanceof MemMergeNode ? "^" : " "; }
+ @Override public Kind kind(Node n) {
+ if( n instanceof StartNode ) return Kind.START;
+ if( n instanceof StopNode ) return Kind.STOP;
+ if( n instanceof LoopNode ) return Kind.LOOP;
+ if( n instanceof RegionNode ) return Kind.REGION;
+ if( n instanceof PhiNode ) return Kind.PHI;
+ if( n instanceof ReturnNode ) return Kind.RETURN;
+ if( n instanceof ConstantNode ) return Kind.CONSTANT;
+ if( n instanceof CProjNode ) return Kind.CPROJ;
+ if( n instanceof ProjNode ) return n instanceof CFGNode ? Kind.CPROJ : Kind.PROJ;
+ if( n instanceof CFGNode ) return Kind.CTRL;
+ if( n instanceof MultiNode ) return Kind.MULTI;
+ return Kind.DATA;
+ }
+ @Override public int index(Node n) {
+ if( n instanceof ProjNode p ) return p._idx;
+ if( n instanceof CProjNode p ) return p._idx;
+ return n._nid;
+ }
+
+ public static String prettyPrint(Node n, int depth) { return PRINT.prettyPrint(n,depth); }
}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/AddFNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/AddFNode.java
index 5d0a473a..fd713156 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/AddFNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/AddFNode.java
@@ -1,21 +1,16 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeFloat;
-import java.util.BitSet;
public class AddFNode extends Node {
public AddFNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
@Override public String label() { return "AddF"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("("), visited);
- in(2)._print0(sb.append("+"), visited);
- return sb.append(")");
- }
+ @Override protected String format() { return "(%1+%2)"; }
@Override
public Type compute() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/AddNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/AddNode.java
index eb1bd073..94fee330 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/AddNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/AddNode.java
@@ -1,20 +1,15 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
public class AddNode extends Node {
public AddNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
@Override public String label() { return "Add"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("("), visited);
- in(2)._print0(sb.append("+"), visited);
- return sb.append(")");
- }
+ @Override protected String format() { return "(%1+%2)"; }
@Override
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/BoolNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/BoolNode.java
index 2055ea6f..e515a5f1 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/BoolNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/BoolNode.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.Type;
@@ -7,7 +9,6 @@ import com.seaofnodes.simple.type.TypeInteger;
import com.seaofnodes.simple.type.TypeFloat;
import com.seaofnodes.simple.type.TypeMemPtr;
-import java.util.BitSet;
abstract public class BoolNode extends Node {
@@ -20,11 +21,8 @@ abstract public class BoolNode extends Node {
@Override
public String label() { return getClass().getSimpleName(); }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("("), visited);
- in(2)._print0(sb.append(op()), visited);
- return sb.append(")");
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ return p.open().n(in(1)).p(op()).n(in(2)).close();
}
@Override
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/CProjNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/CProjNode.java
index fb0ff879..ff5d1a76 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/CProjNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/CProjNode.java
@@ -1,10 +1,11 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeMem;
import com.seaofnodes.simple.type.TypeTuple;
-import java.util.BitSet;
public class CProjNode extends CFGNode {
@@ -22,7 +23,7 @@ public class CProjNode extends CFGNode {
@Override public String label() { return _label; }
- @Override StringBuilder _print1(StringBuilder sb, BitSet visited) { return sb.append(_label); }
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) { return p.p(_label); }
@Override public boolean isMultiTail() { return in(0).isMultiHead(); }
@Override public boolean blockHead() { return true; }
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/CastNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/CastNode.java
index 38d6a126..9ade5a50 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/CastNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/CastNode.java
@@ -1,10 +1,11 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
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.
// Can also be used to make a type-assertion if ctrl is null.
@@ -18,13 +19,10 @@ public class CastNode extends Node {
@Override public String label() { return "("+_t.str()+")"; }
- @Override
- public String uniqueName() { return "Cast_" + _nid; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- return in(1)._print0(sb.append(label()), visited);
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ return p.p(label()).n(in(1));
}
@Override
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/ConstantNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/ConstantNode.java
index 37a529d1..9ecd1152 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/ConstantNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/ConstantNode.java
@@ -1,9 +1,10 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.type.Type;
-import java.util.BitSet;
/**
* A Constant node represents a constant value. At present, the only constants
@@ -24,15 +25,16 @@ public class ConstantNode extends Node {
_con = type;
}
- @Override
- public String label() { return "#"+_con; }
+ @Override protected String repeatName() {
+ return _con==null || _con.toString().length()<=32 ? null : uniqueName();
+ }
@Override
- public String uniqueName() { return "Con_" + _nid; }
+ public String label() { return "Con"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- return _con.print(sb);
+
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ return p.p(_con);
}
@Override public boolean isMultiTail() { return true; }
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/DivFNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/DivFNode.java
index 6c0c2eb3..a3f4318d 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/DivFNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/DivFNode.java
@@ -1,21 +1,16 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeFloat;
-import java.util.BitSet;
public class DivFNode extends Node {
public DivFNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
@Override public String label() { return "DivF"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("("), visited);
- in(2)._print0(sb.append("/"), visited);
- return sb.append(")");
- }
+ @Override protected String format() { return "(%1/%2)"; }
@Override
public Type compute() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/DivNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/DivNode.java
index bc9ff7d9..cd52d117 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/DivNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/DivNode.java
@@ -1,21 +1,16 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;
-import java.util.BitSet;
public class DivNode extends Node {
public DivNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
@Override public String label() { return "Div"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("("), visited);
- in(2)._print0(sb.append("/"), visited);
- return sb.append(")");
- }
+ @Override protected String format() { return "(%1/%2)"; }
@Override
public Type compute() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/IfNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/IfNode.java
index 5457ac6e..70340f7f 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/IfNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/IfNode.java
@@ -1,5 +1,6 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;
@@ -17,11 +18,7 @@ public class IfNode extends CFGNode implements MultiNode {
@Override
public String label() { return "If"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- sb.append("if( ");
- return in(1)._print0(sb, visited).append(" )");
- }
+ @Override protected String format() { return "if( %1 )"; }
@Override public boolean isMultiHead() { return true; }
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/LoadNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/LoadNode.java
index f1d4884a..277644f5 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/LoadNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/LoadNode.java
@@ -1,10 +1,11 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.type.Type;
-import java.util.BitSet;
/**
* Load represents extracting a value from inside a memory object,
@@ -43,7 +44,7 @@ public class LoadNode extends MemOpNode {
@Override public String label() { return _name; }
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) { return sb.append(".").append(_name); }
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) { return p.p(".").p(_name); }
@Override
public Type compute() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java
index d7fed402..f3d5b01e 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java
@@ -1,9 +1,10 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeMem;
-import java.util.BitSet;
/** All memory: a default slice and explicit overrides for individual aliases. */
public class MemMergeNode extends Node {
@@ -28,14 +29,14 @@ public class MemMergeNode extends Node {
@Override public String label() { return "MemMerge"; }
@Override public boolean isMem() { return true; }
@Override public Type compute() { return TypeMem.BOT; }
- @Override StringBuilder _print1(StringBuilder sb, BitSet visited) {
- sb.append("MEM[");
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ p.p("MEM[");
for( int i=1; i<nIns(); i++ )
if( in(i)!=null ) {
- sb.append(i==1 ? "default:" : i+":");
- in(i)._print0(sb,visited).append(" ");
+ p.p(i==1 ? "default:" : i+":");
+ p.n(in(i)).p(" ");
}
- return sb.append("]");
+ return p.p("]");
}
@Override public Node idealize() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/MinusFNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/MinusFNode.java
index 7cacf2c9..1b45c7c5 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/MinusFNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/MinusFNode.java
@@ -1,20 +1,16 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeFloat;
-import java.util.BitSet;
public class MinusFNode extends Node {
public MinusFNode(Node in) { super(null, in); }
@Override public String label() { return "MinusF"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("(-"), visited);
- return sb.append(")");
- }
+ @Override protected String format() { return "(-%1)"; }
@Override
public Type compute() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/MinusNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/MinusNode.java
index c3be733c..ae450b22 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/MinusNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/MinusNode.java
@@ -1,20 +1,16 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;
-import java.util.BitSet;
public class MinusNode extends Node {
public MinusNode(Node in) { super(null, in); }
@Override public String label() { return "Minus"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("(-"), visited);
- return sb.append(")");
- }
+ @Override protected String format() { return "(-%1)"; }
@Override
public Type compute() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/MulFNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/MulFNode.java
index 4b753ba7..6a57f3c5 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/MulFNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/MulFNode.java
@@ -1,21 +1,16 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeFloat;
-import java.util.BitSet;
public class MulFNode extends Node {
public MulFNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
@Override public String label() { return "MulF"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("("), visited);
- in(2)._print0(sb.append("*"), visited);
- return sb.append(")");
- }
+ @Override protected String format() { return "(%1*%2)"; }
@Override
public Type compute() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/MulNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/MulNode.java
index 4cd075e4..7fd52399 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/MulNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/MulNode.java
@@ -1,21 +1,16 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;
-import java.util.BitSet;
public class MulNode extends Node {
public MulNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
@Override public String label() { return "Mul"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("("), visited);
- in(2)._print0(sb.append("*"), visited);
- return sb.append(")");
- }
+ @Override protected String format() { return "(%1*%2)"; }
@Override
public Type compute() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/NeverNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/NeverNode.java
index e77ed653..7e42ccf9 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/NeverNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/NeverNode.java
@@ -1,11 +1,12 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.type.TypeInteger;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeTuple;
-import java.util.BitSet;
// "Never true" for infinite loop exits
public class NeverNode extends IfNode {
@@ -13,7 +14,7 @@ public class NeverNode extends IfNode {
@Override public String label() { return "Never"; }
- @Override StringBuilder _print1(StringBuilder sb, BitSet visited) { return sb.append("Never"); }
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) { return p.p("Never"); }
@Override public Type compute() { return TypeTuple.IF_BOTH; }
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/NewNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/NewNode.java
index 1c82d5f5..74ba5184 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/NewNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/NewNode.java
@@ -1,9 +1,10 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeMemPtr;
-import java.util.BitSet;
public class NewNode extends Node {
@@ -17,10 +18,8 @@ public class NewNode extends Node {
@Override
public String label() { return "new"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- sb.append("new ");
- return sb.append(_ptr._obj.str());
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ return p.p("new ").p(_ptr._obj.str());
}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter13/src/main/java/com/seaofnodes/simple/node/Node.java
index 2082168a..7448e05e 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/Node.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/Node.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.BaseNode;
+
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.IRPrinter;
@@ -16,14 +18,7 @@ import java.util.function.Function;
* The Node class provides common functionality used by all subtypes.
* Subtypes of Node specialize by overriding methods.
*/
-public abstract class Node implements OutNode, Cloneable {
-
- /**
- * Each node has a unique dense Node ID within a compilation context
- * The ID is useful for debugging, for using as an offset in a bitvector,
- * as well as for computing equality of nodes (to be implemented later).
- */
- public int _nid;
+public abstract class Node extends BaseNode<Node> implements OutNode, Cloneable {
/**
* Inputs to the node. These are use-def references to Nodes.
@@ -45,14 +40,12 @@ public abstract class Node implements OutNode, Cloneable {
*/
public ArrayList<Node> _outputs;
-
/**
* Current computed type for this Node. This value changes as the graph
* changes and more knowledge is gained about the program.
*/
public Type _type;
-
/**
* A private Global Static mutable counter, for unique node id generation.
* To make the compiler multithreaded, this field will have to move into a TLS.
@@ -62,7 +55,7 @@ public abstract class Node implements OutNode, Cloneable {
public static int UID() { return UNIQUE_ID; }
protected Node(Node... inputs) {
- _nid = UNIQUE_ID++; // allocate unique dense ID
+ super(UNIQUE_ID++); // allocate unique dense ID
_inputs = new ArrayList<>();
Collections.addAll(_inputs,inputs);
_outputs = new ArrayList<>();
@@ -74,42 +67,6 @@ public abstract class Node implements OutNode, Cloneable {
// Easy reading label for debugger, e.g. "Add" or "Region" or "EQ"
public abstract String label();
- // Unique label for debugging, e.g. "Add12" or "Region30" or "EQ99"
- public String uniqueName() {
- return label() + _nid;
- }
-
- // ------------------------------------------------------------------------
-
- // Debugger Printing.
-
- // {@code toString} is what you get in the debugger. It has to print 1
- // line (because this is what a debugger typically displays by default) and
- // has to be robust with broken graph/nodes.
- @Override
- public final String toString() { return print(); }
-
- // This is a *deep* print. This version will fail on cycles, which we will
- // correct later when we can parse programs with loops. We print with a
- // tik-tok style; the common _print0 calls the per-Node _print1, which
- // calls back to _print0;
- public final String print() {
- return _print0(new StringBuilder(), new BitSet()).toString();
- }
-
- // This is the common print: check for repeats, check for DEAD and print
- // "DEAD" else call the per-Node print1.
- final StringBuilder _print0(StringBuilder sb, BitSet visited) {
- if (visited.get(_nid) && !(this instanceof ConstantNode) )
- return sb.append(label());
- visited.set(_nid);
- return isDead()
- ? sb.append(uniqueName()).append(":DEAD")
- : _print1(sb, visited);
- }
- // Every Node implements this; a partial-line recursive print
- abstract StringBuilder _print1(StringBuilder sb, BitSet visited);
-
public String p(int depth) { return IRPrinter.prettyPrint(this,depth); }
public boolean isMultiHead() { return false; }
@@ -118,6 +75,8 @@ public abstract class Node implements OutNode, Cloneable {
// ------------------------------------------------------------------------
// Graph Node & Edge manipulation
+ @Override public String typeName() { return _type==null ? null : _type.toString(); }
+
/**
* Gets the ith input node
* @param i Offset of the input node
@@ -258,7 +217,6 @@ public abstract class Node implements OutNode, Cloneable {
// Test "keep" status
public boolean iskeep() { return Utils.find(_outputs,null) != -1; }
-
// Replace self with nnn in the graph, making 'this' go dead
public void subsume( Node nnn ) {
assert nnn!=this;
@@ -389,7 +347,6 @@ public abstract class Node implements OutNode, Cloneable {
return old;
}
-
/**
* This function rewrites the current Node into a more "idealized" form.
* This is the bulk of our peephole rewrite rules, and we use this to
@@ -437,7 +394,6 @@ public abstract class Node implements OutNode, Cloneable {
*/
public abstract Node idealize();
-
// Some of the peephole rules get complex, and search further afield than
// just the nearest neighbor. These peepholes can fail the pattern match
// on a node some distance away, and if that node ever changes we should
@@ -481,7 +437,6 @@ public abstract class Node implements OutNode, Cloneable {
_deps.clear();
}
-
// Global Value Numbering. Hash over opcode and inputs; hits in this table
// are structurally equal.
public static final HashMap<Node,Node> GVN = new HashMap<>();
@@ -503,7 +458,6 @@ public abstract class Node implements OutNode, Cloneable {
// and can assume "this!=n" and has the same Java class.
boolean eq( Node n ) { return true; }
-
// Cached hash. If zero, then not computed AND this Node is NOT in the GVN
// table - and can have its edges hacked (which will change his hash
// anyway). If Non-Zero then this Node is IN the GVN table, or is being
@@ -519,7 +473,6 @@ public abstract class Node implements OutNode, Cloneable {
_hash=0; // Out of table now
}
-
// Hash of opcode and inputs
@Override public final int hashCode() {
if( _hash != 0 ) return _hash;
@@ -537,7 +490,6 @@ public abstract class Node implements OutNode, Cloneable {
//
/** Is this Node control-flow-graph related */
- public boolean isCFG() { return false; }
/** Is this Node Memory related */
public boolean isMem() { return false; }
@@ -545,7 +497,6 @@ public abstract class Node implements OutNode, Cloneable {
/** Return block start from a isCFG() */
public Node getBlockStart() { return null; }
-
// Semantic change to the graph (so NOT a peephole), used by the Parser.
// If any input is a float, flip to a float-flavored opcode and widen any
// non-float input.
@@ -566,7 +517,6 @@ public abstract class Node implements OutNode, Cloneable {
}
Node copyF() { return null; }
-
// ------------------------------------------------------------------------
// Peephole utilities
@@ -595,7 +545,6 @@ public abstract class Node implements OutNode, Cloneable {
return true;
}
-
// Make a shallow copy (same class) of this Node, with given inputs and
// empty outputs and a new Node ID. The original inputs are ignored.
// Does not need to be implemented in isCFG() nodes.
@@ -628,7 +577,6 @@ public abstract class Node implements OutNode, Cloneable {
ITER_CNT = ITER_NOP_CNT = 0;
}
-
// Utility to walk the entire graph applying a function; return the first
// not-null result.
private static final BitSet WVISIT = new BitSet();
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/NotNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/NotNode.java
index bb7e9265..4539f982 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/NotNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/NotNode.java
@@ -1,19 +1,15 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
public class NotNode extends Node {
public NotNode(Node in) { super(null, in); }
@Override public String label() { return "Not"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("(!"), visited);
- return sb.append(")");
- }
+ @Override protected String format() { return "(!%1)"; }
@Override
public Type compute() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/PhiNode.java
index 277c16d1..8dfa04cf 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/PhiNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/PhiNode.java
@@ -1,10 +1,11 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeMem;
import com.seaofnodes.simple.Utils;
-import java.util.BitSet;
public class PhiNode extends Node {
@@ -23,18 +24,12 @@ public class PhiNode extends Node {
@Override public String label() { return "Phi_"+_label; }
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
if( !(region() instanceof RegionNode r) || r.inProgress() )
- sb.append("Z");
- sb.append("Phi(");
- for( Node in : _inputs ) {
- if (in == null) sb.append("____");
- else in._print0(sb, visited);
- sb.append(",");
- }
- sb.setLength(sb.length()-1);
- sb.append(")");
- return sb;
+ p.p("Z");
+ p.p("Phi(");
+ for( Node in : _inputs ) p.n(in).p(",");
+ return p.unchar(',').close();
}
public CFGNode region() { return (CFGNode)in(0); }
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/ProjNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/ProjNode.java
index 93239a61..e82c69b3 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/ProjNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/ProjNode.java
@@ -1,10 +1,11 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeMem;
import com.seaofnodes.simple.type.TypeTuple;
-import java.util.BitSet;
public class ProjNode extends Node {
@@ -24,7 +25,7 @@ public class ProjNode extends Node {
public String label() { return _label; }
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) { return sb.append(_label); }
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) { return p.p(_label); }
@Override public boolean isMultiTail() { return in(0).isMultiHead(); }
@Override public boolean isMem() { return _type instanceof TypeMem; }
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/RegionNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/RegionNode.java
index d7e934d7..cdfd10ad 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/RegionNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/RegionNode.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.Utils;
@@ -16,9 +18,8 @@ public class RegionNode extends CFGNode {
@Override
public String label() { return "Region"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- return sb.append(label()).append(_nid);
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ return p.p(label()).p(_nid);
}
@Override public boolean isMultiHead() { return true; }
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/ReturnNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/ReturnNode.java
index 725c704f..161cc7d6 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/ReturnNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/ReturnNode.java
@@ -1,8 +1,9 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
/** Keeps all preceding memory effects and the return value alive: {ctrl, $mem, value}. */
public class ReturnNode extends CFGNode {
@@ -20,10 +21,10 @@ public class ReturnNode extends CFGNode {
public String label() { return "Return"; }
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- sb.append("return ");
- expr()._print0(sb, visited);
- return sb.append(";");
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ p.p("return ");
+ p.n(expr());
+ return p.p(";");
}
@Override
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/ScopeNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/ScopeNode.java
index b931e862..b408eb2f 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/ScopeNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/ScopeNode.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.Utils;
@@ -42,20 +44,19 @@ public class ScopeNode extends Node {
@Override public String label() { return "Scope"; }
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- sb.append("Scope[ ");
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ p.p("Scope[ ");
String[] names = reverseNames();
for( int j=0; j<nIns(); j++ ) {
- sb.append(names[j]).append(":");
+ p.p(names[j]).p(":");
Node n = in(j);
while( n instanceof ScopeNode loop ) {
- sb.append("Lazy_");
+ p.p("Lazy_");
n = loop.in(j);
}
- n._print0(sb, visited).append(" ");
+ p.n(n).p(" ");
}
- sb.setLength(sb.length()-1);
- return sb.append("]");
+ return p.unchar(' ').p("]");
}
/**
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/StartNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/StartNode.java
index 2cedf0f6..a5d4923f 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/StartNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/StartNode.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.type.*;
import java.util.BitSet;
import java.util.HashSet;
@@ -17,9 +19,8 @@ public class StartNode extends CFGNode implements MultiNode {
@Override
public String label() { return "Start"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- return sb.append(label());
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ return p.p(label());
}
@Override public boolean isMultiHead() { return true; }
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/StopNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/StopNode.java
index af3a9de6..202afbd2 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/StopNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/StopNode.java
@@ -1,12 +1,13 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.GlobalCodeMotion;
-import java.util.BitSet;
public class StopNode extends CFGNode {
@@ -23,12 +24,12 @@ public class StopNode extends CFGNode {
}
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- if( ret()!=null ) return ret()._print0(sb, visited);
- sb.append("Stop[ ");
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ if( ret()!=null ) return p.n(ret());
+ p.p("Stop[ ");
for( Node ret : _inputs )
- ret._print0(sb, visited).append(" ");
- return sb.append("]");
+ p.n(ret).p(" ");
+ return p.p("]");
}
@Override public boolean blockHead() { return true; }
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/StoreNode.java
index 031240ce..e9eaaf2e 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/StoreNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/StoreNode.java
@@ -1,10 +1,11 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
/**
* Store represents setting a value to a memory based object, in chapter 10
@@ -35,8 +36,8 @@ public class StoreNode extends MemOpNode {
public Node val() { return in(3); }
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- return sb.append(".").append(_name).append("=").append( val()).append(";");
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ return p.p(".").p(_name).p("=").p( val()).p(";");
}
@Override
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/SubFNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/SubFNode.java
index d911ce7e..7c1a5dde 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/SubFNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/SubFNode.java
@@ -1,21 +1,16 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeFloat;
-import java.util.BitSet;
public class SubFNode extends Node {
public SubFNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
@Override public String label() { return "SubF"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("("), visited);
- in(2)._print0(sb.append("-"), visited);
- return sb.append(")");
- }
+ @Override protected String format() { return "(%1-%2)"; }
@Override
public Type compute() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/SubNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/SubNode.java
index 4ae302f0..f36f2af5 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/SubNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/SubNode.java
@@ -1,22 +1,17 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;
-import java.util.BitSet;
public class SubNode extends Node {
public SubNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
@Override public String label() { return "Sub"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("("), visited);
- in(2)._print0(sb.append("-"), visited);
- return sb.append(")");
- }
+ @Override protected String format() { return "(%1-%2)"; }
@Override
public Type compute() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
index fde483d6..26cf50e1 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
@@ -1,20 +1,17 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeFloat;
import com.seaofnodes.simple.type.TypeInteger;
-import java.util.BitSet;
public class ToFloatNode extends Node {
public ToFloatNode(Node lhs) { super(null, lhs); }
@Override public String label() { return "ToFloat"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- return in(1)._print0(sb.append("(flt)"), visited);
- }
+ @Override protected String format() { return "(flt)%1"; }
@Override
public Type compute() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/XCtrlNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/XCtrlNode.java
index 83779dd2..056dfba1 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/XCtrlNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/XCtrlNode.java
@@ -1,13 +1,14 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.type.Type;
-import java.util.BitSet;
public class XCtrlNode extends CFGNode {
public XCtrlNode( ) { super(Parser.START); }
@Override public String label() { return "Xctrl"; }
- @Override StringBuilder _print1(StringBuilder sb, BitSet visited) { return sb.append("Xctrl"); }
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) { return p.p("Xctrl"); }
@Override public Type compute() { return Type.XCONTROL; }
@Override public Node idealize() { return null; }
}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java b/chapter13/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
index 3778a6d9..9d996c03 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
@@ -1,43 +1,20 @@
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 13'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 String[] edgeNames(Node n) {
+ return n instanceof ScopeNode scope && n.nIns()!=0 ? scope.reverseNames() : null;
}
+ @Override protected int projectionIndex(Node n) { return n instanceof ProjNode p ? p._idx : n instanceof CProjNode p ? p._idx : -1; }
- @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) {
+ @Override protected Kind kind(Node n) {
if( n instanceof StopNode ) return Kind.STOP;
if( n instanceof ScopeNode ) return Kind.SCOPE;
if( n instanceof StartNode ) return Kind.CTRL;
@@ -47,7 +24,7 @@ public class SimpleGraphAdapter extends GraphAdapter<Node> {
return n.isCFG() ? Kind.CTRL : isMem(n) ? Kind.MEM : Kind.DATA;
}
- private Role role(Node n, int i) {
+ @Override protected 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;