diff options
| author | Cliff Click <cliffc@acm.org> | 2026-09-22 11:25:05 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2026-09-22 11:25:05 -0700 |
| commit | 29fb671e69f90ad3b04c6fa8d746caf857f89e77 (patch) | |
| tree | 2f39d082f8a6de6a2b60b66406f8c9f0190d25c2 /chapter25/src/main | |
| parent | 1d961838cff168a101069d08a8ab6594f49f0911 (diff) | |
| download | Simple-29fb671e69f90ad3b04c6fa8d746caf857f89e77.tar.gz Simple-29fb671e69f90ad3b04c6fa8d746caf857f89e77.zip | |
Add shared graph viewer to all chapters
Diffstat (limited to 'chapter25/src/main')
28 files changed, 26 insertions, 383 deletions
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<<p2)) == 0 ) return p2; - if( (dump & (1<<29)) != 0 ) { - String fn = ""+p2+"-"+_phase+".dot"; - try { - Files.writeString(Path.of(fn), - new GraphVisualizer().generateDotOutput(compunit(), null, null)); - } catch(IOException e) { throw Utils.TODO("Cannot write DOT file"); } - return p2; - } + if( (dump & (1<<30)) != 0 ) System.err.println("After "+_phase+":"); @@ -866,16 +859,14 @@ public class CodeGen { public Ary<CFGNode> _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<String,Integer> strs, HashMap<Type,Integer> types, IdentityHashMap<Node,Integer> 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 @@ -24,9 +24,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); in(2)._print0(sb.append(op()), 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<String,Type> 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<ScopeNode> xScopes) { - - // Since the graph has cycles, we need to create a flat list of all the - // nodes in the graph. - Collection<Node> all = findAll(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<Node> all) { - if (!_separateControlCluster && doCtrl) // all nodes in 1 cluster - return; - // Just the Nodes first, in a cluster no edges - sb.append(doCtrl ? "\tsubgraph cluster_Controls {\n" : "\tsubgraph cluster_Nodes {\n"); // Magic "cluster_" in the subgraph name - for (Node n : all) { - if( n instanceof ProjNode || n instanceof CProjNode || n instanceof 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<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">\n"); - sb.append("\t\t\t<TR><TD BGCOLOR=\"yellow\">").append(lab).append("</TD></TR>\n"); - sb.append("\t\t\t<TR>"); - boolean doProjTable = false; - 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("<TD>").append("\n"); - sb.append("\t\t\t\t<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">").append("\n"); - sb.append("\t\t\t\t<TR>"); - } - sb.append("<TD PORT=\"p").append(proj._idx).append("\">").append(proj.glabel()).append("</TD>"); - } - if (use instanceof CProjNode proj) { - if (!doProjTable) { - doProjTable = true; - sb.append("<TD>").append("\n"); - sb.append("\t\t\t\t<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">").append("\n"); - sb.append("\t\t\t\t<TR>"); - } - sb.append("<TD PORT=\"p").append(proj._idx).append("\" BGCOLOR=\"yellow\">").append(proj.glabel()).append("</TD>"); - } - } - if (doProjTable) { - sb.append("</TR>").append("\n"); - sb.append("\t\t\t\t</TABLE>").append("\n"); - sb.append("\t\t\t</TD>"); - } - sb.append("</TR>\n"); - sb.append("\t\t\t</TABLE>>\n\t\t"); - - } else { - // control nodes have box shape - // other nodes are ellipses, i.e. default shape - if( n 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<Node> all) { - nodesByCluster(sb, true, all); - nodesByCluster(sb, false, all); - } - - // Build a nested scope display, walking the _prev edge - private void scope( StringBuilder sb, ScopeNode scope ) { - sb.append("\tnode [shape=plaintext];\n"); - int 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<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n"); - // Add the scope level - sb.append("\t\t\t<TR><TD BGCOLOR=\"cyan\">").append(level).append("</TD>"); - int lexStart = scope._kinds.at(level)._lexSize; - for( int j=lexStart; j<last; j++ ) { - var v = scope._vars.at(j); - sb.append("<TD PORT=\"").append(makePortName(scopeName, v._name)).append("\">").append(v._name).append("</TD>"); - } - last = lexStart; - sb.append("</TR>\n"); - sb.append("\t\t\t</TABLE>>];\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<Node> all) { - // All them edge labels - sb.append("\tedge [ fontname=Helvetica, fontsize=8 ];\n"); - for( Node n : all ) { - // Do not display the Constant->Start edge; - // ProjNodes handled by Multi; - // ScopeNodes are done separately - if( n instanceof ConstantNode || n instanceof ProjNode || n instanceof CProjNode || n instanceof ScopeNode || n instanceof XCtrlNode ) - continue; - for( int i=0; i<n.nIns(); i++ ) { - Node def = n.in(i); - if( n instanceof PhiNode && def instanceof RegionNode ) { - // Draw a dotted use->def edge from Phi to Region. - sb.append('\t').append(n.uniqueName()); - sb.append(" -> "); - sb.append(def.uniqueName()); - sb.append(" [style=dotted taillabel=").append(i).append("];\n"); - } else if( def != null ) { - // Most edges land here use->def - sb.append('\t').append(n.uniqueName()).append(" -> "); - if( def instanceof CProjNode proj ) { - String mname = proj.ctrl().uniqueName(); - sb.append(mname).append(":p").append(proj._idx); - } else if( def instanceof ProjNode proj ) { - String mname = proj.in(0).uniqueName(); - sb.append(mname).append(":p").append(proj._idx); - } else sb.append(def.uniqueName()); - // Number edges, so we can see how they track - sb.append("[taillabel=").append(i); - // The edge from New to ctrl is just for anchoring the New - if ( n instanceof NewNode ) - sb.append(" color=green"); - // control edges are colored red - else if( def 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<Node> findAll(Stack<ScopeNode> ss, Node... ns) { - final HashMap<Integer, Node> 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<Integer,Node> all, Node n) { - if(n == null ) return; - if (all.get(n._nid) != null) return; // Been there, done that - all.put(n._nid, n); - for (Node c : n._inputs) - walk(all, c); - for( Node c : n._outputs ) - walk(all, c); - } -} diff --git a/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<Node> { - private final CodeGen _code; - protected SimpleGraphObserver(CodeGen code) { super(new SimpleGraphAdapter()); _code = code; } +public class SimpleGraphObserver extends GraphCapture<Node> { + 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<Node> roots) { roots.add(_code._stop); if( _code._phase == CodeGen.Phase.Parse ) { |
