summaryrefslogtreecommitdiff
path: root/chapter20/src/main/java/com/seaofnodes
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 /chapter20/src/main/java/com/seaofnodes
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 'chapter20/src/main/java/com/seaofnodes')
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java2
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/AddFNode.java9
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/AddNode.java9
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/BoolNode.java10
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/CProjNode.java5
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/CallEndNode.java14
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/CallNode.java16
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/CastNode.java10
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/ConstantNode.java17
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/CtrlNode.java5
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/DivFNode.java9
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/DivNode.java9
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/FRefNode.java8
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/IfNode.java8
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/LoadNode.java5
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/LogicalNode.java10
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/MachConcreteNode.java12
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java12
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/MemOpNode.java6
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/MinusFNode.java8
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/MinusNode.java8
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/MulFNode.java9
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/MulNode.java9
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/NeverNode.java5
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/NewNode.java9
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/Node.java70
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/NotNode.java8
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/ParmNode.java19
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/PhiNode.java19
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/ProjNode.java11
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/ReadOnlyNode.java7
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/RegionNode.java7
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/ReturnNode.java13
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java7
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/ScopeNode.java28
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/SplitNode.java13
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/StartNode.java8
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/StopNode.java13
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/StoreNode.java7
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/StructNode.java18
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/SubFNode.java9
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/SubNode.java9
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java7
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/XCtrlNode.java5
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java2
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java5
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java13
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java8
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java5
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java7
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java13
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java192
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/print/IRPrinter.java396
-rw-r--r--chapter20/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java38
54 files changed, 324 insertions, 857 deletions
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/chapter20/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
index 93362799..78cf4c06 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
@@ -347,7 +347,7 @@ public class CodeGen {
@Override public String toString() {
return _phase.ordinal() > Phase.Schedule.ordinal()
? IRPrinter._prettyPrint( this )
- : _stop.p(9999);
+ : IRPrinter.prettyPrint(this);
}
// Debugging helper
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/AddFNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/AddFNode.java
index 5d0a473a..fd713156 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/AddFNode.java
+++ b/chapter20/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/chapter20/src/main/java/com/seaofnodes/simple/node/AddNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/AddNode.java
index e1d16cf3..01cb6bb7 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/AddNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/AddNode.java
@@ -1,9 +1,9 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
import static com.seaofnodes.simple.Parser.con;
@@ -12,12 +12,7 @@ public class AddNode extends Node {
@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/chapter20/src/main/java/com/seaofnodes/simple/node/BoolNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/BoolNode.java
index 9faa5181..85bcae0f 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/BoolNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/BoolNode.java
@@ -1,9 +1,10 @@
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.*;
-import java.util.BitSet;
import static com.seaofnodes.simple.type.TypeInteger.*;
abstract public class BoolNode extends Node {
@@ -17,11 +18,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/chapter20/src/main/java/com/seaofnodes/simple/node/CProjNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/CProjNode.java
index adc4e66f..bfdcb04b 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/CProjNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/CProjNode.java
@@ -1,11 +1,12 @@
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;
import com.seaofnodes.simple.type.TypeMem;
import com.seaofnodes.simple.type.TypeTuple;
-import java.util.BitSet;
public class CProjNode extends CFGNode {
@@ -24,7 +25,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 blockHead() { return true; }
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/CallEndNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/CallEndNode.java
index c90e0530..ba04922b 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/CallEndNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/CallEndNode.java
@@ -1,9 +1,10 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.*;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
/**
* CallEnd
@@ -24,13 +25,12 @@ public class CallEndNode extends CFGNode implements MultiNode {
public CallNode call() { return (CallNode)in(0); }
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- sb.append("cend( ");
- sb.append( in(0) instanceof CallNode ? "Call, " : "----, ");
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ p.p("cend( ");
+ p.p( in(0) instanceof CallNode ? "Call, " : "----, ");
for( int i=1; i<nIns()-1; i++ )
- in(i)._print0(sb,visited).append(",");
- sb.setLength(sb.length()-1);
- return sb.append(")");
+ p.n(in(i)).p(",");
+ return p.unchar(',').unchar(' ').close();
}
@Override
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/CallNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/CallNode.java
index a3f880b6..ba09d1cc 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/CallNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/CallNode.java
@@ -1,12 +1,13 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeFunPtr;
-import java.util.BitSet;
/**
* Call
@@ -21,15 +22,14 @@ public class CallNode extends CFGNode {
@Override public String label() { return "Call"; }
- @Override StringBuilder _print1(StringBuilder sb, BitSet visited) {
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
String fname = name();
- if( fname == null ) fptr()._print0(sb,visited);
- else sb.append(fname);
- sb.append("( ");
+ if( fname == null ) p.n(fptr());
+ else p.p(fname);
+ p.p("( ");
for( int i=2; i<nIns()-1; i++ )
- in(i)._print0(sb,visited).append(",");
- sb.setLength(sb.length()-1);
- return sb.append(")");
+ p.n(in(i)).p(",");
+ return p.unchar(',').unchar(' ').close();
}
public String name() {
if( fptr()._type instanceof TypeFunPtr tfp && tfp.isConstant() && tfp.notNull() ) {
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/CastNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/CastNode.java
index f3ee1aa2..9aedf53e 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/CastNode.java
+++ b/chapter20/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.Parser;
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;
-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.
@@ -24,14 +25,11 @@ public class CastNode extends Node {
@Override public String label() { return "("+_t.str()+")"; }
- @Override
- public String uniqueName() { return "Cast_" + _nid; }
@Override public boolean isConst() { return true; }
- @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/chapter20/src/main/java/com/seaofnodes/simple/node/ConstantNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/ConstantNode.java
index 5ddf47a1..cadb6511 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/ConstantNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/ConstantNode.java
@@ -1,11 +1,12 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeFunPtr;
-import java.util.BitSet;
/**
* A Constant node represents a constant value. At present, the only constants
@@ -35,18 +36,20 @@ public class ConstantNode extends Node {
return new ConstantNode(type);
}
- @Override public String label() { return "#"+_con; }
- @Override
- public String uniqueName() { return "Con_" + _nid; }
+ @Override protected String repeatName() {
+ return _con==null || _con.toString().length()<=32 ? null : uniqueName();
+ }
+
+ @Override public String label() { return "Con"; }
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
if( _con instanceof TypeFunPtr tfp && tfp.isConstant() && tfp.notNull() ) {
FunNode fun = CodeGen.CODE.link(tfp);
if( fun!=null && fun._name != null )
- return sb.append("{ ").append(fun._name).append("}");
+ return p.p("{ ").p(fun._name).p("}");
}
- return sb.append(_con.print(new SB()));
+ return p.p(_con.print(new SB()));
}
@Override public boolean isConst() { return true; }
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/CtrlNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/CtrlNode.java
index 61d9c310..cf630ad4 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/CtrlNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/CtrlNode.java
@@ -1,14 +1,15 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.type.Type;
-import java.util.BitSet;
public class CtrlNode extends CFGNode {
public CtrlNode() { super(CodeGen.CODE._start); }
@Override public String label() { return "Ctrl"; }
- @Override StringBuilder _print1(StringBuilder sb, BitSet visited) { return sb.append("Cctrl"); }
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) { return p.p("Cctrl"); }
@Override public boolean isConst() { return true; }
@Override public Type compute() { return Type.CONTROL; }
@Override public Node idealize() { return null; }
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/DivFNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/DivFNode.java
index 258720c8..149499f9 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/DivFNode.java
+++ b/chapter20/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/chapter20/src/main/java/com/seaofnodes/simple/node/DivNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/DivNode.java
index 69b151cd..f0ee21e1 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/DivNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/DivNode.java
@@ -1,20 +1,15 @@
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/chapter20/src/main/java/com/seaofnodes/simple/node/FRefNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/FRefNode.java
index f0c4045d..bf1c5a00 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/FRefNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/FRefNode.java
@@ -1,9 +1,10 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.Var;
import com.seaofnodes.simple.type.Type;
-import java.util.BitSet;
/**
* A Forward Reference. Its any final constant, including functions. When
@@ -17,10 +18,9 @@ public class FRefNode extends ConstantNode {
@Override public String label() { return "FRef"+_n; }
- @Override public String uniqueName() { return "FRef_" + _nid; }
- @Override StringBuilder _print1(StringBuilder sb, BitSet visited) {
- return sb.append("FRef_").append(_n);
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ return p.p("FRef_").p(_n);
}
@Override public Node idealize() {
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/IfNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/IfNode.java
index e04522b0..2c4cad70 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/IfNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/IfNode.java
@@ -1,9 +1,9 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
import java.util.HashSet;
public class IfNode extends CFGNode implements MultiNode {
@@ -17,11 +17,7 @@ public class IfNode extends CFGNode implements MultiNode {
@Override
public String label() { return "If"; }
- @Override
- public StringBuilder _print1(StringBuilder sb, BitSet visited) {
- sb.append("if( ");
- return in(1)._print0(sb, visited).append(" )");
- }
+ @Override protected String format() { return "if( %1 )"; }
public Node ctrl() { return in(0); }
public Node pred() { return in(1); }
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/LoadNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/LoadNode.java
index 76125e39..339e4460 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/LoadNode.java
+++ b/chapter20/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.codegen.CodeGen;
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
/**
* Load represents extracting a value from inside a memory object,
@@ -46,7 +47,7 @@ public class LoadNode extends MemOpNode {
// Debugger label
@Override public String label() { return "ld_"+mlabel(); }
@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/chapter20/src/main/java/com/seaofnodes/simple/node/LogicalNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/LogicalNode.java
index 8c3452bf..6ac16d31 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/LogicalNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/LogicalNode.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 com.seaofnodes.simple.type.TypeInteger;
-import java.util.BitSet;
public abstract class LogicalNode extends Node {
// Source location for late reported errors
@@ -12,11 +13,8 @@ public abstract class LogicalNode extends Node {
public LogicalNode(Parser.Lexer loc, Node lhs, Node rhs) { super(null, lhs, rhs); _loc = loc; }
abstract String op();
- @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();
}
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/MachConcreteNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/MachConcreteNode.java
index b01b3308..4f5d9151 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/MachConcreteNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/MachConcreteNode.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.Utils;
import java.io.ByteArrayOutputStream;
-import java.util.BitSet;
// Generic machine-specific class, has a few Node implementations that have to
// exist (abstract) but are not useful past the optimizer.
@@ -16,12 +17,11 @@ public abstract class MachConcreteNode extends Node implements MachNode {
@Override public Type compute () { throw Utils.TODO(); }
@Override public Node idealize() { throw Utils.TODO(); }
- @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) {
- sb.append("(").append(op()).append(",");
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ p.open().p(op()).p(",");
for( int i=1; i<nIns(); i++ )
- (in(i)==null ? sb.append(" ---") : in(i)._print0(sb, visited)).append(",");
- sb.setLength(sb.length()-1);
- return sb.append(")");
+ (in(i)==null ? p.p(" ---") : p.n(in(i))).p(",");
+ return p.unchar(',').close();
}
}
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java
index 31c76a93..c8a76714 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.*;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.type.*;
@@ -53,14 +55,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/chapter20/src/main/java/com/seaofnodes/simple/node/MemOpNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/MemOpNode.java
index 41760124..4f404846 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/MemOpNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/MemOpNode.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;
@@ -48,8 +50,8 @@ public abstract class MemOpNode extends Node {
public Node ptr() { return in(2); }
public Node off() { return in(3); }
- @Override StringBuilder _print1( StringBuilder sb, BitSet visited ) { return _printMach(sb,visited); }
- public StringBuilder _printMach( StringBuilder sb, BitSet visited ) { throw Utils.TODO(); }
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) { return _printMach(p); }
+ protected ExprPrinter<Node> _printMach(ExprPrinter<Node> p) { throw Utils.TODO(); }
// Extra conditions for factoring matching memory operations through a Phi.
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/MinusFNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/MinusFNode.java
index 129963c2..852e646d 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/MinusFNode.java
+++ b/chapter20/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/chapter20/src/main/java/com/seaofnodes/simple/node/MinusNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/MinusNode.java
index dad245fd..20220915 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/MinusNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/MinusNode.java
@@ -1,21 +1,17 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;
import com.seaofnodes.simple.Utils;
-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/chapter20/src/main/java/com/seaofnodes/simple/node/MulFNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/MulFNode.java
index 4b753ba7..6a57f3c5 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/MulFNode.java
+++ b/chapter20/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/chapter20/src/main/java/com/seaofnodes/simple/node/MulNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/MulNode.java
index c7fb620c..e9dc6887 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/MulNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/MulNode.java
@@ -1,21 +1,16 @@
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 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/chapter20/src/main/java/com/seaofnodes/simple/node/NeverNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/NeverNode.java
index 26198500..7e42ccf9 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/NeverNode.java
+++ b/chapter20/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 public 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/chapter20/src/main/java/com/seaofnodes/simple/node/NewNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/NewNode.java
index b9c9de71..68871918 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/NewNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/NewNode.java
@@ -1,7 +1,8 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
/** Allocate a zeroed object. Inputs {ctrl, $mem, size};
* results {ptr, $mem}.
@@ -34,10 +35,8 @@ public class NewNode extends Node implements MultiNode {
@Override public String label() { return "new_"+(_ptr._obj.isAry() ? "ary_"+_ptr._obj._fields[1]._type.str() : _ptr._obj.str()); }
- @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/chapter20/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter20/src/main/java/com/seaofnodes/simple/node/Node.java
index aecac75c..e038d351 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/Node.java
+++ b/chapter20/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.*;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.print.IRPrinter;
@@ -15,14 +17,7 @@ import static com.seaofnodes.simple.codegen.CodeGen.CODE;
* The Node class provides common functionality used by all subtypes.
* Subtypes of Node specialize by overriding methods.
*/
-public abstract class Node implements 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 Cloneable {
/**
* Inputs to the node. These are use-def references to Nodes.
@@ -44,16 +39,14 @@ public abstract class Node implements Cloneable {
*/
public Ary<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;
-
Node(Node... inputs) {
- _nid = CODE.getUID(); // allocate unique dense ID
+ super(CODE.getUID()); // allocate unique dense ID
_inputs = new Ary<>(Node.class);
Collections.addAll(_inputs,inputs);
_outputs = new Ary<>(Node.class);
@@ -65,8 +58,8 @@ public abstract class Node implements Cloneable {
// Make a Node using the existing arrays of nodes.
// Used by any pass rewriting all Node classes but not the edges.
Node( Node n ) {
+ super(CODE.getUID()); // allocate unique dense ID
assert CodeGen.CODE._phase.ordinal() >= CodeGen.Phase.InstSelect.ordinal();
- _nid = CODE.getUID(); // allocate unique dense ID
_inputs = new Ary<>(n==null ? new Node[0] : n._inputs.asAry());
_outputs = new Ary<>(Node.class);
_type = n==null ? Type.BOTTOM : n._type;
@@ -77,48 +70,6 @@ public abstract class Node implements 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;
- }
-
- // Operator symbol used by assembly/debug printing.
- public String glabel() { return label(); }
-
- // Extra fun stuff, for assembly printing. Jump labels, parser locations,
- // variable types, etc.
- public String comment() { return null; }
-
- // ------------------------------------------------------------------------
-
- // 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. We print with a mutually recursive 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.
- public 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 isConst() { return false; }
@@ -126,6 +77,8 @@ public abstract class Node implements 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
@@ -204,7 +157,6 @@ public abstract class Node implements Cloneable {
return setDef(idx,new_def);
}
-
/**
* Add a new def to an existing Node. Keep the edges correct by
* adding the corresponding <em>def->use</em> edge.
@@ -280,7 +232,6 @@ public abstract class Node implements Cloneable {
kill();
}
-
// Replace self with nnn in the graph, making 'this' go dead
public void subsume( Node nnn ) {
assert nnn!=this;
@@ -525,7 +476,6 @@ public abstract class Node implements 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
@@ -570,7 +520,6 @@ public abstract class Node implements Cloneable {
_deps.clear();
}
-
// Two nodes are equal if they have the same inputs and the same "opcode"
// which means the same Java class, plus same internal parts.
@Override public final boolean equals( Object o ) {
@@ -588,7 +537,6 @@ public abstract class Node implements 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
@@ -604,7 +552,6 @@ public abstract class Node implements Cloneable {
_hash=0; // Out of table now
}
-
// Hash of opcode and inputs
@Override public final int hashCode() {
if( _hash != 0 ) return _hash;
@@ -624,7 +571,6 @@ public abstract class Node implements Cloneable {
/** Is this Node Memory related */
public boolean isMem() { return false; }
-
// 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.
@@ -645,7 +591,6 @@ public abstract class Node implements Cloneable {
}
Node copyF() { return null; }
-
// ------------------------------------------------------------------------
// Peephole utilities
@@ -672,7 +617,6 @@ public abstract class Node implements 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.
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/NotNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/NotNode.java
index 5e631b78..57fa9301 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/NotNode.java
+++ b/chapter20/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 TypeInteger compute() {
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/ParmNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/ParmNode.java
index c7c21171..c3a0cf21 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/ParmNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/ParmNode.java
@@ -1,8 +1,9 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.Type;
-import java.util.BitSet;
public class ParmNode extends PhiNode {
@@ -20,18 +21,12 @@ public class ParmNode extends PhiNode {
public FunNode fun() { return (FunNode)in(0); }
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
if( "main".equals(fun()._name) && _label.equals("arg") )
- return sb.append("arg");
- sb.append("Parm_").append(_label).append("(");
- 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;
+ return p.p("arg");
+ p.p("Parm_").p(_label).open();
+ for( Node in : _inputs ) p.n(in).p(",");
+ return p.unchar(',').close();
}
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/PhiNode.java
index 52298345..a752977b 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/PhiNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/PhiNode.java
@@ -1,8 +1,9 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.*;
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
public class PhiNode extends Node {
@@ -31,18 +32,12 @@ public class PhiNode extends Node {
@Override public String label() { return "Phi_"+MemOpNode.mlabel(_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/chapter20/src/main/java/com/seaofnodes/simple/node/ProjNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/ProjNode.java
index 83044156..da5841f6 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/ProjNode.java
+++ b/chapter20/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,11 +25,11 @@ public class ProjNode extends Node {
@Override public String label() { return _label; }
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- if( _label != null ) return sb.append(_label);
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ if( _label != null ) return p.p(_label);
if( in(0) instanceof CallEndNode cend && cend.call()!=null )
- return cend.call()._print0(sb,visited);
- return sb.append("LONELY PROJ");
+ return p.n(cend.call());
+ return p.p("LONELY PROJ");
}
@Override public CFGNode cfg0() {
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/ReadOnlyNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/ReadOnlyNode.java
index b755af3f..d79f2815 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/ReadOnlyNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/ReadOnlyNode.java
@@ -1,9 +1,9 @@
package com.seaofnodes.simple.node;
+
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeMemPtr;
-import java.util.BitSet;
/**
* Cast a pointer to read-only
@@ -13,10 +13,7 @@ public class ReadOnlyNode extends Node {
public ReadOnlyNode( ReadOnlyNode n ) { super(n); }
@Override public String label() { return "ReadOnly"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- return in(1)._print0(sb.append("(const)"),visited);
- }
+ @Override protected String format() { return "(const)%1"; }
@Override public Type compute() {
Type t = in(1)._type;
return t instanceof TypeMemPtr tmp ? tmp.makeRO() : t;
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/RegionNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/RegionNode.java
index f28952e0..8993a49f 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/RegionNode.java
+++ b/chapter20/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.*;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.type.Type;
@@ -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());
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ return p.p(label());
}
@Override public boolean blockHead() { return true; }
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/ReturnNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/ReturnNode.java
index 7858671c..e101ee09 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/ReturnNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/ReturnNode.java
@@ -1,10 +1,11 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
/** Keeps all preceding memory effects and the return value alive: {ctrl, $mem, value, rpc}. */
public class ReturnNode extends CFGNode {
@@ -27,11 +28,11 @@ public class ReturnNode extends CFGNode {
public String label() { return "Return"; }
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- sb.append("return ");
- if( expr()==null ) sb.append("----");
- else expr()._print0(sb, visited);
- return sb.append(";");
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ p.p("return ");
+ if( expr()==null ) p.p("----");
+ else p.n(expr());
+ return p.p(";");
}
// No one unique control follows; can be many call end sites
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter20/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java
index 3dd7cbf0..78e7698c 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java
@@ -1,19 +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 RoundF32Node extends Node {
public RoundF32Node(Node lhs) { super(null, lhs); }
@Override public String label() { return "RoundF32"; }
- @Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- return in(1)._print0(sb.append("((f32)"), visited).append(")");
- }
+ @Override protected String format() { return "((f32)%1)"; }
@Override
public Type compute() {
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/ScopeNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/ScopeNode.java
index 406be11f..2724d0a6 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/ScopeNode.java
+++ b/chapter20/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.*;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.type.*;
@@ -49,28 +51,26 @@ 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[ ");
int j=1;
for( int i=0; i<nIns(); i++ ) {
- if( j < _lexSize._len && i == _lexSize.at(j) ) { sb.append("| "); j++; }
+ if( j < _lexSize._len && i == _lexSize.at(j) ) { p.p("| "); j++; }
Var v = _vars.get(i);
- sb.append(v._type().print(new SB()));
- sb.append(" ");
- if( v._final ) sb.append("!");
- sb.append(v._name);
- sb.append("=");
+ p.p(v._type().print(new SB()));
+ p.p(" ");
+ if( v._final ) p.p("!");
+ p.p(v._name);
+ p.p("=");
Node n = in(i);
while( n instanceof ScopeNode loop ) {
- sb.append("Lazy_");
+ p.p("Lazy_");
n = loop.in(i);
}
- if( n==null ) sb.append("___");
- else n._print0(sb, visited);
- sb.append(", ");
+ p.n(n);
+ p.p(", ");
}
- sb.setLength(sb.length()-2);
- return sb.append("]");
+ return p.unchar(", ").p("]");
}
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/SplitNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/SplitNode.java
index 37d1a63d..07166a7c 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/SplitNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/SplitNode.java
@@ -1,20 +1,21 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.type.Type;
-import java.util.BitSet;
public abstract class SplitNode extends MachConcreteNode {
public final String _kind; // Kind of split
public final byte _round;
public SplitNode(String kind, byte round, Node[] nodes) { super(nodes); _kind = kind; _round = round; }
@Override public String op() { return "mov"; }
- @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) {
- sb.append("mov(");
- if( in(1)==null ) sb.append("---");
- else in(1)._print0(sb,visited);
- return sb.append(")");
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ p.p("mov(");
+ if( in(1)==null ) p.p("---");
+ else p.n(in(1));
+ return p.close();
}
@Override public Type compute() { return in(0)._type; }
@Override public Node idealize() { return null; }
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/StartNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/StartNode.java
index 2783ab93..cbaefa6a 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/StartNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/StartNode.java
@@ -1,9 +1,10 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
import java.util.HashSet;
import static com.seaofnodes.simple.Utils.TODO;
@@ -17,9 +18,8 @@ public class StartNode extends LoopNode 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 blockHead() { return true; }
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/StopNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/StopNode.java
index 80c911ca..524c6a9e 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/StopNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/StopNode.java
@@ -1,8 +1,9 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.Type;
-import java.util.BitSet;
public class StopNode extends CFGNode {
@@ -21,13 +22,13 @@ public class StopNode extends CFGNode {
}
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
// For the sake of many old tests, and single value prints as "return val"
- if( ret()!=null ) return ret()._print0(sb,visited);
- sb.append("Stop[ ");
+ 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/chapter20/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/StoreNode.java
index 4833df39..e9a35a0d 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/StoreNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/StoreNode.java
@@ -1,9 +1,10 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.codegen.*;
import com.seaofnodes.simple.*;
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
/**
* Store represents setting a value to a memory based object, in chapter 10
@@ -36,8 +37,8 @@ public class StoreNode extends MemOpNode {
public Node val() { return in(4); }
@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/chapter20/src/main/java/com/seaofnodes/simple/node/StructNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/StructNode.java
index 076b342a..b9801f63 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/StructNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/StructNode.java
@@ -1,8 +1,9 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.type.*;
-import java.util.BitSet;
/**
* Build a compound object
@@ -14,16 +15,15 @@ public class StructNode extends Node {
@Override public String label() { return _ts==null ? "STRUCT?" : _ts.str(); }
@Override
- StringBuilder _print1(StringBuilder sb, BitSet visited) {
- if( _ts==null ) return sb.append("STRUCT?");
- sb.append(_ts._name).append(" {");
+ protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ if( _ts==null ) return p.p("STRUCT?");
+ p.p(_ts._name).p(" {");
for( int i=0; i<nIns(); i++ ) {
- sb.append(_ts._fields[i]._fname).append(":");
- sb.append((in(i)==null ? Type.BOTTOM : in(i)._type).print(new SB()));
- sb.append("; ");
+ p.p(_ts._fields[i]._fname).p(":");
+ p.p((in(i)==null ? Type.BOTTOM : in(i)._type).print(new SB()));
+ p.p("; ");
}
- sb.setLength(sb.length()-2);
- return sb.append("}");
+ return p.unchar("; ").p("}");
}
@Override
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/SubFNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/SubFNode.java
index 27bbda8d..2d218a03 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/SubFNode.java
+++ b/chapter20/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/chapter20/src/main/java/com/seaofnodes/simple/node/SubNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/SubNode.java
index 034f2fb1..9bf6d83e 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/SubNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/SubNode.java
@@ -1,21 +1,16 @@
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/chapter20/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
index a4aa8934..7b0122ce 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
+++ b/chapter20/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/chapter20/src/main/java/com/seaofnodes/simple/node/XCtrlNode.java b/chapter20/src/main/java/com/seaofnodes/simple/node/XCtrlNode.java
index da021246..477b9af8 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/XCtrlNode.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/XCtrlNode.java
@@ -1,14 +1,15 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.type.Type;
-import java.util.BitSet;
public class XCtrlNode extends CFGNode {
public XCtrlNode() { super(new Node[]{CodeGen.CODE._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 boolean isConst() { return true; }
@Override public Type compute() { return Type.XCONTROL; }
@Override public Node idealize() { return null; }
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java
index 4359c045..0f883847 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java
@@ -34,7 +34,7 @@ public class CallARM extends CallNode implements MachNode {
}
@Override public void asm(CodeGen code, SB sb) {
- sb.p(_name);
+ sb.p(_name).p(" ");
for( int i=0; i<nargs(); i++ )
sb.p(code.reg(arg(i))).p(" ");
sb.unchar(2);
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java
index e874ce15..c22e71f6 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple.node.cpus.arm;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.*;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.codegen.RegMask;
@@ -7,7 +9,6 @@ import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.type.*;
import java.io.ByteArrayOutputStream;
import java.lang.StringBuilder;
-import java.util.BitSet;
public class MemOpARM extends MemOpNode implements MachNode {
@@ -32,7 +33,7 @@ public class MemOpARM extends MemOpNode implements MachNode {
Node idx() { return in(3); }
Node val() { return in(4); } // Only for stores, includin
- @Override public StringBuilder _printMach(StringBuilder sb, BitSet visited) { return sb.append(".").append(_name); }
+ @Override protected ExprPrinter<Node> _printMach(ExprPrinter<Node> p) { return p.p(".").p(_name); }
@Override public boolean isMem() { return _type instanceof TypeMem; }
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java
index 6a1cf7dc..30dfd7fe 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/BranchRISC.java
@@ -1,11 +1,12 @@
package com.seaofnodes.simple.node.cpus.riscv;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.*;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.codegen.RegMask;
import com.seaofnodes.simple.node.*;
import java.io.ByteArrayOutputStream;
-import java.util.BitSet;
// Conditional branch such as: BEQ
public class BranchRISC extends IfNode implements MachNode {
@@ -23,11 +24,11 @@ public class BranchRISC extends IfNode implements MachNode {
@Override public RegMask regmap(int i) { return riscv.RMASK; }
@Override public RegMask outregmap() { return null; }
- @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("if( "),visited).append(_bop);
- if( in(2)==null ) sb.append("0");
- else in(2)._print0(sb,visited);
- return sb.append(" )");
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ p.p("if( ").n(in(1)).p(_bop);
+ if( in(2)==null ) p.p("0");
+ else p.n(in(2));
+ return p.p(" )");
}
// Encoding is appended into the byte array; size is returned
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java
index 02191d05..330de299 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/ImmRISC.java
@@ -1,11 +1,12 @@
package com.seaofnodes.simple.node.cpus.riscv;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.*;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.codegen.RegMask;
import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.type.TypeInteger;
-import java.util.BitSet;
import java.io.ByteArrayOutputStream;
public abstract class ImmRISC extends MachConcreteNode implements MachNode {
@@ -21,9 +22,8 @@ public abstract class ImmRISC extends MachConcreteNode implements MachNode {
// Register mask allowed as a result. 0 for no register.
@Override public RegMask outregmap() { return riscv.WMASK; }
- @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) {
- in(1)._print0(sb.append("( "), visited);
- return sb.append(String.format(" %s #%d )",glabel(),_imm));
+ @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
+ return p.p("( ").n(in(1)).p(String.format(" %s #%d )",glabel(),_imm));
}
abstract int opcode();
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java
index 01f51b57..19869285 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple.node.cpus.riscv;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.*;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.codegen.RegMask;
@@ -7,7 +9,6 @@ import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.type.*;
import java.io.ByteArrayOutputStream;
import java.lang.StringBuilder;
-import java.util.BitSet;
public class MemOpRISC extends MemOpNode implements MachNode {
@@ -31,7 +32,7 @@ public class MemOpRISC extends MemOpNode implements MachNode {
Node idx() { return in(3); }
Node val() { return in(4); } // Only for stores, including op-to-memory
- @Override public StringBuilder _printMach(StringBuilder sb, BitSet visited) { return sb.append(".").append(_name); }
+ @Override protected ExprPrinter<Node> _printMach(ExprPrinter<Node> p) { return p.p(".").p(_name); }
@Override public boolean isMem() { return _type instanceof TypeMem; }
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java
index 1a771081..e74de677 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java
@@ -1,5 +1,7 @@
package com.seaofnodes.simple.node.cpus.x86_64_v2;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.*;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.codegen.RegMask;
@@ -7,7 +9,6 @@ import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.type.*;
import java.io.ByteArrayOutputStream;
import java.lang.StringBuilder;
-import java.util.BitSet;
// Generic X86 memory operand base.
// inputs:
@@ -53,8 +54,8 @@ public abstract class MemOpX86 extends MemOpNode implements MachNode {
Node idx() { return in(3); }
Node val() { return in(4); } // Only for stores, including op-to-memory
- @Override public StringBuilder _printMach(StringBuilder sb, BitSet visited) {
- return sb.append(".").append(_name);
+ @Override protected ExprPrinter<Node> _printMach(ExprPrinter<Node> p) {
+ return p.p(".").p(_name);
}
@Override public boolean isMem() { return _type instanceof TypeMem; }
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
index 024ef904..08d481fa 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
@@ -1,11 +1,12 @@
package com.seaofnodes.simple.node.cpus.x86_64_v2;
+import com.seaofnodes.print.ExprPrinter;
+
import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.codegen.RegMask;
import com.seaofnodes.simple.node.Node;
import com.seaofnodes.simple.node.StoreNode;
-import java.util.BitSet;
public class StoreX86 extends MemOpX86 {
StoreX86( StoreNode st, Node base, Node idx, int off, int scale, int imm, Node val ) {
@@ -14,12 +15,12 @@ public class StoreX86 extends MemOpX86 {
@Override public String op() { return "st"+_sz; }
- @Override public StringBuilder _printMach(StringBuilder sb, BitSet visited) {
+ @Override protected ExprPrinter<Node> _printMach(ExprPrinter<Node> p) {
Node val = val();
- sb.append(".").append(_name).append("=");
- if( val==null ) sb.append(_imm);
- else val._print0(sb,visited);
- return sb.append(";");
+ p.p(".").p(_name).p("=");
+ if( val==null ) p.p(_imm);
+ else p.n(val);
+ return p.p(";");
}
// Register mask allowed as a result. 0 for no register.
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java b/chapter20/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
index 1a233aa2..a4f768c5 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
@@ -1,163 +1,53 @@
package com.seaofnodes.simple.print;
+import com.seaofnodes.print.AssemblyAdapter;
+import com.seaofnodes.print.ASMPrinter.Data;
+import com.seaofnodes.print.ASMPrinter.Pool;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.node.*;
-import com.seaofnodes.simple.type.TypeFunPtr;
-import com.seaofnodes.simple.type.TypeMem;
-import com.seaofnodes.simple.type.TypeRPC;
-
-public abstract class ASMPrinter {
-
+import com.seaofnodes.simple.type.*;
+import java.util.ArrayList;
+
+/** Machine-specific facts; traversal, columns and byte display live in print/. */
+public final class ASMPrinter extends AssemblyAdapter<Node> {
+ private final CodeGen _code;
+ private ASMPrinter(CodeGen code) {
+ super(new IRPrinter());
+ _code=code;
+ }
public static SB print(SB sb, CodeGen code) {
- if( code._cfg==null )
- return sb.p("Need _cfg set, run after GCM");
-
- // instruction address
- int iadr = 0;
- for( int i=0; i<code._cfg._len; i++ )
- if( code._cfg.at(i) instanceof FunNode fun )
- iadr = print(iadr,sb,code,fun,i);
- return sb;
+ return sb.p(new com.seaofnodes.print.ASMPrinter<>(new ASMPrinter(code)).print());
}
-
- private static int print(int iadr, SB sb, CodeGen code, FunNode fun, int cfgidx) {
- // Function header
- sb.nl().p("---");
- if( fun._name != null ) sb.p(fun._name).p(" ");
- fun.sig().print(sb);
- sb.p("---------------------------").nl();
-
-
- while( !(code._cfg.at(cfgidx) instanceof ReturnNode) )
- iadr = doBlock(iadr,sb,code,fun,cfgidx++);
-
- // Function separator
- sb.p("---");
- fun.sig().print(sb);
- sb.p("---------------------------").nl();
- return iadr;
+ @Override public ArrayList<Node> blocks() {
+ var blocks=new ArrayList<Node>();
+ var cfg=_code._cfg;
+ if( cfg!=null ) for( Node n : cfg ) blocks.add(n);
+ return blocks;
}
-
- static private final int encWidth = 8;
- static private final int opWidth = 5;
- static private final int argWidth = 30;
- static int doBlock(int iadr, SB sb, CodeGen code, FunNode fun, int cfgidx) {
- CFGNode bb = code._cfg.at(cfgidx);
- if( bb != fun && !(bb instanceof IfNode) && !(bb instanceof CallEndNode) && !(bb instanceof CallNode) && !(bb instanceof CProjNode && bb.in(0) instanceof CallEndNode ))
- sb.p(bb instanceof LoopNode ? "LOOP" : "L").p(bb._nid).p(":").nl();
- if( bb instanceof CallNode ) return iadr;
- final boolean postAlloc = code._phase.ordinal() > CodeGen.Phase.RegAlloc.ordinal();
-
- // Count Phis
- int nPhi=0;
- for( ; nPhi<bb.nOuts(); nPhi++ )
- if( !(bb.out(nPhi) instanceof PhiNode) )
- break;
-
- if( nPhi>0 ) {
- // Post-alloc phi prints all on one line
- if( postAlloc ) {
- sb.fix(4," ").p(" ").fix(encWidth,"").p(" ");
- for( int i=0; i<nPhi; i++ ) {
- PhiNode phi = (PhiNode)bb.out(i);
- if( !(phi._type instanceof TypeMem || phi._type instanceof TypeRPC) ) // Nothing for the hidden ones
- sb.p(phi._label).p(':').p(code.reg(phi)).p(',');
- }
- sb.unchar().nl();
-
- } else {
- for( int j=0; j<nPhi; j++ ) {
- PhiNode phi = (PhiNode)bb.out(j);
- if( phi._type instanceof TypeMem || phi._type instanceof TypeRPC ) continue; // Nothing for the hidden ones
- sb.fix(4," ").p(" ").fix(encWidth,"").p(" ").fix(opWidth,phi._label).p(" ");
- sb.p(code.reg(phi));
- if( !(phi instanceof ParmNode) ) {
- sb.p(" = phi( ");
- for( int i=1; i<phi.nIns(); i++ )
- sb.p("N").p(phi.in(i)._nid).p(",");
- sb.unchar().p(" )");
- }
- sb.nl();
- }
- }
+ @Override public String op(Node n) { return n instanceof MachNode m ? m.op() : n.label(); }
+ @Override public String register(Node n) { return _code.reg(n); }
+ @Override public String comment(Node n) { return n.comment(); }
+ @Override public String phiName(Node n) { return ((PhiNode)n)._label; }
+ @Override public String operands(Node n) {
+ SB sb=new SB();
+ if( n instanceof MachNode m ) m.asm(_code,sb);
+ else if( !(n._type instanceof TypeMem) ) {
+ sb.p(n._nid).p(": ");
+ for( Node def : n._inputs ) sb.p(def==null ? "___" : Integer.toString(def._nid)).p(' ');
}
-
- // All the non-phis
- for( int i=nPhi; i<bb.nOuts(); i++ )
- iadr = doInst(iadr, sb,code,fun,bb,bb.out(i),postAlloc );
-
- return iadr;
+ return sb.toString();
}
-
- static int doInst(int iadr, SB sb, CodeGen code, FunNode fun, CFGNode bb, Node n, boolean postAlloc ) {
- if( n instanceof CProjNode ) return iadr;
- if( n instanceof CalleeSaveNode && postAlloc ) return iadr;
-
- // All blocks ending in a Region will need to either fall into or jump
- // to this block. Until the post-reg-alloc block layout cleanup, we
- // need to assume a jump. There's no real hardware op here, yet.
- if( n instanceof RegionNode && !(n instanceof FunNode) ) {
- sb.hex4(iadr++).p(" ").fix(encWidth,"??").p(" ").fix(opWidth,"JMP").p(" ").fix(argWidth,"L"+n._nid).nl();
- return iadr;
- }
-
- // ProjNodes following a multi (e.g. Call or New results),
- // get indent slightly and just print their index & node#
- if( n instanceof ProjNode proj ) {
- if( proj._type instanceof TypeMem ) return iadr; // Nothing for the hidden ones
- sb.fix(4," ").p(" ").fix(encWidth,"").p(" ").fix(opWidth,proj._label==null ? "---" : proj._label).p(" ").p(code.reg(n)).nl();
- return iadr;
- }
-
- // ADDR ENCODING Op--- dst = src op src // Comment
- // 1234 abcdefgh ld4 RAX = [Rbase + off] // Comment
- sb.hex4(iadr);
- sb.p(" ");
-
- // Encoding
- int size = 1; // TODO: Fake encoding size
- iadr += size;
- sb.fix(encWidth,"??");
- sb.p(" ");
-
- // Op; generally "ld4" or "call"
- sb.fix(opWidth, n instanceof MachNode mach ? mach.op() : n.label());
- sb.p(" ");
-
- // General asm args
- if( n instanceof MachNode mach ) {
- int old = sb.len();
- mach.asm(code,sb);
- sb.fix(argWidth-(sb.len()-old),""); // Pad out
-
- } else if( !(n._type instanceof TypeMem) ) {
- // Room for some inputs
- sb.fix(5, n._nid+":" );
- int off = 0;
- for( int i=0; i<n.nIns(); i++ ) {
- sb.fix(5, n.in(i) == null ? "___" : String.valueOf(n.in(i)._nid));
- off += 5;
- if( off >= argWidth ) break;
- }
- if( off < argWidth ) sb.fix(argWidth-off,"");
- }
- sb.p(" ");
-
- // Comment
- String comment = n.comment();
- if( comment!=null ) sb.p("// ").p(comment);
-
- sb.nl();
-
- // MultiNodes are immediately followed by projection(s)
- if( !(n instanceof CFGNode) && n instanceof MultiNode ) {
- for( Node proj : n._outputs ) {
- assert proj instanceof ProjNode;
- doInst(iadr,sb,code,fun,bb,proj,postAlloc);
- }
- }
-
- return iadr;
+ @Override public boolean labelBlock(Node n) {
+ return !(n instanceof FunNode) && !(n instanceof IfNode) && !(n instanceof CallNode) &&
+ !(n instanceof CallEndNode) && !(n instanceof CProjNode && ir.input0(n) instanceof CallEndNode);
+ }
+ @Override public boolean hidden(Node n) {
+ if( n instanceof PhiNode || n instanceof ProjNode )
+ if( n._type instanceof TypeMem || n._type instanceof TypeRPC ) return true;
+ if( postAlloc() && n instanceof CalleeSaveNode ) return true;
+ if( n instanceof MemMergeNode ) return true;
+ return n.getClass()==ConstantNode.class;
}
+ @Override public boolean postAlloc() { return _code._phase.ordinal()>CodeGen.Phase.RegAlloc.ordinal(); }
}
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/print/IRPrinter.java b/chapter20/src/main/java/com/seaofnodes/simple/print/IRPrinter.java
index 0e79d54d..e4d719f4 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/print/IRPrinter.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/print/IRPrinter.java
@@ -1,349 +1,61 @@
package com.seaofnodes.simple.print;
-import com.seaofnodes.simple.Ary;
-import com.seaofnodes.simple.SB;
-import com.seaofnodes.simple.Utils;
-import com.seaofnodes.simple.codegen.CodeGen;
+import com.seaofnodes.print.IRAdapter;
import com.seaofnodes.simple.node.*;
-import com.seaofnodes.simple.type.TypeFunPtr;
import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.HashMap;
-
-public abstract 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 SB printLine( Node n, SB sb ) {
- sb.p("%4d %-7.7s ".formatted(n._nid,n.label()));
- if( n.isDead() )
- return sb.p("DEAD\n");
- for( Node def : n._inputs )
- sb.p(def==null ? "____" : "%4d".formatted(def._nid))
- // Lazy Phi indicator
- .p(n instanceof MemMergeNode && def instanceof MemMergeNode ? "^" : " ");
- for( int i = n._inputs.size(); i<4; i++ )
- sb.p(" ");
- sb.p(" [[ ");
- for( Node use : n._outputs )
- sb.p(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.p(" ");
- sb.p(" ]] ");
- if( n._type!= null ) sb.p(n._type.str());
- return sb.p("\n");
- }
-
-
- public static String prettyPrint(Node node, int depth) {
- return CodeGen.CODE._phase.ordinal() > CodeGen.Phase.Schedule.ordinal()
- ? _prettyPrintScheduled( node, depth )
- : _prettyPrint( node, depth );
- }
-
- // Another bulk pretty-printer. Makes more effort at basic-block grouping.
- private static String _prettyPrint( Node node, int depth ) {
- // 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), null, rpos, visit, bfs._bs);
- // Reverse the post-order walk
- SB sb = new SB();
- boolean gap=false;
- for( int i=rpos.size()-1; i>=0; i-- ) {
- Node n = rpos.get(i);
- if( n instanceof CFGNode || n instanceof MultiNode ) {
- if( !gap ) sb.p("\n"); // Blank before multihead
- if( n instanceof FunNode fun )
- fun.sig().print(sb.p("--- ").p(fun._name==null ? "" : fun._name).p(" "),false).p("----------------------\n");
- printLine( n, sb ); // Print head
- while( --i >= 0 ) {
- Node t = rpos.get(i);
- if( !(t.in(0) instanceof MultiNode) ) { i++; break; }
- printLine( t, sb );
- }
- if( n instanceof ReturnNode ret ) {
- FunNode fun = ret.fun();
- sb.p("--- ");
- if( fun != null )
- fun.sig().print(sb.p(fun._name==null ? "" : fun._name).p(" "),false);
- sb.p("----------------------\n");
- }
- if( !(n instanceof CallNode) ) {
- sb.p("\n"); // Blank after multitail
- gap = true;
- }
- } else {
- printLine( n, sb );
- gap = false;
- }
- }
- return sb.toString();
- }
-
- private static void postOrd(Node n, Node prior, ArrayList<Node> rpos, BitSet visit, BitSet bfs) {
- if( !bfs.get(n._nid) )
- return; // Not in the BFS visit
- if( n instanceof FunNode && !(prior instanceof StartNode) )
- return; // Only visit Fun from Start
- if( visit.get(n._nid) ) return; // Already post-order walked
- visit.set(n._nid);
- // First walk the CFG, then everything
- if( n instanceof CFGNode ) {
- for( Node use : n._outputs )
- // Follow CFG, not across call/function borders, and not around backedges
- if( use instanceof CFGNode && !(n instanceof CallNode && use instanceof FunNode) &&
- use.nOuts() >= 1 && !(use._outputs.get(0) instanceof LoopNode) )
- postOrd(use, n, rpos,visit,bfs);
- for( Node use : n._outputs )
- // Follow CFG, not across call/function borders
- if( use instanceof CFGNode && !(n instanceof CallNode && use instanceof FunNode) )
- postOrd(use,n,rpos,visit,bfs);
- }
- // Follow all outputs
- for( Node use : n._outputs )
- if( use != null &&
- !(n instanceof CallNode && use instanceof FunNode) &&
- (n instanceof FunNode || !(use instanceof ParmNode)) )
- postOrd(use, n, 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 instanceof MultiNode ) 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) {
- _bs.clear(_bfs.get(idx)._nid);
- Utils.del(_bfs, idx);
- }
- boolean any_visited( Node n ) {
- for( Node def : n._inputs )
- if( def!=null && _bs.get(def._nid) )
- return true;
- return false;
- }
- }
-
- public static String _prettyPrint( CodeGen code ) {
- SB sb = new SB();
- // Print the Start "block"
- printLine(code._start,sb);
- for( Node n : code._start._outputs )
- printLine(n,sb);
- sb.nl();
-
- // Skip start, stop
- for( int i=1; i<code._cfg._len-1; i++ ) {
- CFGNode blk = code._cfg.at(i);
- if( blk.blockHead() && (!(blk instanceof CProjNode) || (blk.cfg0() instanceof IfNode )) ) {
- if( blk instanceof FunNode fun )
- sb.p("--- ").p(fun.label()).p(" ---------------------------").nl();
- // Print block header
- sb.p("%-13.13s".formatted(label(blk)+":"));
- sb.p( " ".repeat(4) ).p(" [[ ");
- if( blk instanceof RegionNode )
- for( int j=1; j<blk.nIns(); j++ )
- label(sb,blk.cfg(j));
- else
- label(sb,blk.cfg(0));
- sb.p(" ]] \n");
- }
- printLine(blk,sb);
- if( blk instanceof ReturnNode ret )
- sb.p("--- ").p(ret.fun().label()).p(" ---------------------------").nl();
-
- // Block contents
- for( Node n : blk._outputs ) {
- if( n instanceof CFGNode cfg ) continue;
- printLine(n,sb);
- if( !(n instanceof CFGNode) && n instanceof MultiNode )
- for( Node use : n._outputs )
- printLine(use,sb);
- }
- }
-
- printLine(code._stop,sb);
- return sb.toString();
- }
-
- // 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 || cfg instanceof FunNode ) return cfg instanceof FunNode ? 1 : 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
- private static String _prettyPrintScheduled( Node node, int depth ) {
- // Backwards DFS walk to depth.
- HashMap<Integer,Integer> ds = new HashMap<>();
- Ary<Node> ns = new Ary<>(Node.class);
- _walk(ds,ns,node,depth);
- // Remove data projections, these are force-printed behind their multinode head
- for( int i=0; i<ns.size(); i++ ) {
- if( ns.get(i) instanceof ProjNode proj && !(proj.in(0) instanceof CFGNode) ) {
- ns.del(i--);
- ds.remove(proj._nid);
- }
- }
- // Print by block with least diagnostic depth
- HashMap<Integer,Integer> depths = new HashMap<>();
- SB sb = new SB();
- Ary<Node> bns = new Ary<>(Node.class);
- while( !ds.isEmpty() ) {
- CFGNode blk = null;
- for( Node n : ns ) {
- CFGNode cfg = n instanceof CFGNode cfg0 && cfg0.blockHead() ? cfg0 : n.cfg0();
- if( blk==null || _idepth(cfg,depths) < _idepth(blk,depths) )
- blk = cfg;
- }
- Integer d = ds.remove(blk._nid);
- ns.del(ns.find(blk));
-
- // Print block header
- sb.p("%-13.13s".formatted(label(blk)+":"));
- sb.p( " ".repeat(4) ).p(" [[ ");
- if( blk instanceof StartNode ) ;
- else if( blk instanceof RegionNode || blk instanceof StopNode )
- for( int i=(blk instanceof StopNode ? 3 : 1); i<blk.nIns(); i++ )
- label(sb,blk.cfg(i));
- else
- label(sb,blk.cfg(0));
- sb.p(" ]] \n");
- printLine(blk,sb);
-
- // 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._nid);
- if( i!=null && !(use instanceof CFGNode cfg && cfg.blockHead()) ) {
- if( bns.find(use)==-1 )
- 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,bns,i--,ds,ns);
-
- // Print block contents in depth order, bumping depth until whole block printed
- for( ; !bns.isEmpty(); xd++ )
- for( int i=0; i<bns.size(); i++ ) {
- Node n = bns.get(i);
- if( ds.get(n._nid)==xd ) {
- printLine( n, sb, bns, i--, ds,ns );
- if( n instanceof MultiNode && !(n instanceof CFGNode) ) {
- for( Node use : n._outputs ) {
- printLine(use,sb,bns,bns.indexOf(use),ds,ns);
- }
- }
- }
- }
- sb.p("\n");
- }
- return sb.toString();
- }
-
- private static void _walk( HashMap<Integer,Integer> ds, Ary<Node> ns, Node node, int d ) {
- Integer nd = ds.get(node._nid);
- if( nd!=null && d <= nd ) return; // Been there, done that
- Integer old = ds.put(node._nid,d) ;
- if( old == null )
- ns.add(node);
- if( d == 0 ) return; // Depth cutoff
- for( Node def : node._inputs )
- if( def != null &&
- !(node instanceof LoopNode loop && loop.back()==def) &&
- // Don't walk into or out of functions
- !(node instanceof CallEndNode && def instanceof ReturnNode) &&
- !(node instanceof FunNode && def instanceof CallNode) &&
- !(node instanceof ParmNode && !(def instanceof FunNode))
- )
- _walk(ds,ns,def,d-1);
- }
+import com.seaofnodes.simple.SB;
+import com.seaofnodes.simple.codegen.CodeGen;
- static String label( CFGNode blk ) {
- if( blk instanceof StartNode ) return "START";
- return (blk instanceof LoopNode ? "LOOP" : "L")+blk._nid;
- }
- static void label( SB sb, CFGNode blk ) {
- if( !blk.blockHead() ) blk = blk.cfg(0);
- sb.p( "%-9.9s ".formatted( label( blk ) ) );
+/** 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 boolean global(Node n) { return n.isConst(); }
+ @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 FunNode ) return Kind.FUN;
+ if( n instanceof LoopNode ) return Kind.LOOP;
+ if( n instanceof RegionNode ) return Kind.REGION;
+ if( n instanceof ParmNode ) return Kind.PARM;
+ if( n instanceof PhiNode ) return Kind.PHI;
+ if( n instanceof CallEndNode ) return Kind.CALL_END;
+ if( n instanceof CallNode ) return Kind.CALL;
+ 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;
+ }
+ @Override public String functionName(Node n) { return ((FunNode)n)._name==null ? "" : ((FunNode)n)._name; }
+ @Override public String signature(Node n) {
+ FunNode fun=(FunNode)n;
+ return (fun._name==null ? "" : fun._name)+" "+fun.sig().str();
+ }
+
+ public static String prettyPrint(Node n, int depth) { return PRINT.prettyPrint(n,depth); }
+ public static SB printLine(Node n, SB sb) { return sb.p(PRINT.line(n)); }
+
+ public static String prettyPrint(CodeGen code) {
+ var units=new ArrayList<com.seaofnodes.print.IRPrinter.Unit<Node>>();
+ var funs=new ArrayList<Node>();
+ for( Node n : code._start._outputs ) if( n instanceof FunNode ) funs.add(n);
+ units.add(new com.seaofnodes.print.IRPrinter.Unit<>(null,null,null,funs));
+ return PRINT.program(code._start,code._stop,units);
+ }
+ public static String _prettyPrint(CodeGen code) {
+ if( code._cfg==null ) return prettyPrint(code);
+ var blocks=new ArrayList<Node>();
+ for( Node n : code._cfg ) blocks.add(n);
+ return PRINT.scheduled(blocks);
}
- static void printLine( Node n, SB sb, Ary<Node> bns, int i, HashMap<Integer,Integer> ds, Ary<Node> ns ) {
- printLine( n, sb );
- if( i != -1 ) bns.del(i);
- ds.remove(n._nid);
- int idx = ns.find(n);
- if( idx!=-1 ) ns.del(idx);
- }
-
}
diff --git a/chapter20/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java b/chapter20/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
index 7a2025da..0357ff61 100644
--- a/chapter20/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
+++ b/chapter20/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
@@ -1,45 +1,25 @@
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 20'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>();
- for( int i = 0; i < n.nIns(); i++ ) {
- String name = n instanceof ScopeNode scope && i < scope._vars.size()
+ @Override protected String edgeName(Node n, int i) {
+ return n instanceof ScopeNode scope && i < scope._vars.size()
? scope._vars.get(i)._name : null;
- int jump = n instanceof CallEndNode && i>0 && n.in(i) instanceof ReturnNode ret
- ? ref(ret.fun()) : 0;
- edges.add(new Edge(i, ref(n.in(i)), role(n, i), name, jump));
- }
- return edges;
}
-
- @Override protected GraphSnapshot.Node desc(Node n) {
- Projection proj = n instanceof ProjNode p ? new Projection(ref(n.in(0)), p._idx)
- : n instanceof CProjNode p ? new Projection(ref(n.in(0)), p._idx) : null;
- String label = n.label();
- return new GraphSnapshot.Node(n._nid, label == null ? n.getClass().getSimpleName() : label,
- n._type == null ? null : n._type.toString(), kind(n), edges(n), proj, folding(n));
+ @Override protected int edgeJump(Node n, int i) {
+ return n instanceof CallEndNode && i>0 && n.in(i) instanceof ReturnNode ret
+ ? ref(ret.fun()) : 0;
}
+ @Override protected int projectionIndex(Node n) { return n instanceof ProjNode p ? p._idx : n instanceof CProjNode p ? p._idx : -1; }
- private boolean folding(Node n) {
+ @Override protected boolean folding(Node n) {
if( n instanceof FunNode fun ) return fun.folding();
if( n instanceof ReturnNode ret ) return ret.fun().folding();
if( n instanceof CallEndNode cend ) return cend.folding();
@@ -49,7 +29,7 @@ public class SimpleGraphAdapter extends GraphAdapter<Node> {
return false;
}
- 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 FunNode ) return Kind.FUN;
@@ -60,7 +40,7 @@ public class SimpleGraphAdapter extends GraphAdapter<Node> {
return n instanceof CFGNode ? 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 CtrlNode || 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 )