diff options
| author | Cliff Click <cliffc@acm.org> | 2026-08-10 14:09:04 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2026-08-10 14:09:04 -0700 |
| commit | 8f5b226cf472bc249b935320b8f3b7ac71d09579 (patch) | |
| tree | 0499933cc8762528c4d16c0dd13b8812f9470607 /chapter25/src | |
| parent | 51f1f8f4b871e3b52eb0c5d18b03f362a2b37791 (diff) | |
| download | Simple-8f5b226cf472bc249b935320b8f3b7ac71d09579.tar.gz Simple-8f5b226cf472bc249b935320b8f3b7ac71d09579.zip | |
A few missed ser/de-ser tags
A little less aggressive FunPtr trimming before Opto
Diffstat (limited to 'chapter25/src')
8 files changed, 110 insertions, 23 deletions
diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/FunNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/FunNode.java index a9d03543..5018f5d6 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/FunNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/FunNode.java @@ -154,14 +154,14 @@ public class FunNode extends RegionNode { } // Attempt to get rid of the unknown caller. - // - Must be past Parser, which invents new calls "from whole cloth". + // - Must be past pessimistic Iter, which discovers and links calls + // through class-field loads and other initially imprecise values. // - FIDX is not in the escape set // - Not called anywhere else; post Opto called-not-escaped functions need to still be hooked to start if( in(1) instanceof StartCUNode start ) { boolean preOpto = CodeGen.CODE._phase == null || CodeGen.CODE._phase.ordinal() < CodeGen.Phase.Opto.ordinal(); - if( !start.escapedFIDX(_sig.fidx()) && nIns()<=2 && _ret!=null && - !(preOpto && hasFunPtr()) ) { + if( !preOpto && !start.escapedFIDX(_sig.fidx()) && nIns()<=2 && _ret!=null ) { _compunit._stop.delDef(_compunit._stop._inputs.find(ret())); return removeDeadPath(1); } else { @@ -186,17 +186,6 @@ public class FunNode extends RegionNode { return null; } - // Before SCCP has discovered all Call edges, a live function pointer is - // enough reason to retain the unknown-caller Start edge. - private boolean hasFunPtr() { - for( Node use : ret().outs() ) - if( use instanceof FunPtrNode && !use.isDead() ) { - addDep(use); - return true; - } - return false; - } - // Bypass Region idom, always assume depth == 1, one more than Start, // unless folding @Override public int idepth() { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java index cbed5996..8d8d3950 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java @@ -12,13 +12,20 @@ public class TFPX86 extends FunPtrNode implements MachNode, RIPRelSize { private byte _opLen; final String _ext; // External name // Pointer to a Simple function - TFPX86( FunPtrNode fptr ) { super(fptr); _ext = null; } + TFPX86( FunPtrNode fptr ) { this((TypeFunPtr)fptr._type,null); } + // Spill clone: copy inputs without registering their reverse edges; + // insertBefore will place and register the clone in its use block. + private TFPX86( TFPX86 fptr ) { super(fptr); _ext = fptr._ext; } // Pointer to an Extern "C" function TFPX86( TypeFunPtr fptr, String ext ) { super(fptr,CodeGen.CODE._start,null); _type = fptr; _ext = ext; } @Override public String op() { return "ldx"; } @Override public String label() { return op(); } + // The ideal FunPtrNode is pinned because its Return input is a lifetime + // hook. After selection this is an ordinary cloneable load-address + // instruction and must be scheduled down near its actual use. + @Override public boolean isPinned() { return false; } @Override public boolean isClone() { return true; } - @Override public TFPX86 copy() { return new TFPX86((TypeFunPtr)_con,_ext); } + @Override public TFPX86 copy() { return new TFPX86(this); } @Override public RegMask regmap(int i) { return null; } @Override public RegMask outregmap() { return x86_64_v2.WMASK; } @Override public void encoding( Encoding enc ) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeInteger.java b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeInteger.java index 4245626a..25c3fa6f 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeInteger.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeInteger.java @@ -193,7 +193,8 @@ public class TypeInteger extends TypeScalar { baos.write(TAGOFFS[_type] + 6); baos.packed8(_min); baos.packed8(_max); - baos.packed1(_widen); + assert -3 <= _widen && _widen <= 3; + baos.packed1(_widen + 3); } } @@ -205,7 +206,7 @@ public class TypeInteger extends TypeScalar { case 3 -> BOOL; case 4 -> ZERO; case 5 -> constant(bais.packed8()); - case 6 -> make(bais.packed8(),bais.packed8(),(byte)bais.packed1()); + case 6 -> make(bais.packed8(),bais.packed8(),(byte)(bais.packed1()-3)); default -> throw Utils.TODO(); }; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeScalar.java b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeScalar.java index 4fec3c33..7b5d6317 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeScalar.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeScalar.java @@ -41,14 +41,16 @@ public class TypeScalar extends Type { @Override boolean _isGLB(boolean mem) { return this == BOT; } @Override Type _glb(boolean mem) { return BOT; } - @Override int TAGOFF() { return 1; } + // Reserve tags for both lattice endpoints. Unlike most concrete scalar + // families, generic scalar TOP can survive into a serialized graph. + @Override int TAGOFF() { return 2; } @Override public void packed(BAOS baos, HashMap<String,Integer> strs) { - assert this == BOT; - baos.write(TAGOFFS[_type]); + assert this == BOT || this == TOP; + baos.write(TAGOFFS[_type] + (this == BOT ? 0 : 1)); } static TypeScalar packed(int tag) { - assert tag == 0; - return BOT; + assert tag == 0 || tag == 1; + return tag == 0 ? BOT : TOP; } @Override public String str() { return isHigh() ? "~scalar" : "scalar"; } diff --git a/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys.smp b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys.smp new file mode 100644 index 00000000..1725c57d --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys.smp @@ -0,0 +1,3 @@ +// Reduced multi-compilation-unit reproducer for order-sensitive inlining. +var aryu8 = aryu8; +var aryi64 = aryi64; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/Ary.smp b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/Ary.smp new file mode 100644 index 00000000..e3dd6140 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/Ary.smp @@ -0,0 +1,6 @@ +// Array utilities, discovered indirectly from aryu8. +val copy = { u8[] dst, int doff, u8[~] src, int soff, int len -> + for( int i=0; i<len; i++ ) + dst[i+doff] = src[i+soff]; + return dst; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/aryi64.smp b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/aryi64.smp new file mode 100644 index 00000000..53c93666 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/aryi64.smp @@ -0,0 +1,29 @@ +struct aryi64 { + u32 !len = 0; + i64[] !buf; + + new aryi64 = { i64[] b -> buf = b; }; + + val _grow = { int len2 -> + if( len+len2 < buf# ) return self; + int newlen = buf# * 2; + while( len+len2 >= newlen ) newlen *= 2; + i64[] !buf2 = new i64[newlen]; + for( int i=0; i<buf#; i++ ) + buf2[i] = buf[i]; + buf = buf2; + self; + }; + + val add = { i64 c -> + _grow(1).buf[len++] = c; + self; + }; + + val str = { -> + var str = new aryu8(new u8[1]).add('['); + for( int i=0; i<len; i++ ) + str.num(buf[i]).add(',').add(' '); + str.undo(2).add(']'); + }; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/aryu8.smp b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/aryu8.smp new file mode 100644 index 00000000..112a0321 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/aryu8.smp @@ -0,0 +1,50 @@ +struct aryu8 { + u32 !len = 0; + u8[] !buf; + + new aryu8 = { u8[] b -> buf = b; }; + + val _grow = { int len2 -> + if( len+len2 < buf# ) return self; + int newlen = buf# * 2; + while( len+len2 >= newlen ) newlen *= 2; + u8[] !buf2 = new u8[newlen]; + Ary.copy(buf2,0,buf,0,buf#); + buf = buf2; + self; + }; + + val clear = { -> len = 0; self; }; + + val add = { u8 c -> + _grow(1).buf[len++] = c; + self; + }; + + val addAry = { u8[~] ary -> + _grow(ary#); + Ary.copy(buf,len,ary,0,ary#); + len += ary#; + self; + }; + + val undo = { int x -> + len = len >= x ? len-x : 0; + self; + }; + + val num = { i64 x -> + if( !x ) { add('0'); return self; } + if( x < 0 ) { add('-'); x = -x; } + i64 ten = 1, log = 0; + while( ten <= x ) { ten *= 10; log++; } + for( int i=0; i<log; i++ ) { + ten /= 10; + i64 q = x/ten; + u8 digit = q+'0'; + add(digit); + x -= q*ten; + } + self; + }; +}; |
