summaryrefslogtreecommitdiff
path: root/chapter25/src/main/java/com
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-09-09 11:41:35 -0700
committerCliff Click <cliffc@acm.org>2026-09-09 11:41:35 -0700
commit7f3b8856119da7e4fd6fc0a9c0c740d7b0b3170f (patch)
tree0bb6161192b9e6e717c4a19e614ac2a998240c1a /chapter25/src/main/java/com
parent66e426e7c4576a8433449bc649597cf63f22436e (diff)
downloadSimple-7f3b8856119da7e4fd6fc0a9c0c740d7b0b3170f.tar.gz
Simple-7f3b8856119da7e4fd6fc0a9c0c740d7b0b3170f.zip
Fix some lattice bugs
Diffstat (limited to 'chapter25/src/main/java/com')
-rw-r--r--chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java20
-rw-r--r--chapter25/src/main/java/com/seaofnodes/simple/type/TypeMem.java17
-rw-r--r--chapter25/src/main/java/com/seaofnodes/simple/type/XInt.java22
3 files changed, 37 insertions, 22 deletions
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<min; i++ ) {
- if( (xs[i] | ys[i])!=xs[i] ) isX=false;
- if( (xs[i] | ys[i])!=ys[i] ) isY=false;
+ int max = Math.max(xs.length,ys.length);
+ for( int i=1; i<max; i++ ) {
+ int x = i < xs.length ? xs[i] : isHigh(xs) ? -1 : 0;
+ int y = i < ys.length ? ys[i] : isHigh(ys) ? -1 : 0;
+ if( (x | y)!=x ) isX=false;
+ if( (x | y)!=y ) isY=false;
}
- if( !isHigh(xs) && min < ys.length )
- isX = false; // YS has *some* more bits set, and XS does not
- if( !isHigh(ys) && min < xs.length )
- isY = false; // XS has *some* more bits set, and YS does not
if( isX ) return xs;
if( isY ) return ys;
// Get a free one
- int[] ms = free(Math.max(xs.length,ys.length));
+ int[] ms = free(max);
for( int i=1; i<min; i++ )
ms[i] = xs[i] | ys[i];
- if( min < xs.length ) System.arraycopy(xs,min,ms,min,xs.length-min);
- if( min < ys.length ) System.arraycopy(ys,min,ms,min,ys.length-min);
+ for( int i=min; i<ms.length; i++ ) {
+ int x = i < xs.length ? xs[i] : isHigh(xs) ? -1 : 0;
+ int y = i < ys.length ? ys[i] : isHigh(ys) ? -1 : 0;
+ ms[i] = x | y;
+ }
return intern(ms);
}