From 29fb671e69f90ad3b04c6fa8d746caf857f89e77 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Tue, 22 Sep 2026 11:25:05 -0700 Subject: Add shared graph viewer to all chapters --- chapter25/Makefile | 10 +- .../com/seaofnodes/simple/codegen/CodeGen.java | 15 +- .../java/com/seaofnodes/simple/node/AndNode.java | 2 - .../java/com/seaofnodes/simple/node/ArithNode.java | 1 - .../java/com/seaofnodes/simple/node/BoolNode.java | 6 - .../com/seaofnodes/simple/node/ConFldOffNode.java | 1 - .../com/seaofnodes/simple/node/ConstantNode.java | 1 - .../com/seaofnodes/simple/node/ExternNode.java | 1 - .../com/seaofnodes/simple/node/FldOffNode.java | 1 - .../com/seaofnodes/simple/node/FunPtrNode.java | 1 - .../java/com/seaofnodes/simple/node/LoadNode.java | 5 +- .../java/com/seaofnodes/simple/node/MinusNode.java | 1 - .../java/com/seaofnodes/simple/node/NewNode.java | 5 +- .../main/java/com/seaofnodes/simple/node/Node.java | 8 +- .../java/com/seaofnodes/simple/node/NotNode.java | 2 - .../java/com/seaofnodes/simple/node/OrNode.java | 3 - .../java/com/seaofnodes/simple/node/ParmNode.java | 2 - .../java/com/seaofnodes/simple/node/PhiNode.java | 2 - .../com/seaofnodes/simple/node/PtrToIntNode.java | 1 - .../com/seaofnodes/simple/node/RoundF32Node.java | 2 - .../java/com/seaofnodes/simple/node/SarNode.java | 2 - .../java/com/seaofnodes/simple/node/ShlNode.java | 2 - .../java/com/seaofnodes/simple/node/ShrNode.java | 2 - .../java/com/seaofnodes/simple/node/StoreNode.java | 4 +- .../com/seaofnodes/simple/node/ToFloatNode.java | 2 - .../java/com/seaofnodes/simple/node/XorNode.java | 2 - .../seaofnodes/simple/print/GraphVisualizer.java | 288 --------------------- .../java/com/seaofnodes/simple/print/JSViewer.java | 26 -- .../simple/print/SimpleGraphObserver.java | 21 +- .../test/java/com/seaofnodes/simple/Simple.java | 3 - 30 files changed, 27 insertions(+), 395 deletions(-) delete mode 100644 chapter25/src/main/java/com/seaofnodes/simple/print/GraphVisualizer.java delete mode 100644 chapter25/src/main/java/com/seaofnodes/simple/print/JSViewer.java (limited to 'chapter25') diff --git a/chapter25/Makefile b/chapter25/Makefile index 886354d3..fb71fc6b 100644 --- a/chapter25/Makefile +++ b/chapter25/Makefile @@ -65,10 +65,7 @@ main_javas := $(wildcard $(SRC)/$(SIMPLE)/*java $(SRC)/$(SIMPLE)/*/*java $(SRC test_javas := $(wildcard $(TST)/$(SIMPLE)/*java $(TST)/$(SIMPLE)/*/*java) simple_driver := $(TST)/$(SIMPLE)/Simple.java main_classes := $(patsubst $(SRC)/%java,$(CLZDIR)/main/%class,$(main_javas)) -# Compile the common adapter into this chapter without copying its sources. -GRAPH_DIR := $(firstword $(wildcard ../graph graph)) -graph_javas := $(wildcard $(GRAPH_DIR)/src/main/java/com/seaofnodes/graph/*.java) -main_javas += $(graph_javas) +include $(firstword $(wildcard ../graph/graph.mk graph/graph.mk)) test_classes := $(patsubst $(TST)/%java,$(CLZDIR)/test/%class,$(test_javas)) # These tests do not rely on the stdlib test_alone := com.seaofnodes.simple.BrainFuckTest com.seaofnodes.simple.MergeSortTest com.seaofnodes.simple.TypeTest @@ -218,11 +215,6 @@ build/release/Simple.jar: $(CLZDIR)/main/.mtag $(CLZDIR)/test/.ttag @printf "Main-Class: com.seaofnodes.simple.Simple\nClass-Path: ../../lib/junit-4.12.jar ../../lib/hamcrest-core-1.3.jar\n\n" > build/release/MANIFEST.MF @jar cfm $@ build/release/MANIFEST.MF -C $(CLZDIR)/main . -C $(CLZDIR)/test . -C $(SRC)/$(SIMPLE) . -C $(TST)/$(SIMPLE) . -# Launch viewer -.PHONY: view -view: $(CLZDIR)/main/.mtag - @echo "viewing " - @$(JVM) com.seaofnodes.simple.print.JSViewer ####################################################### .PHONY: clean diff --git a/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java index f8674d64..87aa96c4 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java @@ -275,14 +275,7 @@ public class CodeGen { private int dump(int dump) { int p2 = _phase.ordinal(); if( (dump & (1< _cfg = new Ary<>(CFGNode.class); // Global schedule (code motion) nodes - public CodeGen GCM() { return GCM(false); } - public CodeGen GCM( boolean show) { + public CodeGen GCM() { assert _phase.ordinal() <= Phase.Select.ordinal(); _phase = Phase.Schedule; long t0 = System.currentTimeMillis(); GlobalCodeMotion.buildCFG(this); _times[Phase.Schedule.ordinal()] = System.currentTimeMillis() - t0; - if( show ) - System.out.println(new GraphVisualizer().generateDotOutput(compunit(),null,null)); + return this; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/AndNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/AndNode.java index 95095ac3..f02007bc 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/AndNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/AndNode.java @@ -9,8 +9,6 @@ public class AndNode extends ArithNode { @Override public Tag serialTag() { return Tag.And; } @Override public String op() { return "&"; } - @Override public String glabel() { return "&"; } - @Override long doOp( long x, long y ) { return x & y; } @Override TypeInteger doOp(TypeInteger x, TypeInteger y) { // Sharpen allowed bits if either value is narrowed diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/ArithNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/ArithNode.java index dfd81504..60f00854 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/ArithNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/ArithNode.java @@ -21,7 +21,6 @@ public abstract class ArithNode extends Node implements ModeNode { @Override public void packed(BAOS baos, HashMap strs, HashMap types, IdentityHashMap anodes) { baos.packed1(_mode); } - @Override public String glabel() { return op(); } abstract String op(); @Override diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/BoolNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/BoolNode.java index ac3b0bc0..f720d02d 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/BoolNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/BoolNode.java @@ -23,9 +23,6 @@ abstract public class BoolNode extends Node implements ModeNode { abstract public String op(); // String opcode name - @Override - public String glabel() { return op(); } - @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) { in(1)._print0(sb.append("("), visited); @@ -154,7 +151,6 @@ abstract public class BoolNode extends Node implements ModeNode { public LT(Node lhs, Node rhs, byte mode) { super(lhs,rhs, mode); } @Override public Tag serialTag() { return Tag.LT; } public String op() { return "<" ; } - public String glabel() { return "<"; } TypeInteger doOp(TypeInteger i1, TypeInteger i2) { if( i1._max < i2._min ) return TRUE; if( i1._min >= i2._max ) return FALSE; @@ -169,7 +165,6 @@ abstract public class BoolNode extends Node implements ModeNode { public LE(Node lhs, Node rhs, byte mode) { super(lhs,rhs,mode); } @Override public Tag serialTag() { return Tag.LE; } public String op() { return "<="; } - public String glabel() { return "<="; } TypeInteger doOp(TypeInteger i1, TypeInteger i2) { if( i1._max <= i2._min ) return TRUE; if( i1._min > i2._max ) return FALSE; @@ -188,7 +183,6 @@ abstract public class BoolNode extends Node implements ModeNode { } @Override public Tag serialTag() { return Tag.ULT; } public String op() { return "u<" ; } - public String glabel() { return "u<"; } TypeInteger doOp(TypeInteger i1, TypeInteger i2) { if( Long.compareUnsigned(i1._max,i2._min) < 0 ) return TRUE; if( Long.compareUnsigned(i1._min,i2._max) >= 0 ) return FALSE; diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/ConFldOffNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/ConFldOffNode.java index 11a16d28..c7ee1359 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/ConFldOffNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/ConFldOffNode.java @@ -25,7 +25,6 @@ public class ConFldOffNode extends ConstantNode { @Override public String label() { return _fname == " len" ? "sizeof("+_ts._name+")" : "#"+_fname; } - @Override public String glabel() { return label(); } @Override public String uniqueName() { return "Off_" + _nid; } @Override diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/ConstantNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/ConstantNode.java index df2dc27b..1dc369d3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/ConstantNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/ConstantNode.java @@ -67,7 +67,6 @@ public class ConstantNode extends TypeNode { public static ConstantNode seed( Type type ) { return new ConstantNode(type,true); } @Override public String label() { return "#"+_con; } - @Override public String glabel() { return "#"+_con.gprint(); } @Override public String uniqueName() { return "Con_" + _nid; } @Override public Node copy() { return raw(this); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/ExternNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/ExternNode.java index 9768f41f..58d96745 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/ExternNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/ExternNode.java @@ -29,7 +29,6 @@ public class ExternNode extends ConstantNode { } @Override public String label() { return "#"+_con+":"+_extern; } - @Override public String glabel() { return _con.print(new SB().p("#"), new BitSet(), true).p(":").p(_extern).toString(); } @Override public String uniqueName() { return "Extern_" + _nid; } @Override public boolean eq(Node n) { return this==n; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/FldOffNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/FldOffNode.java index 3a44f588..e34799c9 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/FldOffNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/FldOffNode.java @@ -23,7 +23,6 @@ public class FldOffNode extends TypeNode { @Override public String label() { return _fname == " len" ? "sizeof()" : "#"+_fname; } - @Override public String glabel() { return label(); } @Override public String uniqueName() { return "Off_" + _nid; } @Override diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/FunPtrNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/FunPtrNode.java index 6e9b0a70..141fc357 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/FunPtrNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/FunPtrNode.java @@ -25,7 +25,6 @@ public class FunPtrNode extends TypeNode { public FunNode fun() { return ret().fun(); } @Override public String label() { return "#"+_con; } - @Override public String glabel() { return "#"+_con.gprint(); } @Override public String uniqueName() { return "FunPtr_" + _nid; } @Override public Node copy() { FunPtrNode fptr = new FunPtrNode((TypeFunPtr)_con,null,null); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/LoadNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/LoadNode.java index fb93964a..d37655b6 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/LoadNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/LoadNode.java @@ -31,11 +31,8 @@ public class LoadNode extends MemOpNode { } @Override public Tag serialTag() { return Tag.Load; } - // GraphVis DOT code (must be valid Java identifiers) and debugger labels + // Debugger label @Override public String label() { return "ld_"+mlabel(); } - // GraphVis node-internal labels - @Override public String glabel() { return "." +_name; } - @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) { return sb.append(".").append(_name); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/MinusNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/MinusNode.java index 2261adab..7c3d49f2 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/MinusNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/MinusNode.java @@ -20,7 +20,6 @@ public class MinusNode extends Node implements ModeNode { } @Override public Tag serialTag() { return Tag.Minus; } - @Override public String glabel() { return "-"; } @Override public byte mode() { return _mode; } @Override public Node setMode(byte mode) { assert _mode==0 && (mode==1 || mode==2); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/NewNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/NewNode.java index 26a9c0fd..3e1d78dc 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/NewNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/NewNode.java @@ -32,10 +32,7 @@ public class NewNode extends Node implements MultiNode { return new NewNode(ts,null,null); } - @Override public String glabel() { - return _ts.isAry() ? "ary_"+_ts._fields[1]._t.str() : _ts.str(); - } - @Override public String label() { return "new_"+glabel(); } + @Override public String label() { return "new_"+(_ts.isAry() ? "ary_"+_ts._fields[1]._t.str() : _ts.str()); } @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) { sb.append("new "); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter25/src/main/java/com/seaofnodes/simple/node/Node.java index d113a02a..e2148244 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/Node.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/Node.java @@ -151,14 +151,12 @@ public abstract class Node implements Cloneable { // Easy reading label for debugger, e.g. "Add" or "Region" or "EQ" public String label() { return serialTag().toString(); } - // 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 "==" + // Operator symbol used by assembly/debug printing. public String glabel() { return label(); } // Extra fun stuff, for assembly printing. Jump labels, parser locations, diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/NotNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/NotNode.java index 22b5bffe..ed6091fe 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/NotNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/NotNode.java @@ -8,8 +8,6 @@ public class NotNode extends Node { public NotNode(Node in) { super(null, in); } @Override public Tag serialTag() { return Tag.Not; } - @Override public String glabel() { return "!"; } - @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) { in(1)._print0(sb.append("(!"), visited); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/OrNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/OrNode.java index 31d0565b..9d50d1a9 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/OrNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/OrNode.java @@ -10,9 +10,6 @@ public class OrNode extends ArithNode { @Override public String label() { return "Or"; } @Override public String op() { return "|"; } - @Override public String glabel() { return "|"; } - - @Override long doOp( long x, long y ) { return x | y; } @Override TypeInteger doOp(TypeInteger x, TypeInteger y) { return TypeInteger.BOT; diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/ParmNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/ParmNode.java index 04949a53..be36e8d9 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/ParmNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/ParmNode.java @@ -36,8 +36,6 @@ public class ParmNode extends PhiNode { @Override public String label() { return MemOpNode.mlabel(_label); } - @Override public String glabel() { return _label; } - @Override boolean _upgradeType( HashMap TYPES) { Type t = _declaredType.upgradeType(TYPES); if( t == _declaredType ) return false; diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/PhiNode.java index 54cfc3ad..09c55cde 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/PhiNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/PhiNode.java @@ -47,8 +47,6 @@ public class PhiNode extends Node { @Override public String label() { return "Phi_"+MemOpNode.mlabel(_label); } - @Override public String glabel() { return "φ_"+_label; } - @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) { if( !(region() instanceof RegionNode r) || r.inProgress() ) diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/PtrToIntNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/PtrToIntNode.java index 02f77f36..f0e7ae95 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/PtrToIntNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/PtrToIntNode.java @@ -19,7 +19,6 @@ public class PtrToIntNode extends Node { public PtrToIntNode(PtrToIntNode ptr) { super(ptr); } @Override public Tag serialTag() { return Tag.PtrToInt; } - @Override public String glabel() { return "(i64*)"; } @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) { return in(1)._print0(sb.append("(i64*)"),visited); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter25/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 322a6bc0..61809fe3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -9,8 +9,6 @@ public class RoundF32Node extends Node { public RoundF32Node(Node lhs) { super(null, lhs); } @Override public Tag serialTag() { return Tag.RoundF32; } - @Override public String glabel() { return "(f32)"; } - @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) { return in(1)._print0(sb.append("((f32)"), visited).append(")"); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/SarNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/SarNode.java index e3f99ed4..79b7d0e4 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/SarNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/SarNode.java @@ -9,8 +9,6 @@ public class SarNode extends ArithNode { @Override public Tag serialTag() { return Tag.Sar; } @Override public String op() { return ">>"; } - @Override public String glabel() { return ">>"; } - @Override long doOp( long x, long y ) { return x >> y; } @Override TypeInteger doOp( TypeInteger x, TypeInteger y ) { if( y.isConstant() ) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/ShlNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/ShlNode.java index 24d9bdb4..1ca0ba3a 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/ShlNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/ShlNode.java @@ -10,8 +10,6 @@ public class ShlNode extends ArithNode { @Override public Tag serialTag() { return Tag.Shl; } @Override public String op() { return "<<"; } - @Override public String glabel() { return "<<"; } - @Override long doOp( long x, long y ) { return x << y; } @Override TypeInteger doOp( TypeInteger x, TypeInteger y ) { if( x == TypeInteger.ZERO ) diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/ShrNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/ShrNode.java index 1bf7d118..7fad6275 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/ShrNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/ShrNode.java @@ -9,8 +9,6 @@ public class ShrNode extends ArithNode { @Override public Tag serialTag() { return Tag.Shr; } @Override public String op() { return ">>>"; } - @Override public String glabel() { return ">>>"; } - @Override long doOp( long x, long y ) { return x >>> y; } @Override TypeInteger doOp( TypeInteger x, TypeInteger y ) { return x == TypeInteger.ZERO ? x : TypeInteger.BOT; diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/StoreNode.java index faa3d17b..12a94906 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/StoreNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/StoreNode.java @@ -49,10 +49,8 @@ public class StoreNode extends MemOpNode { baos.write(_size); } - // GraphVis DOT code and debugger labels + // Debugger label @Override public String label() { return "st_"+mlabel(); } - // GraphVis node-internal labels - @Override public String glabel() { return "." +_name+"="; } @Override public boolean isMem() { return true; } public Node nnptr() { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java index 2d8cc788..15350afb 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java @@ -10,8 +10,6 @@ public class ToFloatNode extends Node { public ToFloatNode(Node lhs) { super(null, lhs); } @Override public Tag serialTag() { return Tag.ToFloat; } - @Override public String glabel() { return "(flt)"; } - @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) { return in(1)._print0(sb.append("(flt)"), visited); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/XorNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/XorNode.java index 27ebc3dc..2ee816fa 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/XorNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/XorNode.java @@ -9,8 +9,6 @@ public class XorNode extends ArithNode { @Override public Tag serialTag() { return Tag.Xor; } @Override public String op() { return "^"; } - @Override public String glabel() { return "^"; } - @Override long doOp( long x, long y ) { return x ^ y; } @Override TypeInteger doOp( TypeInteger x, TypeInteger y ) { return TypeInteger.BOT; diff --git a/chapter25/src/main/java/com/seaofnodes/simple/print/GraphVisualizer.java b/chapter25/src/main/java/com/seaofnodes/simple/print/GraphVisualizer.java deleted file mode 100644 index ad2df8b6..00000000 --- a/chapter25/src/main/java/com/seaofnodes/simple/print/GraphVisualizer.java +++ /dev/null @@ -1,288 +0,0 @@ -package com.seaofnodes.simple.print; - -import com.seaofnodes.simple.Parser; -import com.seaofnodes.simple.codegen.CompUnit; -import com.seaofnodes.simple.node.*; -import java.util.*; -import static com.seaofnodes.simple.util.Utils.TODO; - -/** - * 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._ref,parse._scope,parse._xScopes); } - public String generateDotOutput(CompUnit cu, Node scope, Stack xScopes) { - - // Since the graph has cycles, we need to create a flat list of all the - // nodes in the graph. - Collection all = findAll(xScopes, cu._stop, scope); - StringBuilder sb = new StringBuilder(); - sb.append("digraph chapter18 {\n"); - sb.append("/*\n"); - sb.append(cu._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 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 MemMergeNode || n instanceof XCtrlNode ) - continue; // Do not emit, rolled into MultiNode or Scope cluster already - if( _separateControlCluster && doCtrl && !(n instanceof CFGNode) ) continue; - if( _separateControlCluster && !doCtrl && (n instanceof CFGNode) ) 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\n"); - sb.append("\t\t\t\n"); - sb.append("\t\t\t"); - boolean doProjTable = false; - n._outputs.sort((x,y) -> x instanceof ProjNode xp && y instanceof ProjNode yp ? (xp._idx - yp._idx) : (x._nid - y._nid)); - for (Node use : n._outputs) { - if (use instanceof ProjNode proj) { - if (!doProjTable) { - doProjTable = true; - sb.append("
").append(lab).append("
").append("\n"); - sb.append("\t\t\t\t").append("\n"); - sb.append("\t\t\t\t"); - } - sb.append(""); - } - if (use instanceof CProjNode proj) { - if (!doProjTable) { - doProjTable = true; - sb.append(""); - } - sb.append("\n"); - sb.append("\t\t\t
").append(proj.glabel()).append("").append("\n"); - sb.append("\t\t\t\t").append("\n"); - sb.append("\t\t\t\t"); - } - sb.append(""); - } - } - if (doProjTable) { - sb.append("").append("\n"); - sb.append("\t\t\t\t
").append(proj.glabel()).append("
").append("\n"); - sb.append("\t\t\t
>\n\t\t"); - - } else { - // control nodes have box shape - // other nodes are ellipses, i.e. default shape - if( n instanceof CFGNode ) 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.uniqueName()).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 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 last = scope.nIns(); - int max = scope.depth(); - for( int i = 0; i < max; i++ ) { - int level = max-i-1; - String scopeName = makeScopeName(scope, level); - sb.append("\tsubgraph cluster_").append(scopeName).append(" {\n"); // Magic "cluster_" in the subgraph name - // Special for memory ScopeMinNode - if( level==0 ) { - Node n = scope.mem(); - sb.append("\t\t").append(n.uniqueName()).append(" [label=\"").append(n.glabel()).append("\"];\n"); - } - sb.append("\t\t").append(scopeName).append(" [label=<\n"); - sb.append("\t\t\t\n"); - // Add the scope level - sb.append("\t\t\t"); - int lexStart = scope._kinds.at(level)._lexSize; - for( int j=lexStart; j").append(v._name).append(""); - } - last = lexStart; - sb.append("\n"); - sb.append("\t\t\t
").append(level).append("
>];\n"); - } - // 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( max ) ); // 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 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 instanceof XCtrlNode ) - continue; - for( int i=0; idef 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 instanceof CFGNode ) - 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=0; - for( var v : scope._vars ) { - Node def = scope.in(v._idx); - while( def instanceof ScopeNode lazy ) - def = lazy.in(v._idx); - if( def==null ) continue; - while( level < scope.depth() && v._idx >= scope._kinds.at(level)._lexSize ) - level++; - String scopeName = makeScopeName(scope, level-1); - sb.append("\t") - .append(scopeName).append(":") - .append('"').append(makePortName(scopeName, v._name)).append('"') // wrap port name with quotes because $ctrl is not valid unquoted - .append(" -> "); - if( def instanceof CProjNode proj ) { - sb.append(def.in(0).uniqueName()).append(":p").append(proj._idx); - } else if( def instanceof ProjNode proj ) { - sb.append(def.in(0).uniqueName()).append(":p").append(proj._idx); - } else sb.append(def.uniqueName()); - sb.append(";\n"); - } - } - - /** - * Finds all nodes in the graph. - */ - public static Collection findAll(Stack ss, Node... ns) { - final HashMap all = new HashMap<>(); - for( Node n : ns ) - walk(all, n); - if( ss != null ) - for( Node n : ss ) - walk(all, n); - return all.values(); - } - - /** - * Walk a subgraph and populate distinct nodes in the all list. - */ - private static void walk(HashMap 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/chapter25/src/main/java/com/seaofnodes/simple/print/JSViewer.java b/chapter25/src/main/java/com/seaofnodes/simple/print/JSViewer.java deleted file mode 100644 index 03842119..00000000 --- a/chapter25/src/main/java/com/seaofnodes/simple/print/JSViewer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.seaofnodes.simple.print; - -import com.seaofnodes.graph.*; -import com.seaofnodes.simple.codegen.CodeGen; -import java.io.IOException; - -public class JSViewer extends GraphViewer { - public static void main(String[] args) throws IOException { - try( var view = new JSViewer() ) { view.run(); } - } - JSViewer() throws IOException {} - - @Override protected void compile(String src) { - CodeGen code = new CodeGen(src); - code._obs = new SimpleGraphObserver(code) { - @Override protected void frame(GraphSnapshot snap, int pos, GraphEvent evt) throws IOException { - JSViewer.this.frame(snap, pos, evt); - } - }; - try { - code.parse().opto(); - } finally { - code._obs = null; - } - } -} diff --git a/chapter25/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java b/chapter25/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java index 0318b793..7af718ac 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java @@ -1,17 +1,30 @@ package com.seaofnodes.simple.print; import com.seaofnodes.graph.GraphCapture; +import com.seaofnodes.graph.GraphViewer; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.Node; import java.util.ArrayList; +import java.io.IOException; /** Chapter 25's compilation context; capture and event bookkeeping are shared. */ -public abstract class SimpleGraphObserver extends GraphCapture { - private final CodeGen _code; - protected SimpleGraphObserver(CodeGen code) { super(new SimpleGraphAdapter()); _code = code; } +public class SimpleGraphObserver extends GraphCapture { + private CodeGen _code; + public SimpleGraphObserver() { super(new SimpleGraphAdapter()); } + public static void main(String[] args) throws IOException { + GraphViewer.run(new SimpleGraphObserver()); + } + @Override protected void compile(String src) { + _code = new CodeGen(src); + _code._obs = this; + _code.parse().opto(); + } @Override protected String phase() { return _code._phase.name(); } @Override protected int pos() { return _code._phase == CodeGen.Phase.Parse ? _code.P.pos() : -1; } - @Override protected void detach() { _code._obs = null; } + @Override protected void detach() { + if( _code != null ) _code._obs = null; + _code = null; + } @Override protected void roots(ArrayList roots) { roots.add(_code._stop); if( _code._phase == CodeGen.Phase.Parse ) { diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Simple.java b/chapter25/src/test/java/com/seaofnodes/simple/Simple.java index 91f690eb..b7e10122 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Simple.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Simple.java @@ -54,7 +54,6 @@ Options: --dump-after-encode - dump intermediate representation after encoding pass --dump-after-all - dump intermediate representation after all passes --dump - dump final intermediate representation only - --dot - dump grapical representation of intermediate code into *.dot file(s) """ ); System.exit(0); @@ -91,7 +90,6 @@ Options: boolean do_run = true; boolean do_codegen = false; boolean emit_main = false; - boolean dump_dot = false; boolean print_time = false; boolean print_size = false; boolean print_asm = false; @@ -126,7 +124,6 @@ Options: case "--dump-after-export": dump |= 1<