diff options
Diffstat (limited to 'chapter24/src/main/java/com/seaofnodes')
12 files changed, 59 insertions, 20 deletions
diff --git a/chapter24/src/main/java/com/seaofnodes/simple/Var.java b/chapter24/src/main/java/com/seaofnodes/simple/Var.java index cf549cd6..14295395 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/Var.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/Var.java @@ -28,6 +28,8 @@ public class Var { _fref = fref; _loc = loc; } + // Raw declared type, without resolving a forward reference while printing. + public Type _type() { return _type; } public Type type() { if( !_type.isFRef() ) return _type; // Update self to no longer use the forward ref type diff --git a/chapter24/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/chapter24/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java index 3715d015..c0b8d68e 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java @@ -140,7 +140,10 @@ public class CodeGen { // Reverse from a constant function pointer to the IR function being called. // Error to call with a non-constant TFP public FunNode link( TypeFunPtr tfp ) { return link(tfp.fidx()); } - // Return the FunNode from a fidx + // Read-only diagnostic lookup; preserve stale entries. + public FunNode _link(TypeFunPtr tfp) { return _link(tfp.fidx()); } + public FunNode _link(int fidx) { return _linker.atX(fidx); } + // Return the FunNode from a fidx, cleaning up dead entries. public FunNode link( int fidx ) { FunNode fun =_linker.atX(fidx); if( fun!=null && fun.isDead() ) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/chapter24/src/main/java/com/seaofnodes/simple/codegen/Encoding.java index e3684445..4e7166fa 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -52,12 +52,16 @@ public class Encoding { public static class Relo { public final Node _op; public final Type _t; // Constant type + public final int _align; // Log alignment, captured for diagnostic display + public final int _structSize; // Capture layout during encoding, not printing public final byte _off; // Offset from start of opcode public final byte _elf; // ELF relocation type, e.g. 2/PC32 public int _target; // Where constant is finally placed public int _opStart; // Opcode start Relo( Node op, Type t, byte off, byte elf ) { _op=op; _t=t; _off=off; _elf=elf; + _align = t.alignment(); + _structSize = t instanceof TypeStruct ts ? ts.size() : 0; } } public final HashMap<Node,Relo> _bigCons = new HashMap<>(); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java b/chapter24/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java index da521082..10297a9a 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java @@ -124,15 +124,23 @@ public class RegAlloc { } + // Diagnostic lookup: do not compress leaders or rewrite the node mapping. + private LRG _lrg(Node n) { + LRG lrg = _lrgs.get(n); + if( lrg != null ) + while( lrg._leader != null ) lrg = lrg._leader; + return lrg; + } + public short regnum( Node n ) { - LRG lrg = lrg(n); + LRG lrg = _lrg(n); return lrg==null ? -1 : lrg._reg; } // Printable register number for node n String reg( Node n ) { return reg(n,null); } String reg( Node n, FunNode fun ) { - LRG lrg = lrg(n); + LRG lrg = _lrg(n); if( lrg==null ) return null; // No register yet, use LRG if( lrg._reg == -1 ) return "V"+lrg._lrg; diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/CallNode.java b/chapter24/src/main/java/com/seaofnodes/simple/node/CallNode.java index 47dfdf19..965efd99 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/CallNode.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/CallNode.java @@ -32,8 +32,8 @@ public class CallNode extends CFGNode { return sb.append(")"); } public String name() { - if( fptr()._type instanceof TypeFunPtr tfp && tfp.isConstant() ) { - FunNode fun = CodeGen.CODE.link(tfp); + if( fptr()._type instanceof TypeFunPtr tfp && tfp._isConstant() && tfp.notNull() ) { + FunNode fun = CodeGen.CODE._link(tfp); if( fun !=null ) return fun._name; if( fptr() instanceof ExternNode ex ) return ex._extern; } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/ConstantNode.java b/chapter24/src/main/java/com/seaofnodes/simple/node/ConstantNode.java index 22bf03c4..d5d70a0f 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/ConstantNode.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/ConstantNode.java @@ -36,8 +36,8 @@ public class ConstantNode extends Node { @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) { - if( _con instanceof TypeFunPtr tfp && tfp.isConstant() ) { - FunNode fun = CodeGen.CODE.link(tfp); + 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("}"); } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java b/chapter24/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java index 9ab57714..2a399b97 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java @@ -38,7 +38,7 @@ public class MemMergeNode extends Node { Node n = in(j); while( n instanceof ScopeNode loop ) { sb.append("Lazy_"); - n = loop.mem(j); + n = loop.mem().alias(j); } if( n==null ) sb.append("___ "); else n._print0(sb, visited).append(" "); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/ScopeNode.java b/chapter24/src/main/java/com/seaofnodes/simple/node/ScopeNode.java index d8c07a92..04666956 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/ScopeNode.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/ScopeNode.java @@ -65,7 +65,7 @@ public class ScopeNode extends MemMergeNode { for( int i=0; i<nIns(); i++ ) { if( j < depth() && i == _kinds.at(j)._lexSize ) { sb.append("| "); j++; } Var v = _vars.at(i); - sb.append(v.type()); + sb.append(v._type()); sb.append(" "); if( v._final ) sb.append("!"); sb.append(v._name); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java b/chapter24/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java index a9f86ce8..9ee26039 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java @@ -8,7 +8,9 @@ import com.seaofnodes.simple.type.*; import com.seaofnodes.simple.util.Ary; import com.seaofnodes.simple.util.SB; import com.seaofnodes.simple.util.Utils; -import java.util.HashSet; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Set; public abstract class ASMPrinter { @@ -28,14 +30,13 @@ public abstract class ASMPrinter { if( enc!=null && !enc._bigCons.isEmpty() && iadr < enc._bits.size() ) { // radix sort the big constants by alignment Ary<Relo>[] raligns = new Ary[5]; - for( Node op : enc._bigCons.keySet() ) { - Relo relo = enc._bigCons.get(op); - int align = relo._t.alignment(); + for( Relo relo : enc._bigCons.values() ) { + int align = relo._align; Ary<Relo> relos = raligns[align]==null ? (raligns[align]=new Ary<>( Relo.class)) : raligns[align]; relos.add(relo); } - HashSet<Type> targets = new HashSet<>(); + Set<Type> targets = Collections.newSetFromMap(new IdentityHashMap<>()); sb.p("--- Constant Pool ------").nl(); // By alignment @@ -55,7 +56,7 @@ public abstract class ASMPrinter { } case TypeStruct ts -> { - int sz = ts.size(); + int sz = relo._structSize; int log = 1<<align; sz = (sz + (log -1)) & -log; // Round up final padding for( int i=0; i<sz; i++ ) diff --git a/chapter24/src/main/java/com/seaofnodes/simple/print/IRPrinter.java b/chapter24/src/main/java/com/seaofnodes/simple/print/IRPrinter.java index d1265bef..336cf500 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/print/IRPrinter.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/print/IRPrinter.java @@ -221,6 +221,26 @@ public abstract class IRPrinter { 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. @@ -234,14 +254,15 @@ public abstract class IRPrinter { ds.remove(proj._nid); } } - // Print by block with least idepth + // 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 || cfg.idepth() < blk.idepth() ) + if( blk==null || _idepth(cfg,depths) < _idepth(blk,depths) ) blk = cfg; } Integer d = ds.remove(blk._nid); diff --git a/chapter24/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java b/chapter24/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java index ddef9651..2e957005 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java @@ -135,7 +135,7 @@ public class TypeFunPtr extends TypeNil { @Override public boolean isHigh() { return _nil <= 1 || (_nil==2 && _fidxs==0); } - @Override boolean _isConstant() { return (_nil==2 && Long.bitCount(_fidxs)==1) || (_nil==3 && _fidxs==0); } + @Override public boolean _isConstant() { return (_nil==2 && Long.bitCount(_fidxs)==1) || (_nil==3 && _fidxs==0); } @Override boolean _isFinal() { return true; } @Override boolean _isGLB(boolean mem) { return true; } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/type/TypeInteger.java b/chapter24/src/main/java/com/seaofnodes/simple/type/TypeInteger.java index 97c17a34..a0cb12cb 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/type/TypeInteger.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/type/TypeInteger.java @@ -116,7 +116,7 @@ public class TypeInteger extends Type { if( this==I16 || this==U16 ) return 1; // 1<<1 == 2 bytes if( this==I32 || this==U32 ) return 2; // 1<<2 == 4 bytes if( this==BOT ) return 3; // 1<<3 == 8 bytes - if( isConstant() ) { // just const here + if( _isConstant() ) { // just const here if (-0xFF <= _min && _min <= 0xFF) return 0; else if (-0xFFFF <= _min && _min <= 0xFFFF) return 1; else if (-0xFFFFFFFFL <= _min && _min <= 0xFFFFFFFFL) return 2; @@ -126,7 +126,7 @@ public class TypeInteger extends Type { throw Utils.TODO(); } - public long value() { assert isConstant(); return _min; } + public long value() { assert _isConstant(); return _min; } // AND-mask of forced zeros. e.g. unsigned types will return their mask; // u8 will return 0xFF. But also a range of 16-18 (0x10-0x12) will return |
