summaryrefslogtreecommitdiff
path: root/chapter02/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'chapter02/src/main/java')
-rw-r--r--chapter02/src/main/java/com/seaofnodes/simple/GraphVisualizer.java117
-rw-r--r--chapter02/src/main/java/com/seaofnodes/simple/Parser.java9
-rw-r--r--chapter02/src/main/java/com/seaofnodes/simple/node/AddNode.java2
-rw-r--r--chapter02/src/main/java/com/seaofnodes/simple/node/DivNode.java2
-rw-r--r--chapter02/src/main/java/com/seaofnodes/simple/node/MinusNode.java2
-rw-r--r--chapter02/src/main/java/com/seaofnodes/simple/node/MulNode.java2
-rw-r--r--chapter02/src/main/java/com/seaofnodes/simple/node/Node.java28
-rw-r--r--chapter02/src/main/java/com/seaofnodes/simple/node/SubNode.java2
-rw-r--r--chapter02/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java45
-rw-r--r--chapter02/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java37
10 files changed, 109 insertions, 137 deletions
diff --git a/chapter02/src/main/java/com/seaofnodes/simple/GraphVisualizer.java b/chapter02/src/main/java/com/seaofnodes/simple/GraphVisualizer.java
deleted file mode 100644
index 4c625be1..00000000
--- a/chapter02/src/main/java/com/seaofnodes/simple/GraphVisualizer.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package com.seaofnodes.simple;
-
-import com.seaofnodes.simple.node.*;
-
-import java.util.*;
-
-/**
- * Simple visualizer that outputs GraphViz dot format.
- * The dot output must be saved to a file and run manually via dot to generate the SVG output.
- * Currently, this is done manually.
- */
-public class GraphVisualizer {
-
- public String generateDotOutput(Parser parser) {
-
- // Since the graph has cycles, we need to create a flat list of all the
- // nodes in the graph.
- Collection<Node> all = findAll(parser);
- StringBuilder sb = new StringBuilder();
- sb.append("digraph chapter02 {\n");
- sb.append("/*\n");
- sb.append(parser.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
-
- // 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");
-
- // Just the Nodes first, in a cluster no edges
- nodes(sb, all);
-
- // Walk the Node edges
- nodeEdges(sb, all);
-
- sb.append("}\n");
- return sb.toString();
- }
-
-
- private void nodes(StringBuilder sb, Collection<Node> all) {
- // Just the Nodes first, in a cluster no edges
- sb.append("\tsubgraph cluster_Nodes {\n"); // Magic "cluster_" in the subgraph name
- for( Node n : all ) {
- sb.append("\t\t").append(n.uniqueName()).append(" [ ");
- String lab = n.glabel();
- // control nodes have box shape
- // other nodes are ellipses, i.e. default shape
- if( n.isCFG() )
- sb.append("shape=box style=filled fillcolor=yellow ");
- sb.append("label=\"").append(lab).append("\" ");
- sb.append("];\n");
- }
- sb.append("\t}\n"); // End Node cluster
- }
-
-
- // 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 ) {
- // In this chapter we do display the Constant->Start edge;
- int i=0;
- for( Node def : n._inputs ) {
- if( def != null ) {
- // Most edges land here use->def
- sb.append('\t').append(n.uniqueName()).append(" -> ");
- sb.append(def.uniqueName());
- // Number edges, so we can see how they track
- sb.append("[taillabel=").append(i);
- if( n instanceof ConstantNode && def instanceof StartNode )
- sb.append(" style=dotted");
- // control edges are colored red
- else if( def.isCFG() )
- sb.append(" color=red");
- sb.append("];\n");
- }
- i++;
- }
- }
- }
-
- /**
- * Finds all nodes in the graph.
- */
- private Collection<Node> findAll(Parser parser) {
- final StartNode start = Parser.START;
- final HashMap<Integer, Node> all = new HashMap<>();
- for( Node n : start._outputs )
- walk(all, n);
- return all.values();
- }
-
- /**
- * Walk a subgraph and populate distinct nodes in the all list.
- */
- private void walk(HashMap<Integer, Node> all, Node n) {
- if (all.get(n._nid) != null) return; // Been there, done that
- all.put(n._nid, n);
- for (Node c : n._inputs)
- if (c != null)
- walk(all, c);
- for (Node c : n._outputs)
- if (c != null)
- walk(all, c);
- }
-}
diff --git a/chapter02/src/main/java/com/seaofnodes/simple/Parser.java b/chapter02/src/main/java/com/seaofnodes/simple/Parser.java
index 72da8eeb..f59b0f25 100644
--- a/chapter02/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter02/src/main/java/com/seaofnodes/simple/Parser.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple;
+import com.seaofnodes.graph.GraphObserver;
+
import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.type.*;
@@ -12,6 +14,12 @@ import com.seaofnodes.simple.type.*;
*/
public class Parser {
+ // Current compilation context; the observer belongs to the parser.
+ public static Parser PARSER;
+ public GraphObserver<Node> _obs;
+ public int pos() { return _lexer._position; }
+
+
/**
* A Global Static, unique to each compilation. This is a public, so we
* can make constants everywhere without having to thread the StartNode
@@ -27,6 +35,7 @@ public class Parser {
public Parser(String source) {
_lexer = new Lexer(source);
+ PARSER = this;
Node.reset();
START = new StartNode();
}
diff --git a/chapter02/src/main/java/com/seaofnodes/simple/node/AddNode.java b/chapter02/src/main/java/com/seaofnodes/simple/node/AddNode.java
index 7c1968c5..814b99b8 100644
--- a/chapter02/src/main/java/com/seaofnodes/simple/node/AddNode.java
+++ b/chapter02/src/main/java/com/seaofnodes/simple/node/AddNode.java
@@ -7,8 +7,6 @@ public class AddNode extends Node {
@Override public String label() { return "Add"; }
- @Override public String glabel() { return "+"; }
-
@Override
StringBuilder _print1(StringBuilder sb) {
in(1)._print0(sb.append("("));
diff --git a/chapter02/src/main/java/com/seaofnodes/simple/node/DivNode.java b/chapter02/src/main/java/com/seaofnodes/simple/node/DivNode.java
index e3c3616a..fc893e27 100644
--- a/chapter02/src/main/java/com/seaofnodes/simple/node/DivNode.java
+++ b/chapter02/src/main/java/com/seaofnodes/simple/node/DivNode.java
@@ -8,8 +8,6 @@ public class DivNode extends Node {
@Override public String label() { return "Div"; }
- @Override public String glabel() { return "//"; }
-
@Override
StringBuilder _print1(StringBuilder sb) {
in(1)._print0(sb.append("("));
diff --git a/chapter02/src/main/java/com/seaofnodes/simple/node/MinusNode.java b/chapter02/src/main/java/com/seaofnodes/simple/node/MinusNode.java
index 0d59ef25..b83c41a5 100644
--- a/chapter02/src/main/java/com/seaofnodes/simple/node/MinusNode.java
+++ b/chapter02/src/main/java/com/seaofnodes/simple/node/MinusNode.java
@@ -8,8 +8,6 @@ public class MinusNode extends Node {
@Override public String label() { return "Minus"; }
- @Override public String glabel() { return "-"; }
-
@Override
StringBuilder _print1(StringBuilder sb) {
in(1)._print0(sb.append("(-"));
diff --git a/chapter02/src/main/java/com/seaofnodes/simple/node/MulNode.java b/chapter02/src/main/java/com/seaofnodes/simple/node/MulNode.java
index 26c28281..b2b2f9c0 100644
--- a/chapter02/src/main/java/com/seaofnodes/simple/node/MulNode.java
+++ b/chapter02/src/main/java/com/seaofnodes/simple/node/MulNode.java
@@ -8,8 +8,6 @@ public class MulNode extends Node {
@Override public String label() { return "Mul"; }
- @Override public String glabel() { return "*"; }
-
@Override
StringBuilder _print1(StringBuilder sb) {
in(1)._print0(sb.append("("));
diff --git a/chapter02/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter02/src/main/java/com/seaofnodes/simple/node/Node.java
index fd233108..7e278173 100644
--- a/chapter02/src/main/java/com/seaofnodes/simple/node/Node.java
+++ b/chapter02/src/main/java/com/seaofnodes/simple/node/Node.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.simple.Parser;
+
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.Type;
@@ -66,13 +68,9 @@ public abstract class Node {
// Easy reading label for debugger, e.g. "Add" or "Region" or "EQ"
public abstract String label();
- // Unique label for graph visualization, e.g. "Add12" or "Region30" or "EQ99"
+ // Unique label for debugging, e.g. "Add12" or "Region30" or "EQ99"
public String uniqueName() { return label() + _nid; }
- // Graphical label, e.g. "+" or "Region" or "=="
- public String glabel() { return label(); }
-
-
// ------------------------------------------------------------------------
// Debugger Printing.
@@ -178,7 +176,7 @@ public abstract class Node {
}
// Mostly used for asserts and printing.
- boolean isDead() { return isUnused() && nIns()==0 && _type==null; }
+ public boolean isDead() { return isUnused() && nIns()==0 && _type==null; }
/**
* We allow disabling peephole opt so that we can observe the
* full graph, vs the optimized graph.
@@ -196,12 +194,22 @@ public abstract class Node {
* <li>we ask the Node for a better replacement (again, none enabled in this chapter)</li>
* </ul>
*/
- public final Node peephole( ) {
+ public final Node peephole() {
+ var obs = Parser.PARSER == null ? null : Parser.PARSER._obs;
+ if( obs != null ) obs.before(this);
+ Type old = _type;
+ Node n = peepholeOpt();
+ Node rez = n == null ? this : n;
+ if( obs != null ) obs.after(this, n == null && old == _type ? null : rez, false);
+ return rez;
+ }
+
+ private Node peepholeOpt() {
// Compute initial or improved Type
Type type = _type = compute();
if (_disablePeephole)
- return this; // Peephole optimizations turned off
+ return null; // Peephole optimizations turned off
// Replace constant computations from non-constants with a constant node
if (!(this instanceof ConstantNode) && type.isConstant()) {
@@ -215,8 +223,8 @@ public abstract class Node {
Node n = idealize();
if( n != null ) return n;
- return this; // No progress
- }
+ return null; // No progress
+ }
/**
diff --git a/chapter02/src/main/java/com/seaofnodes/simple/node/SubNode.java b/chapter02/src/main/java/com/seaofnodes/simple/node/SubNode.java
index d2e32c61..1d2ddaa0 100644
--- a/chapter02/src/main/java/com/seaofnodes/simple/node/SubNode.java
+++ b/chapter02/src/main/java/com/seaofnodes/simple/node/SubNode.java
@@ -8,8 +8,6 @@ public class SubNode extends Node {
@Override public String label() { return "Sub"; }
- @Override public String glabel() { return "-"; }
-
@Override
StringBuilder _print1(StringBuilder sb) {
in(1)._print0(sb.append("("));
diff --git a/chapter02/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java b/chapter02/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
new file mode 100644
index 00000000..502a2a8e
--- /dev/null
+++ b/chapter02/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
@@ -0,0 +1,45 @@
+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 java.util.ArrayList;
+
+/** Chapter 2'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); }
+
+ private ArrayList<Edge> edges(Node n) {
+ var edges = new ArrayList<Edge>();
+ for( int i = 0; i < n.nIns(); i++ ) {
+ String name = null;
+ edges.add(new Edge(i, ref(n.in(i)), role(n, i), name));
+ }
+ return edges;
+ }
+
+ @Override protected GraphSnapshot.Node desc(Node n) {
+ Projection proj = null;
+ String label = n.label();
+ return new GraphSnapshot.Node(n._nid, label == null ? n.getClass().getSimpleName() : label,
+ n._type == null ? null : n._type.toString(), kind(n), edges(n), proj);
+ }
+
+ private Kind kind(Node n) {
+ if( n instanceof StartNode ) return Kind.CTRL;
+ return n.isCFG() ? Kind.CTRL : Kind.DATA;
+ }
+
+ private Role role(Node n, int i) {
+ if( n instanceof ConstantNode ) return Role.ASSOC;
+ if( i == 0 ) return Role.CTRL;
+ return Role.DATA;
+ }
+}
diff --git a/chapter02/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java b/chapter02/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java
new file mode 100644
index 00000000..a17bf796
--- /dev/null
+++ b/chapter02/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java
@@ -0,0 +1,37 @@
+package com.seaofnodes.simple.print;
+
+import com.seaofnodes.graph.GraphCapture;
+import com.seaofnodes.graph.GraphViewer;
+import com.seaofnodes.simple.Parser;
+import com.seaofnodes.simple.node.Node;
+import java.util.ArrayList;
+import java.io.IOException;
+
+/** Chapter 2's compilation context; capture and event bookkeeping are shared. */
+public class SimpleGraphObserver extends GraphCapture<Node> {
+ private Parser _parser;
+ private Node _ret;
+ private String _phase;
+ public SimpleGraphObserver() { super(new SimpleGraphAdapter()); }
+ public static void main(String[] args) throws IOException {
+ GraphViewer.run(new SimpleGraphObserver());
+ }
+ @Override protected void compile(String src) {
+ _parser = new Parser(src);
+ _parser._obs = this;
+ _phase = "Parse";
+ _ret = _parser.parse();
+ phase(_phase);
+ }
+ @Override protected String phase() { return _phase; }
+ @Override protected int pos() { return "Parse".equals(_phase) ? _parser.pos() : -1; }
+ @Override protected void detach() {
+ if( _parser != null ) _parser._obs = null;
+ _parser = null;
+ _ret = null;
+ }
+ @Override protected void roots(ArrayList<Node> roots) {
+ roots.add(Parser.START);
+ roots.add(_ret);
+ }
+}