diff options
16 files changed, 61 insertions, 7 deletions
diff --git a/chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 78e7698c..6be071a2 100644 --- a/chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter14/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -16,6 +16,7 @@ public class RoundF32Node extends Node { public Type compute() { if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) return TypeFloat.constant((float)i0.value()); + if( in(1)._type==TypeFloat.BOT ) return TypeFloat.B32; return in(1)._type; } diff --git a/chapter15/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter15/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 78e7698c..6be071a2 100644 --- a/chapter15/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter15/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -16,6 +16,7 @@ public class RoundF32Node extends Node { public Type compute() { if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) return TypeFloat.constant((float)i0.value()); + if( in(1)._type==TypeFloat.BOT ) return TypeFloat.B32; return in(1)._type; } diff --git a/chapter16/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter16/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 78e7698c..6be071a2 100644 --- a/chapter16/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter16/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -16,6 +16,7 @@ public class RoundF32Node extends Node { public Type compute() { if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) return TypeFloat.constant((float)i0.value()); + if( in(1)._type==TypeFloat.BOT ) return TypeFloat.B32; return in(1)._type; } diff --git a/chapter17a/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter17a/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 78e7698c..6be071a2 100644 --- a/chapter17a/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter17a/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -16,6 +16,7 @@ public class RoundF32Node extends Node { public Type compute() { if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) return TypeFloat.constant((float)i0.value()); + if( in(1)._type==TypeFloat.BOT ) return TypeFloat.B32; return in(1)._type; } diff --git a/chapter17b/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter17b/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 78e7698c..6be071a2 100644 --- a/chapter17b/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter17b/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -16,6 +16,7 @@ public class RoundF32Node extends Node { public Type compute() { if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) return TypeFloat.constant((float)i0.value()); + if( in(1)._type==TypeFloat.BOT ) return TypeFloat.B32; return in(1)._type; } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter18/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 78e7698c..10a0e4aa 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -16,6 +16,7 @@ public class RoundF32Node extends Node { public Type compute() { if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) return TypeFloat.constant((float)i0.value()); + if( in(1)._type==TypeFloat.F64 ) return TypeFloat.F32; return in(1)._type; } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeStruct.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeStruct.java index bc640955..fff6a7db 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeStruct.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeStruct.java @@ -49,7 +49,7 @@ public class TypeStruct extends Type { // Array public static TypeStruct makeAry(TypeInteger len, int lenAlias, Type body, int bodyAlias) { - assert body instanceof TypeInteger || (body instanceof TypeNil tn && tn.nullable()); + assert body instanceof TypeInteger || body instanceof TypeFloat || (body instanceof TypeNil tn && tn.nullable()); return make("[" + body.str() + "]", Field.make("#" ,len , lenAlias,true ), Field.make("[]",body,bodyAlias,false)); diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java index c4d5b9ac..0758fbf5 100644 --- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java +++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java @@ -9,6 +9,33 @@ import static org.junit.Assert.fail; import org.junit.Ignore; public class Chapter18Test { + @Test public void testFloatArrays() { + for( String type : new String[]{"flt","f64","f32"} ) { + CodeGen zero = new CodeGen("var a = new "+type+"[arg]; return a[arg-1];") + .parse().opto().typeCheck(); + assertEquals("0.0",Eval2.eval(zero,3)); + // Eval2 does not execute RoundF32 yet; check nonconstant narrowing here. + new CodeGen(type+" x = arg; var a = new "+type+"[arg]; a[0] = x; return a[0];") + .parse().opto().typeCheck(); + } + for( String type : new String[]{"flt","f64"} ) { + CodeGen loop = new CodeGen("var a = new "+type+"[arg]; "+ + "for(int i=0; i<arg; i++) a[i] += i+0.25; return a[0]+a[arg-1];") + .parse().opto().typeCheck(); + assertEquals("0.5",Eval2.eval(loop,1)); + assertEquals("3.5",Eval2.eval(loop,4)); + + CodeGen rounded = new CodeGen("var a = new "+type+"[arg]; "+ + "for(int i=0; i<arg; i++) a[i] = 16777216.0+i; return a[arg-1];") + .parse().opto().typeCheck(); + assertEquals("1.6777217E7",Eval2.eval(rounded,2)); + } + CodeGen rounded = new CodeGen("var a = new f32[arg]; "+ + "for(int i=0; i<arg; i++) a[i] = 16777217.0; return a[arg-1];") + .parse().opto().typeCheck(); + assertEquals("1.6777216E7",Eval2.eval(rounded,2)); + } + @Test public void testNeverExitLoopDepth() { String[] sources = { "if(arg) while(1) {} return 7;", diff --git a/chapter19/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter19/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 78e7698c..10a0e4aa 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -16,6 +16,7 @@ public class RoundF32Node extends Node { public Type compute() { if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) return TypeFloat.constant((float)i0.value()); + if( in(1)._type==TypeFloat.F64 ) return TypeFloat.F32; return in(1)._type; } diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter20/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 78e7698c..10a0e4aa 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -16,6 +16,7 @@ public class RoundF32Node extends Node { public Type compute() { if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) return TypeFloat.constant((float)i0.value()); + if( in(1)._type==TypeFloat.F64 ) return TypeFloat.F32; return in(1)._type; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter21/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 78e7698c..10a0e4aa 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -16,6 +16,7 @@ public class RoundF32Node extends Node { public Type compute() { if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) return TypeFloat.constant((float)i0.value()); + if( in(1)._type==TypeFloat.F64 ) return TypeFloat.F32; return in(1)._type; } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter22/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 78e7698c..10a0e4aa 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -16,6 +16,7 @@ public class RoundF32Node extends Node { public Type compute() { if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) return TypeFloat.constant((float)i0.value()); + if( in(1)._type==TypeFloat.F64 ) return TypeFloat.F32; return in(1)._type; } diff --git a/chapter23/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter23/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 78e7698c..10a0e4aa 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -16,6 +16,7 @@ public class RoundF32Node extends Node { public Type compute() { if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) return TypeFloat.constant((float)i0.value()); + if( in(1)._type==TypeFloat.F64 ) return TypeFloat.F32; return in(1)._type; } diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter24/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 78e7698c..10a0e4aa 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -16,6 +16,7 @@ public class RoundF32Node extends Node { public Type compute() { if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) return TypeFloat.constant((float)i0.value()); + if( in(1)._type==TypeFloat.F64 ) return TypeFloat.F32; return in(1)._type; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter25/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 1a3592dc..65f10a79 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -15,6 +15,7 @@ public class RoundF32Node extends Node { public Type compute() { if (in(1)._type instanceof TypeFloat i0 && i0.isConstant() ) return TypeFloat.constant((float)i0.value()); + if( in(1)._type==TypeFloat.F64 ) return TypeFloat.F32; return in(1)._type; } diff --git a/docs/chapter-backports.md b/docs/chapter-backports.md index e909e573..765cad82 100644 --- a/docs/chapter-backports.md +++ b/docs/chapter-backports.md @@ -473,12 +473,6 @@ lines beyond the original extraction. Cover constant folding, evaluation, and machine lowering on all three targets; update the Chapter 14 explanation and add boundary-case regressions. -- **Existing Chapter 18 floating-array assertion.** The unchanged - `TypeStruct.makeAry` assertion accepts integers and nullable references but - excludes TypeFloat; `return new flt[1];` fails under `-ea`. The Chapter 18 - memory probe uses floating struct fields for initialization coverage instead. - Investigate separately; this port does not change the array type lattice. - - **Chapter 24 Load BOTTOM-on-error backport, unwound/deferred (2026-09-28).** Cliff requested starting with 24 and analyzing failures before proceeding. Literal global BOTTOM memory/pointer inputs already propagate BOTTOM. The @@ -670,6 +664,26 @@ The top-level runner accepts explicit chapter lists, e.g. ## Validation record +- **Floating arrays in Chapter 18 (2026-10-07).** Added TypeFloat to the + `TypeStruct.makeAry` assertion, matching Chapter 19 onward; earlier array + chapters already accept floating elements. The original `return new flt[1];` + reproduction passes with assertions enabled. One regression covers flt/f64/f32 + zero initialization, flt/f64 looped loads and stores, and constant f32 rounding. + It fails at the original assertion before the correction. The complete + Chapter 18 suite passes (340 tests plus its fuzzer wrapper); no other compiler + snapshot needed this assertion change. Nonconstant scalar and array narrowing + now passes type checking with the RoundF32 correction below. Eval2 does not + execute RoundF32 yet, so runtime coverage uses constant f32 stores. Logs: + `build/float-arrays-18-before.log`, `build/float-arrays-18-after.log`. + +- **Nonconstant f32 narrowing (2026-10-07).** RoundF32Node now returns F32 + for an F64 input in Chapters 18-25, and the equivalent B32 for BOT in + Chapters 14-17b. Constant rounding and other input types are unchanged. + Chapter 18's floating-array regression also checks nonconstant scalar and + array assignments. Complete Make suites pass in every affected chapter, + including Chapter 25's native tests; no expected graph or allocation results + changed. Logs: `build/round-f32-<chapter>.log`. + - **Shared Phi inputs and deterministic inlining (2026-10-07).** Chapters 20-25 split a self-conflicting Phi's inputs when another Phi shares them; splitting only the entry and result could leave two loop Phis joined through |
