From 2136abe8071833fd072c4be13c885525b46f5320 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Tue, 3 Dec 2024 13:51:58 -0800 Subject: Greatly improved JSViewer Handle memory edges. Color-coded edges & nodes to match lattice. Add SB vs StringBuilder. JSViewer needs SB to keep my sanity. Catch successful peeps and `show` them. Drop unused LLVM format, so I don't need to support Yet Another Printer. SimpleWebSocket handles longer packets; more robust close. Bug fix st/new fold. Bug fix Phi pull-down op losing precision. --- .../com/seaofnodes/simple/GraphVisualizer.java | 5 +- .../main/java/com/seaofnodes/simple/IRPrinter.java | 52 ++------ .../main/java/com/seaofnodes/simple/IterPeeps.java | 1 + .../main/java/com/seaofnodes/simple/JSViewer.java | 146 +++++++++++++-------- .../main/java/com/seaofnodes/simple/Parser.java | 3 +- .../com/seaofnodes/simple/SimpleWebSocket.java | 15 ++- .../com/seaofnodes/simple/node/ConstantNode.java | 3 +- .../main/java/com/seaofnodes/simple/node/Node.java | 16 +-- .../java/com/seaofnodes/simple/node/PhiNode.java | 6 +- .../com/seaofnodes/simple/node/ScopeMinNode.java | 3 +- .../java/com/seaofnodes/simple/node/ScopeNode.java | 6 +- .../java/com/seaofnodes/simple/node/StoreNode.java | 2 +- .../com/seaofnodes/simple/node/StructNode.java | 3 +- .../java/com/seaofnodes/simple/type/Field.java | 5 +- .../main/java/com/seaofnodes/simple/type/Type.java | 12 +- .../java/com/seaofnodes/simple/type/TypeFloat.java | 25 +--- .../com/seaofnodes/simple/type/TypeFunPtr.java | 21 +-- .../com/seaofnodes/simple/type/TypeInteger.java | 13 +- .../java/com/seaofnodes/simple/type/TypeMem.java | 18 +-- .../com/seaofnodes/simple/type/TypeMemPtr.java | 9 +- .../com/seaofnodes/simple/type/TypeStruct.java | 11 +- .../java/com/seaofnodes/simple/type/TypeTuple.java | 31 ++--- 22 files changed, 198 insertions(+), 208 deletions(-) (limited to 'chapter18/src/main/java') diff --git a/chapter18/src/main/java/com/seaofnodes/simple/GraphVisualizer.java b/chapter18/src/main/java/com/seaofnodes/simple/GraphVisualizer.java index eb8d8e23..ea6862d2 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/GraphVisualizer.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/GraphVisualizer.java @@ -267,8 +267,9 @@ public class GraphVisualizer { final HashMap all = new HashMap<>(); for( Node n : ns ) walk(all, n); - for( Node n : ss ) - walk(all, n); + if( ss != null ) + for( Node n : ss ) + walk(all, n); return all.values(); } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/IRPrinter.java b/chapter18/src/main/java/com/seaofnodes/simple/IRPrinter.java index 7ef55a3f..bd071870 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/IRPrinter.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/IRPrinter.java @@ -11,7 +11,7 @@ public class IRPrinter { // Print a node on 1 line, columnar aligned, as: // NNID NNAME DDEF DDEF [[ UUSE UUSE ]] TYPE // 1234 sssss 1234 1234 1234 1234 1234 1234 tttttt - public static void _printLine( Node n, StringBuilder sb ) { + public static void printLine( Node n, StringBuilder sb ) { sb.append("%4d %-7.7s ".formatted(n._nid,n.label())); if( n._inputs==null ) { sb.append("DEAD\n"); @@ -40,40 +40,14 @@ public class IRPrinter { return sb; } - // Print a node on 1 line, format is inspired by LLVM - // %id: TYPE = NODE(inputs ....) - // Nodes as referred to as %id - public static void _printLineLlvmFormat( Node n, StringBuilder sb ) { - nodeId(sb, n).append(": "); - if( n._inputs==null ) { - sb.append("DEAD\n"); - return; - } - if( n._type!= null ) n._type.typeName(sb); - sb.append(" = ").append( n.label() ).append( "(" ); - for( int i = 0; i < n._inputs.size(); i++ ) { - Node def = n.in(i); - if (i > 0) - sb.append(", "); - if (def == null) sb.append("_"); - else nodeId(sb, def); - } - sb.append(")").append("\n"); - } - - public static void printLine( Node n, StringBuilder sb, boolean llvmFormat ) { - if (llvmFormat) _printLineLlvmFormat( n, sb ); - else _printLine ( n, sb ); - } - public static String prettyPrint(Node node, int depth) { return Parser.SCHEDULED - ? prettyPrintScheduled( node, depth, false ) - : prettyPrint( node, depth, false ); + ? _prettyPrintScheduled( node, depth ) + : _prettyPrint( node, depth ); } // Another bulk pretty-printer. Makes more effort at basic-block grouping. - public static String prettyPrint( Node node, int depth, boolean llvmFormat ) { + 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 @@ -88,16 +62,16 @@ public class IRPrinter { Node n = rpos.get(i); if( n instanceof CFGNode || n.isMultiHead() ) { if( !gap ) sb.append("\n"); // Blank before multihead - printLine( n, sb, llvmFormat ); // Print head + printLine( n, sb ); // Print head while( --i >= 0 ) { Node t = rpos.get(i); if( !t.isMultiTail() ) { i++; break; } - printLine( t, sb, llvmFormat ); + printLine( t, sb ); } sb.append("\n"); // Blank after multitail gap = true; } else { - printLine( n, sb, llvmFormat ); + printLine( n, sb ); gap = false; } } @@ -188,7 +162,7 @@ public class IRPrinter { } // Bulk pretty printer, knowing scheduling information is available - public static String prettyPrintScheduled( Node node, int depth, boolean llvmFormat ) { + private static String _prettyPrintScheduled( Node node, int depth ) { // Backwards DFS walk to depth. HashMap ds = new HashMap<>(); ArrayList ns = new ArrayList<>(); @@ -237,17 +211,17 @@ public class IRPrinter { // Print Phis up front, if any for( int i=0; i bns, int i, HashMap ds, ArrayList ns ) { - printLine( n, sb, llvmFormat ); + static void printLine( Node n, StringBuilder sb, ArrayList bns, int i, HashMap ds, ArrayList ns ) { + printLine( n, sb ); if( i != -1 ) Utils.del(bns,i); ds.remove(n._nid); ns.remove(n); diff --git a/chapter18/src/main/java/com/seaofnodes/simple/IterPeeps.java b/chapter18/src/main/java/com/seaofnodes/simple/IterPeeps.java index 36f053f9..c0b34263 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/IterPeeps.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/IterPeeps.java @@ -86,6 +86,7 @@ public abstract class IterPeeps { } // If there are distant neighbors, move to worklist n.moveDepsToWorklist(); + JSViewer.show(); // Show again assert progressOnList(stop); // Very expensive assert } if( n.isUnused() && !(n instanceof StopNode) ) diff --git a/chapter18/src/main/java/com/seaofnodes/simple/JSViewer.java b/chapter18/src/main/java/com/seaofnodes/simple/JSViewer.java index 48776fd5..79a84edf 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/JSViewer.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/JSViewer.java @@ -1,10 +1,10 @@ package com.seaofnodes.simple; import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.*; import java.nio.file.Paths; import java.io.IOException; -import java.util.Stack; import java.util.Collection; public class JSViewer implements AutoCloseable { @@ -49,11 +49,12 @@ public class JSViewer implements AutoCloseable { P.parse(); // No longer user parse internal state when building views P = null; - + STOP.iterate(); // Catch and ignore Parser errors } catch(RuntimeException re) { + System.err.println(re); } finally { SHOW = false; SERVER.put("#"); // Final frame @@ -124,7 +125,6 @@ public class JSViewer implements AutoCloseable { } - private static void nodes(SB sb, Collection all) { // Just the Nodes first, in a cluster no edges sb.i().p("subgraph cluster_Nodes {\n").ii(); // Magic "cluster_" in the subgraph name @@ -132,13 +132,12 @@ public class JSViewer implements AutoCloseable { if( n instanceof ProjNode || n instanceof CProjNode || n instanceof ScopeMinNode || n==Parser.XCTRL ) continue; // Do not emit, rolled into MultiNode or Scope cluster already sb.i().p(n.uniqueName()).p(" [ "); - String lab = n.glabel(); if( n instanceof MultiNode ) { // Make a box with the MultiNode on top, and all the projections on the bottom sb. p("shape=plaintext label=<\n").ii(); sb.i().p("\n"); // Row over single cell for node label - cell(sb.i().p(""), lab, null, true, false).p("\n"); + cell(sb.i().p(""), n.glabel(), n, null).p("\n"); // Row over single cell, for nested table sb.i().p("\n"); @@ -162,9 +160,9 @@ public class JSViewer implements AutoCloseable { } else { // control nodes have box shape // other nodes are ellipses, i.e. default shape - if( n instanceof CFGNode ) sb.p("shape=box style=filled fillcolor=yellow "); - else if (n instanceof PhiNode) sb.p("style=filled fillcolor=lightyellow "); - sb.p("label=\"").p(lab).p("\" ];\n"); + //else if (n instanceof PhiNode) sb.p("style=filled fillcolor=lightyellow "); + node(sb,n.glabel(),n); + sb.p("];\n"); } } // Force Region & Phis to line up @@ -191,30 +189,28 @@ public class JSViewer implements AutoCloseable { sb.i().p("subgraph cluster_").p(scopeName).p(" {\n").ii(); // Magic "cluster_" in the subgraph name sb.i().p(scopeName).p(" [label=<\n").ii(); sb.i().p("
\n").ii(); sb.i().p("").p("\n"); @@ -147,12 +146,11 @@ public class JSViewer implements AutoCloseable { boolean empty_row=true; for( Node use : n._outputs ) if( use instanceof MultiUse muse ) { - cell(sb,use.glabel(),"p"+muse.idx(),use instanceof CFGNode,use.isMem()); + cell(sb,use.glabel(),use,"p"+muse.idx()); empty_row=false; } // At least one cell on row - if( empty_row ) - cell(sb,"",null,false,false); + if( empty_row ) sb.p(""); sb. p("").p("\n"); sb.i().p("
").p("\n").di(); sb.i().p("
\n"); - // Add the scope level - sb.i().p(""); int lexStart=scope._lexSize.at(level); // Special for memory ScopeMinNode ScopeMinNode n = scope.nIns()>1 ? scope.mem() : null; if( level==0 && n!=null && n.nIns()>2 ) { - sb. p(""); + sb.i().p(""); + for( int m=2; m\n"); // End scope level } - sb. p("\n"); // End scope level - sb.i().p("\n"); - for( int j=lexStart; j\n"); + for( int j=lexStart; j\n"); } - last = lexStart; - sb.i().p("\n"); sb.i().p("
").p(level).p("\n"); - sb.i().p("\t"); - for( int m=2; m").p(m).p(""); - throw Utils.TODO(); // Need port names for edges - } - sb.p("
\n"); - sb.i().p("
>];\n").di(); + // Scope label + sb.i().p(scopeName).p("A [label=\"").p(level).p("\" shape=doublecircle style=filled fillcolor=aqua fontsize=10 margin=0 width=0.2 ];\n"); } // Scope clusters nest, so the graphics shows the nested scopes, so // they are not closed as they are printed; so they just keep nesting. @@ -224,19 +220,42 @@ public class JSViewer implements AutoCloseable { } // Append a cell, with color - private static SB cell(SB sb, String text, String port, boolean isCFG, boolean isMem) { - sb.p(""); - if( isMem ) sb.p(""); + private static SB cell(SB sb, String text, Node n, String port) { + boolean dark=false; + sb.p(""),text,n,dark).p(""); + } + private static SB node(SB sb, String text, Node n) { + boolean dark=false; + if( n instanceof CFGNode ) sb.p("style=filled fillcolor=yellow shape=box "); + if( n instanceof PhiNode ) sb.p("style=filled fillcolor=lightyellow "); + if( n instanceof StructNode) sb.p("style=filled fillcolor=lightgreen "); + if( n.isMem() ) { sb.p("style=filled fillcolor=blue "); dark=true; } + if( n._type instanceof TypeMemPtr ) { sb.p("style=filled fillcolor=green "); dark=true; } + if( n._type instanceof TypeInteger ) sb.p("style=filled fillcolor=lightblue "); + return colorcell(sb.p("label=<"),text,n,dark).p(">"); + } + // Called with an open div + private static SB colorcell(SB sb, String text, Node n, boolean dark) { + if( dark ) sb.p(""); sb.p(text); - if( isMem ) sb.p(""); - sb.p(""); + if( n._type!=null ) { + sb.p("
"); + n._type.print(sb); + sb.p(""); + } + if( dark ) sb.p("
"); return sb; } + private static String makeScopeName(ScopeNode sn, int level) { return sn.uniqueName() + "_" + level; } private static String makePortName(String scopeName, String varName) { return scopeName + "_" + varName; } @@ -279,14 +298,8 @@ public class JSViewer implements AutoCloseable { } else sb.p(def.uniqueName()); // Number edges, so we can see how they track sb.p("[taillabel=").p(i); - // The edge from New to ctrl is just for anchoring the New - if ( n instanceof NewNode ) - sb.p(" color=green"); - // control edges are colored red - else if( def instanceof CFGNode ) - sb.p(" color=red"); - else if( def.isMem() ) - sb.p(" color=blue"); + // Color the edge + nodeEdgeColor(sb,def._type); // Backedges do not add a ranking constraint if( i==2 && (n instanceof PhiNode || n instanceof LoopNode) ) sb.p(" constraint=false"); @@ -296,11 +309,23 @@ public class JSViewer implements AutoCloseable { // Bonus edge if hooked by parser if( (n.iskeep() || n.isUnused()) && scopeName != null ) { - sb.i().p(scopeName).p(" -> ").p(n.uniqueName()).p(" [ stype=dotted color=grey]\n"); + sb.i().p(scopeName).p(" -> ").p(n.uniqueName()).p(" [ style=dashed color=grey]\n"); } } } + private static void nodeEdgeColor(SB sb, Type t) { + String color = switch( t ) { + case TypeMem mem -> "blue"; + case TypeMemPtr ptr -> "green"; + case TypeInteger ti -> "lightblue"; + // control edges are colored red + default -> (t==Type.CONTROL || t==Type.XCONTROL) ? "red" : null; + }; + if( color!=null ) + sb.p(" color=").p(color); + } + // Walk the scope edges private static void scopeEdges( SB sb, ScopeNode scope ) { sb.i().p("edge [style=dashed color=cornflowerblue];\n"); @@ -318,14 +343,29 @@ public class JSViewer implements AutoCloseable { .p(scopeName).p(":") .p('"').p(makePortName(scopeName, v._name)).p('"') // wrap port name with quotes because $ctrl is not valid unquoted .p(" -> "); - if( def instanceof CProjNode proj ) { - sb.p(def.in(0).uniqueName()).p(":p").p(proj._idx); - } else if( def instanceof ProjNode proj ) { - sb.p(def.in(0).uniqueName()).p(":p").p(proj._idx); - } else sb.p(def.uniqueName()); - sb.p(";\n"); + defPort(sb,def).p(";\n"); } - } + // Memory + if( scope.nIns()>1 ) { + ScopeMinNode n = scope.mem(); + for( int i=2; i "); + defPort(sb,def).p(";\n"); + } + } + + } + private static SB defPort(SB sb, Node def) { + return def instanceof MultiUse muse + ? sb.p(def.in(0).uniqueName()).p(":p").p(muse.idx()) + : sb.p(def.uniqueName()); + } } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java index 123841e8..47bfe08e 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java @@ -156,7 +156,7 @@ public class Parser { mem.addDef(null); _scope.define(ScopeNode.CTRL, Type.CONTROL , false, new CProjNode(START, 0, ScopeNode.CTRL).peephole()); mem.addDef( new ProjNode(START, 1, ScopeNode.MEM0).peephole()); - _scope.define(ScopeNode.MEM0, TypeMem.TOP , false, mem .peephole()); + _scope.define(ScopeNode.MEM0, TypeMem.BOT , false, mem .peephole()); _scope.define(ScopeNode.ARG0, TypeInteger.BOT, false, new ProjNode(START, 2, ScopeNode.ARG0).peephole()); JSViewer.show(); @@ -172,6 +172,7 @@ public class Parser { INITS.clear(); if (!_lexer.isEOF()) throw error("Syntax error, unexpected " + _lexer.getAnyNextToken()); STOP.peephole(); + JSViewer.show(); if( show ) showGraph(); return STOP; } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/SimpleWebSocket.java b/chapter18/src/main/java/com/seaofnodes/simple/SimpleWebSocket.java index 114bfddd..f9a85d19 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/SimpleWebSocket.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/SimpleWebSocket.java @@ -65,9 +65,12 @@ class SimpleWebSocket extends ServerSocket { switch( op&15) { case 1: { // Message length - int len = (rawget()&0xFF)-128; - if( len > 125 ) - throw Utils.TODO(); // Multi-byte length + int len = rawget()-128; + if( len > 125 ) { + if( len > 126 ) + throw Utils.TODO(); // Multi-byte length + len = (rawget()<<8) | rawget(); + } // Encoding key _key[0] = (byte)rawget(); _key[1] = (byte)rawget(); @@ -108,8 +111,10 @@ class SimpleWebSocket extends ServerSocket { } @Override public void close() throws IOException { - _out.write(0b10001000); - _out.flush(); + if( _out != null ) { + _out.write(0b10001000); + _out.flush(); + } super.close(); } } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/ConstantNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/ConstantNode.java index 845b9d08..406b20ca 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/ConstantNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ConstantNode.java @@ -1,6 +1,7 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.Parser; +import com.seaofnodes.simple.SB; import com.seaofnodes.simple.type.Type; import java.util.BitSet; @@ -32,7 +33,7 @@ public class ConstantNode extends Node { @Override StringBuilder _print1(StringBuilder sb, BitSet visited) { - return _con.print(sb); + return sb.append(_con.print(new SB())); } @Override public boolean isMultiTail() { return true; } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter18/src/main/java/com/seaofnodes/simple/node/Node.java index 040e3a0e..e23a128a 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/Node.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/Node.java @@ -90,8 +90,9 @@ public abstract class Node implements OutNode { @Override public final String toString() { return print(); } - // This is a *deep* print. We print with a tik-tok style; the common - // _print0 calls the per-Node _print1, which calls back to _print0; + // 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(); } @@ -302,7 +303,11 @@ public abstract class Node implements OutNode { _type = compute(); return this; // Peephole optimizations turned off } + if( _type==null ) // Brand-new node, never peeped before + JSViewer.show(); Node n = peepholeOpt(); + if( n!=null ) // Made progress? + JSViewer.show(); // Show again return n==null ? this : deadCodeElim(n._nid >= _nid ? n.peephole() : n); // Cannot return null for no-progress } @@ -325,13 +330,6 @@ public abstract class Node implements OutNode { * */ public final Node peepholeOpt( ) { - JSViewer.show(); - Node n = _peepholeOpt(); - if( n==null ) return null; - JSViewer.show(); - return n; - } - private final Node _peepholeOpt( ) { ITER_CNT++; // Compute initial or improved Type Type old = setType(compute()); diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/PhiNode.java index cb266ca3..407cf378 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/PhiNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/PhiNode.java @@ -84,7 +84,11 @@ public class PhiNode extends Node { } Node phi_lhs = new PhiNode(_label, _declaredType,lhss).peephole(); Node phi_rhs = new PhiNode(_label, _declaredType,rhss).peephole(); - return op.copy(phi_lhs,phi_rhs); + Node down = op.copy(phi_lhs,phi_rhs); + // Test not running backwards, which can happen for e.g. And's + if( down.compute().isa(compute()) ) + return down; + down.kill(); } // If merging Phi(N, cast(N)) - we are losing the cast JOIN effects, so just remove. diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeMinNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeMinNode.java index 9134f9c3..f69461cc 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeMinNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeMinNode.java @@ -42,7 +42,8 @@ public class ScopeMinNode extends Node { public ScopeMinNode() { _type = TypeMem.BOT; } - @Override public String label() { return "MEM"; } + @Override public String label() { return "$mem"; } + @Override public boolean isMem() { return true; } @Override StringBuilder _print1(StringBuilder sb, BitSet visited) { diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java index 86aa7665..0d8ad2fc 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java @@ -1,10 +1,10 @@ package com.seaofnodes.simple.node; -import com.seaofnodes.simple.IterPeeps; import com.seaofnodes.simple.Ary; +import com.seaofnodes.simple.IterPeeps; +import com.seaofnodes.simple.SB; import com.seaofnodes.simple.type.*; import java.util.*; - import static com.seaofnodes.simple.Utils.TODO; /** @@ -50,7 +50,7 @@ public class ScopeNode extends ScopeMinNode { for( int i=0; i ")); - sb.append(String.format(" #%X",_fidxs)); - sb.append("}"); - if( (_fidxs&1)==1 ) sb.append("?"); + _sig._types[i].print(sb).p(" "); + _sig._types[0].print(sb.p("-> ")); + sb.p(String.format(" #%X",_fidxs)); + sb.p("}"); + if( (_fidxs&1)==1 ) sb.p("?"); return sb; } @Override public String str() { if( this== NULLPTR) return "null"; if( this== VOIDPTR) return "*void"; - return print(new StringBuilder()).toString(); + return print(new SB()).toString(); } } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeInteger.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeInteger.java index b2979d7b..2be4f4d8 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeInteger.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeInteger.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.type; +import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import java.util.ArrayList; @@ -46,7 +47,7 @@ public class TypeInteger extends Type { // FIXME this display format is problematic // In visualizer '#' gets prepended if its a constant @Override - public StringBuilder print(StringBuilder sb) { return sb.append(str()); } + public SB print(SB sb) { return sb.p(str()); } @Override public String str() { if( this==TOP ) return "~int"; @@ -62,16 +63,6 @@ public class TypeInteger extends Type { return "["+_min+"-"+_max+"]"; } - /** - * Display Type name in a format that's good for IR printer - */ - @Override - public StringBuilder typeName(StringBuilder sb) { - if( this==TOP ) return sb.append("IntTop"); - if( this==BOT ) return sb.append("IntBot"); - return sb.append("Int"); - } - @Override public boolean isHigh () { return _min > _max; } @Override public boolean isHighOrConst() { return _min >= _max; } @Override public boolean isConstant () { return _min == _max; } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMem.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMem.java index 33c6a8ce..8c0bdca8 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMem.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMem.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.type; +import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import java.lang.Long; import java.util.BitSet; @@ -13,7 +14,7 @@ public class TypeMem extends Type { // Which slice of memory? // 0 means TOP, no slice. - // -1 means BOT, all memory. + // 0 means BOT, all memory. // N means slice#N. public final int _alias; public final Type _t; // Memory contents, some scalar type @@ -21,8 +22,8 @@ public class TypeMem extends Type { private TypeMem(int alias, Type t) { super(TMEM); _alias = alias; _t = t; } public static TypeMem make(int alias, Type t) { return new TypeMem(alias,t).intern(); } - public static final TypeMem TOP = make(-1, Type.TOP ); - public static final TypeMem BOT = make(-1, Type.BOTTOM); + public static final TypeMem TOP = make(0, Type.TOP ); + public static final TypeMem BOT = make(0, Type.BOTTOM); public static void gather(ArrayList ts) { ts.add(make(1,TypeInteger.ZERO)); ts.add(BOT); } @@ -33,7 +34,7 @@ public class TypeMem extends Type { if( that==TOP ) return this; if( this==BOT ) return BOT; if( that==BOT ) return BOT; - int alias = _alias==that._alias ? _alias : -1; + int alias = _alias==that._alias ? _alias : 0; Type mt = _t.meet(that._t); return make(alias,mt); } @@ -56,11 +57,10 @@ public class TypeMem extends Type { } @Override - public StringBuilder print(StringBuilder sb) { - sb.append("MEM#"); - if( _alias== 0 ) return sb.append("TOP"); - if( _alias==-1 ) return sb.append("BOT"); - return _t.print(sb.append(_alias).append(":")); + public SB print(SB sb) { + sb.p("#"); + if( _alias==0 ) return sb.p(_t._type==TTOP ? "TOP" : "BOT"); + return _t.print(sb.p(_alias).p(":")); } @Override public String str() { return toString(); } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java index 786a7be5..a009cc4a 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.type; +import com.seaofnodes.simple.SB; import java.util.ArrayList; /** @@ -83,10 +84,10 @@ public class TypeMemPtr extends Type { // [void,name,MANY]*[,?] @Override - public StringBuilder print(StringBuilder sb) { - if( this== NULLPTR) return sb.append("null"); - if( this== VOIDPTR) return sb.append("*void"); - return _obj.print(sb.append("*")).append(_nil ? "?" : ""); + public SB print(SB sb) { + if( this== NULLPTR) return sb.p("null"); + if( this== VOIDPTR) return sb.p("*void"); + return _obj.print(sb.p("*")).p(_nil ? "?" : ""); } @Override public String str() { diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeStruct.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeStruct.java index b3dbcad0..239c6df1 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeStruct.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeStruct.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.type; +import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import java.util.ArrayList; @@ -195,13 +196,13 @@ public class TypeStruct extends Type { } @Override - public StringBuilder print(StringBuilder sb) { - sb.append(_name); + public SB print(SB sb) { + sb.p(_name); if( _fields == null ) return sb; // Forward reference struct, just print the name - sb.append(" {"); + sb.p(" {"); for( Field f : _fields ) - f._type.print(sb).append(f._final ? " " : " !").append(f._fname).append("; "); - return sb.append("}"); + f._type.print(sb).p(f._final ? " " : " !").p(f._fname).p("; "); + return sb.p("}"); } @Override public String str() { return _name; } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeTuple.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeTuple.java index 8a98952c..7e1296e2 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeTuple.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeTuple.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.type; +import com.seaofnodes.simple.SB; import java.util.ArrayList; public class TypeTuple extends Type { @@ -44,34 +45,18 @@ public class TypeTuple extends Type { return make(ts); } - @Override public StringBuilder print(StringBuilder sb) { - sb.append("[ "); + @Override public SB print(SB sb) { + sb.p("[ "); for( Type t : _types ) - t.print(sb).append(", "); - sb.setLength(sb.length()-2); - sb.append("]"); - return sb; + t.print(sb).p(", "); + return sb.unchar(2).p("]"); } @Override public String str() { - StringBuilder sb = new StringBuilder(); - sb.append("[ "); + SB sb = new SB().p("[ "); for( Type t : _types ) - sb.append(t.str()).append(", "); - sb.setLength(sb.length()-2); - return sb.append("]").toString(); - } - - /** - * Display Type name in a format that's good for IR printer - */ - @Override - public StringBuilder typeName(StringBuilder sb) { - sb.append("["); - for( Type t : _types ) - t.typeName(sb).append(","); - sb.setLength(sb.length()-1); - return sb.append("]"); + sb.p(t.str()).p(", "); + return sb.unchar(2).p("]").toString(); } public static final TypeTuple IF_BOTH = make(new Type[]{Type. CONTROL,Type. CONTROL}); -- cgit v1.2.3