From 2d80a348bad4b1e3165bd955ceaff3e18a96e516 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sun, 25 Oct 2026 14:20:11 -0700 Subject: Retire Evalutator Minor rounding bug in eval2 --- .../java/com/seaofnodes/simple/Chapter19Test.java | 36 ++++++++++++++++++++++ .../src/test/java/com/seaofnodes/simple/Eval2.java | 8 +++++ 2 files changed, 44 insertions(+) (limited to 'chapter28a/src/test/java/com') diff --git a/chapter28a/src/test/java/com/seaofnodes/simple/Chapter19Test.java b/chapter28a/src/test/java/com/seaofnodes/simple/Chapter19Test.java index 6f290279..d5fe207a 100644 --- a/chapter28a/src/test/java/com/seaofnodes/simple/Chapter19Test.java +++ b/chapter28a/src/test/java/com/seaofnodes/simple/Chapter19Test.java @@ -11,6 +11,42 @@ import org.junit.Test; import static org.junit.Assert.*; public class Chapter19Test { + @Test public void testNarrowStores() { + // Return the allocation so Load forwarding cannot hide a bad Store. + for( String type : new String[]{"u8","i8","u16","i16","u32","i32","int","f32","flt"} ) { + boolean flt = type.equals("f32") || type.equals("flt"); + String init = flt ? "flt v=arg; " : ""; + if( type.equals("f32") ) init+="f32 w=v; "; + String value = type.equals("f32") ? "w" : flt ? "v" : "arg"; + for( boolean array : new boolean[]{false,true} ) { + String src = array + ? "var a=new "+type+"[1]; a[0]="+value+"; return a;" + : "struct S { "+type+" x; }; var s=new S; s.x="+value+"; return s;"; + CodeGen code = new CodeGen(init+src).driver(CodeGen.Phase.TypeCheck); + long[] args = flt ? new long[]{0,1,-1,16777217,-16777217} + : new long[]{0,1,-1,0x180,0x18000,0x180000000L,Long.MIN_VALUE,Long.MAX_VALUE}; + for( long arg : args ) { + Object expected = switch( type ) { + case "u8" -> arg & 0xffL; + case "i8" -> (long)(byte)arg; + case "u16" -> arg & 0xffffL; + case "i16" -> (long)(short)arg; + case "u32" -> arg & 0xffffffffL; + case "i32" -> (long)(int)arg; + case "f32" -> (double)(float)arg; + case "flt" -> (double)arg; + default -> arg; + }; + String msg = type+" array="+array+" arg="+arg; + String printed = array + ? (type.equals("u8") ? ""+(char)(long)(Long)expected : (type.equals("int") ? "i64" : type)+"[ "+expected+"]") + : "Test.S{x="+expected+"}"; + assertEquals(msg,printed,Eval2.eval(code,arg)); + } + } + } + } + @Test public void testPrintingFunctionLookup() { var code = new CodeGen("return 0;").parse(); var tfp = TypeFunPtr.make1((byte)2,false,new Type[]{TypeInteger.constant(987654)},TypeInteger.constant(123456),30); diff --git a/chapter28a/src/test/java/com/seaofnodes/simple/Eval2.java b/chapter28a/src/test/java/com/seaofnodes/simple/Eval2.java index 366bd7f4..901a8990 100644 --- a/chapter28a/src/test/java/com/seaofnodes/simple/Eval2.java +++ b/chapter28a/src/test/java/com/seaofnodes/simple/Eval2.java @@ -460,6 +460,14 @@ public abstract class Eval2 { ? offToIdx(x(st.off()),tmp._obj) : tmp._obj.find(st._name); Object val = val(st.val()); + // Idealization can remove conversions already performed by the store. + Type type = st.declaredType(); + if( type instanceof TypeInteger ti ) { + int shift = 64-(8 << st.log_size()); + long x = (Long)val << shift; + val = ti._min < 0 ? x >> shift : x >>> shift; + } else if( type instanceof TypeFloat && st.log_size()==2 ) + val = (double)(float)(double)(Double)val; fs[idx] = val; return "$mem"; } -- cgit v1.2.3