summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/print
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/seaofnodes/simple/print')
-rw-r--r--src/main/java/com/seaofnodes/simple/print/ASMPrinter.java40
-rw-r--r--src/main/java/com/seaofnodes/simple/print/IRPrinter.java17
-rw-r--r--src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java43
-rw-r--r--src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java2
4 files changed, 70 insertions, 32 deletions
diff --git a/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java b/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
index 48296ce7..e8218afd 100644
--- a/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
+++ b/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java
@@ -9,6 +9,8 @@ import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.type.*;
import java.util.ArrayList;
import com.seaofnodes.simple.codegen.Encoding;
+import com.seaofnodes.simple.util.BAOS;
+import java.util.HashMap;
/** Machine-specific facts; traversal, columns and byte display live in print/. */
public final class ASMPrinter extends AssemblyAdapter<Node> {
@@ -24,7 +26,7 @@ public final class ASMPrinter extends AssemblyAdapter<Node> {
}
@Override public ArrayList<Node> blocks() {
var blocks=new ArrayList<Node>();
- var cfg=_code._cfg;
+ var cfg=_enc==null ? _code._cfg : _enc._cfg;
if( cfg!=null ) for( Node n : cfg ) blocks.add(n);
return blocks;
}
@@ -50,26 +52,24 @@ public final class ASMPrinter extends AssemblyAdapter<Node> {
if( n._type instanceof TypeMem || n._type instanceof TypeRPC ) return true;
if( postAlloc() && n instanceof CalleeSaveNode ) return true;
if( n instanceof MemMergeNode ) return true;
+ if( n instanceof EscapeNode ) return true;
return n.getClass()==ConstantNode.class;
}
- @Override public boolean postAlloc() { return _code._phase.ordinal()>CodeGen.Phase.RegAlloc.ordinal(); }
+ @Override public boolean postAlloc() { return _code._phase.ordinal()>CodeGen.Phase.RegAlloc.ordinal() ||
+ (_code._phase==CodeGen.Phase.RegAlloc && _code._regAlloc!=null && _code._regAlloc.done()); }
@Override public boolean encoded() { return _enc!=null && _code._phase.ordinal()>=CodeGen.Phase.Encoding.ordinal(); }
@Override public int defaultSize() { return _code._mach==null ? 2 : _code._mach.defaultOpSize(); }
@Override public boolean littleEndian() { return _code._asmLittle; }
@Override public boolean prologue(Node n) { return ((FunNode)n)._frameAdjust!=0; }
@Override public byte[] bytes() { return encoded() ? _enc._bits.buf() : null; }
- @Override public int offset(Node n) {
- return encoded() && _enc._opStart!=null && n._nid<_enc._opStart.length ? _enc._opStart[n._nid] : -1;
- }
- @Override public int size(Node n) {
- return encoded() && _enc._opLen!=null && n._nid<_enc._opLen.length ? _enc._opLen[n._nid]&255 : 0;
- }
- private static ArrayList<Data> entries(Iterable<Encoding.Relo> relos) {
+ @Override public int offset(Node n) { return encoded() ? _enc.opStart(n) : -1; }
+ @Override public int size(Node n) { return encoded() ? _enc.opLen(n)&255 : 0; }
+ private static ArrayList<Data> entries(Iterable<Encoding.Relo> relos, boolean ro) {
var data=new ArrayList<Data>();
for( Encoding.Relo r : relos ) {
+ if( r.readOnly()!=ro ) continue;
int align=1<<r._align;
int size=r._t instanceof TypeStruct ? (r._structSize+align-1)&-align : align;
- if( r._t instanceof TypeTuple t ) size=align*t._types.length;
data.add(new Data(r._t,r._t.str(),r._align,size));
}
return data;
@@ -78,8 +78,24 @@ public final class ASMPrinter extends AssemblyAdapter<Node> {
var pools=new ArrayList<Pool>();
if( !encoded() ) return pools;
int base=(codeEnd+15)&-16;
- if( !_enc._bigCons.isEmpty() && base<_enc._bits.size() )
- pools.add(new Pool("Constant Pool",_enc._bits.buf(),base,base,entries(_enc._bigCons.values())));
+ if( _enc._cpool.size()>0 )
+ pools.add(new Pool("Constant Pool",_enc._cpool.buf(),0,base,objects(true)));
+ base=(base+_enc._cpool.size()+15)&-16;
+ if( _enc._sdata.size()>0 )
+ pools.add(new Pool("Static Data",_enc._sdata.buf(),0,base,objects(false)));
return pools;
}
+ private ArrayList<Data> objects(boolean ro) {
+ var data=new ArrayList<Data>();
+ for( var obj : _enc._data.entries() )
+ if( !obj.external && obj.readOnly==ro )
+ data.add(new Data(obj,obj.symbol+": "+obj.type.str(),obj.alignment,obj.size));
+ return data;
+ }
+ // Retain this diagnostic entry point for checking that pool printing never lays out types.
+ static int printConstantPool(int address, SB sb, BAOS bits, HashMap<Node,Encoding.Relo> relos,
+ boolean ro, String name) {
+ sb.p(com.seaofnodes.print.ASMPrinter.pool(new Pool(name,bits.buf(),0,address,entries(relos.values(),ro))));
+ return address+bits.size();
+ }
}
diff --git a/src/main/java/com/seaofnodes/simple/print/IRPrinter.java b/src/main/java/com/seaofnodes/simple/print/IRPrinter.java
index c912ab77..531a549a 100644
--- a/src/main/java/com/seaofnodes/simple/print/IRPrinter.java
+++ b/src/main/java/com/seaofnodes/simple/print/IRPrinter.java
@@ -14,6 +14,8 @@ public final class IRPrinter extends IRAdapter<Node> {
@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 StartCUNode ) return Kind.UNIT;
+ if( n instanceof StopCUNode ) return Kind.UNIT;
if( n instanceof StartNode ) return Kind.START;
if( n instanceof StopNode ) return Kind.STOP;
if( n instanceof FunNode ) return Kind.FUN;
@@ -47,15 +49,12 @@ public final class IRPrinter extends IRAdapter<Node> {
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));
+ for( var cu : code._compunits.values() ) {
+ var funs=new ArrayList<Node>();
+ for( FunNode fun : code._linker )
+ if( fun!=null && fun._compunit==cu ) funs.add(fun);
+ units.add(new com.seaofnodes.print.IRPrinter.Unit<>(cu._cname,cu._start,cu._stop,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);
- }
}
diff --git a/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java b/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
index 8dc6ea47..9ca0ec51 100644
--- a/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
+++ b/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
@@ -2,22 +2,30 @@ package com.seaofnodes.simple.print;
import com.seaofnodes.graph.GraphAdapter;
import com.seaofnodes.graph.GraphSnapshot.*;
+import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.node.Node;
import com.seaofnodes.simple.type.TypeMem;
-/** Chapter 24's view of the IR; browser, transport and layout are shared. */
+/** Chapter 25's view of the IR, including partially constructed parse-time graphs. */
public class SimpleGraphAdapter extends GraphAdapter<Node> {
+ @Override protected boolean show(Node n) {
+ if( n != CodeGen.CODE.ZERO && n != CodeGen.CODE.XCTRL ) return true;
+ for( int i=0; i<n.nOuts(); i++ )
+ if( n.out(i) != null ) return true;
+ return false; // The parser's keep is not a graph use.
+ }
+
@Override protected String edgeName(Node n, int i) {
return n instanceof ScopeNode scope && i < scope._vars.size()
- ? scope._vars.get(i)._name : null;
+ ? scope.var(i)._name : null;
}
@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; }
+ @Override protected int projectionIndex(Node n) { return n instanceof Proj p ? p.idx() : -1; }
@Override protected boolean folding(Node n) {
if( n instanceof FunNode fun ) return fun.folding();
@@ -32,26 +40,41 @@ public class SimpleGraphAdapter extends GraphAdapter<Node> {
@Override protected Kind kind(Node n) {
if( n instanceof StopNode ) return Kind.STOP;
if( n instanceof ScopeNode ) return Kind.SCOPE;
+ if( n instanceof StartCUNode ) return Kind.UNIT;
if( n instanceof FunNode ) return Kind.FUN;
- if( n instanceof StartNode ) return Kind.CTRL;
+ // Start inherits Loop for whole-program analysis, but is not a source loop.
+ if( n instanceof StartNode ) return Kind.START;
if( n instanceof LoopNode ) return Kind.LOOP;
if( n instanceof RegionNode ) return Kind.REGION;
if( n instanceof PhiNode ) return Kind.PHI;
- return n instanceof CFGNode ? Kind.CTRL : isMem(n) ? Kind.MEM : Kind.DATA;
+ if( n instanceof CFGNode ) return Kind.CTRL;
+ return isMem(n) ? Kind.MEM : Kind.DATA;
}
@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 )
+ if( n instanceof ScopeNode || n instanceof ConstantNode || n instanceof FunPtrNode ||
+ 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 Proj )
return n instanceof CFGNode ? Role.CTRL : isMem(n) ? Role.MEM : Role.DATA;
+ // StartCU inherits Region, but slot 0 really connects it to Start.
+ if( n instanceof StartCUNode && i == 0 ) return Role.CTRL;
if( n instanceof RegionNode && i == 0 ) return Role.ASSOC;
+ // Preserve known slot roles even when an input is not attached/typed yet.
if( i == 0 || n instanceof RegionNode || n instanceof StopNode ) return Role.CTRL;
- if( n instanceof MemMergeNode || (i == 1 && (n instanceof MemOpNode || n instanceof ReturnNode || n instanceof CallNode || n instanceof NewNode)) ) return Role.MEM;
+ if( n instanceof MemMergeNode ||
+ (i == 1 && (n instanceof MemOpNode || n instanceof ReturnNode || n instanceof CallNode)) ||
+ (n instanceof EscapeNode && i >= 2) ) return Role.MEM;
Node def = n.in(i);
+ if( def instanceof CFGNode ) return Role.CTRL;
if( def != null && isMem(def) ) return Role.MEM;
return Role.DATA;
}
- private boolean isMem(Node n) { return n.isMem() || n._type instanceof TypeMem; }
+ private boolean isMem(Node n) {
+ // These Phi subclasses are memory even before their first type computation.
+ return n instanceof MemPhiNode || n instanceof BulkMemPhiNode || n.isMem() || n._type instanceof TypeMem;
+ }
}
diff --git a/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java b/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java
index 3df1e0ea..bf8403e1 100644
--- a/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java
+++ b/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java
@@ -7,7 +7,7 @@ import com.seaofnodes.simple.node.Node;
import java.util.ArrayList;
import java.io.IOException;
-/** Chapter 24's compilation context; capture and event bookkeeping are shared. */
+/** Chapter 25's compilation context; capture and event bookkeeping are shared. */
public class SimpleGraphObserver extends GraphCapture<Node> {
private CodeGen _code;
public SimpleGraphObserver() { super(new SimpleGraphAdapter()); }