From 7f3b8856119da7e4fd6fc0a9c0c740d7b0b3170f Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Wed, 9 Sep 2026 11:41:35 -0700 Subject: Fix some lattice bugs --- .../com/seaofnodes/simple/type/TypeFunPtr.java | 20 ++++++++++++++++++-- .../java/com/seaofnodes/simple/type/TypeMem.java | 17 +++++++---------- .../main/java/com/seaofnodes/simple/type/XInt.java | 22 ++++++++++++---------- 3 files changed, 37 insertions(+), 22 deletions(-) (limited to 'chapter25/src/main/java/com/seaofnodes') diff --git a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java index ff52c93b..975bce3d 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java @@ -59,9 +59,19 @@ public class TypeFunPtr extends TypeNil { if( f2==fun ) return fun; return VISIT.isEmpty() ? f2.free(fun) : f2.delayFree(fun); } - public static TypeFunPtr make( boolean nil, Type[] sig, Type ret ) { return make((byte)(nil ? 3 : 2),true,sig,ret, XInt.FULL); } + // Trim trailing args which match the default. + private static TypeFunPtr makeAdjusted( byte nil, boolean open, Type[] sig, Type ret, int[] fidxs ) { + Type def = open ? TypeScalar.BOT : TypeScalar.TOP; + int nargs = sig.length; + while( nargs > 0 && sig[nargs-1] == def ) + nargs--; + if( nargs != sig.length ) + sig = nargs == 0 ? ARG_EMPTY : Arrays.copyOf(sig,nargs); + return make(nil,open,sig,ret,fidxs); + } + public static TypeFunPtr make( boolean nil, Type[] sig, Type ret ) { return makeAdjusted((byte)(nil ? 3 : 2),true,sig,ret, XInt.FULL); } public static TypeFunPtr make1( byte nil, boolean open, Type[] sig, Type ret, int fidx ) { - return make(nil,open,sig,ret,XInt.make(fidx)); + return makeAdjusted(nil,open,sig,ret,XInt.make(fidx)); } @@ -94,6 +104,12 @@ public class TypeFunPtr extends TypeNil { ts.add(CALLOC); ts.add(make((byte)2,false,TINT,TypeInteger.I32, XInt.SET1)); ts.add(make((byte)2,true ,TINT,TypeInteger.BOT, XInt.SET3)); + ts.add(make1((byte)2,true, + new Type[]{TypeInteger.BOT}, + TypeInteger.BOT, 65)); + ts.add(make1((byte)2,true, + new Type[]{TypeInteger.BOT, TypeScalar.BOT}, + TypeInteger.BOT, 65)); } private static final Type[] ARG_EMPTY = new Type[0]; diff --git a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeMem.java b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeMem.java index 420dea55..106dee49 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeMem.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeMem.java @@ -111,6 +111,8 @@ public class TypeMem extends Type { ts.add(BOT); ts.add(SELF_MEM); ts.add(START); + ts.add(make(2,TypeInteger.ZERO,true,false,true,XInt.EMPTY,XInt.make(2))); + ts.add(make(2,TypeInteger.BOT,false,false,false,XInt.EMPTY,XInt.FULL)); } @Override @@ -128,16 +130,11 @@ public class TypeMem extends Type { Type mt = _t.meet(that._t); int[] fidxs = XInt.meet( _escFs, that._escFs ); int[] aliases= XInt.meet( _escAs, that._escAs ); - // Singleton & class facts are kept only when both sides agree. - - // Final is kept if either side is final, merging a final & non-final - // memory can be argued either way here: - - // - Keep it: merging a final & non-final memory means a later Store - // update will be flagged as an error. - // - Lose it: merging a final & non-final memory means a later Load - // cannot be promised the memory is unchanging. - return make(alias, mt, _one & that._one, _clz & that._clz, _final | that._final, fidxs, aliases); + // Singleton and class facts are kept only when both sides agree. + // Finality is a low-side fact, and flips on the dual side. + boolean highAlias1 = (this._alias==1 && this._t.isHigh()) || (that._alias==1 && that._t.isHigh()); + boolean xfinal = highAlias1 ? (_final & that._final) : (_final | that._final); + return make(alias, mt, _one & that._one, _clz & that._clz, xfinal, fidxs, aliases); } @Override diff --git a/chapter25/src/main/java/com/seaofnodes/simple/type/XInt.java b/chapter25/src/main/java/com/seaofnodes/simple/type/XInt.java index e3054a73..752c1419 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/type/XInt.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/type/XInt.java @@ -166,22 +166,24 @@ public abstract class XInt { if( xs==ys ) return xs; boolean isX=true, isY=true; int min = Math.min(xs.length,ys.length); - for( int i=1; i