From 413353dc37fead68507856fca500fa59423dca69 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Fri, 11 Sep 2026 12:31:25 -0700 Subject: Optional reset Types so Fuzzer can work. FunNodes never GVN. --- .../main/java/com/seaofnodes/simple/Parser.java | 13 ++++++----- .../com/seaofnodes/simple/codegen/CodeGen.java | 12 +++++------ .../java/com/seaofnodes/simple/node/FunNode.java | 4 ++-- .../java/com/seaofnodes/simple/node/PhiNode.java | 3 ++- .../java/com/seaofnodes/simple/Chapter25Test.java | 25 +++++++++++++++------- .../test/java/com/seaofnodes/simple/Simple.java | 2 +- .../src/test/java/com/seaofnodes/simple/TestC.java | 2 +- .../java/com/seaofnodes/simple/fuzzer/Fuzzer.java | 6 +++--- .../com/seaofnodes/simple/fuzzer/FuzzerUtils.java | 4 ++-- .../seaofnodes/simple/fuzzer/ScriptGenerator.java | 17 +++++---------- 10 files changed, 47 insertions(+), 41 deletions(-) (limited to 'chapter25') diff --git a/chapter25/src/main/java/com/seaofnodes/simple/Parser.java b/chapter25/src/main/java/com/seaofnodes/simple/Parser.java index b6feb809..37c43a7a 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/Parser.java @@ -1249,6 +1249,7 @@ public class Parser { priv = new ProjNode(cend,2,"#selfMem").peephole(); } + priv.keep(); for( Field field : ts._fields ) { Type storage = field._t.makeStorage(); Field escaped = field._final ? field : Field.make(field._fname,storage,field._alias,true); @@ -1260,6 +1261,7 @@ public class Parser { pub.unkeep(); pub = next; } + priv.unkill(); ReturnNode ret = (ReturnNode)new ReturnNode(ctl,pub,self,rpc,fun).peephole(); fun.setRet(ret); fun._approxUIDs = _code.UID() - oldUID; @@ -1697,10 +1699,11 @@ public class Parser { int dir = parseCompDir(); // No compare if( dir==0 ) return lhs; + lhs.keep(); // Compare Node rhs = parseShift().keep(); - Node cmp = makeCompBool(dir,lhs,rhs); // Convert to a bool + Node cmp = makeCompBool(dir,lhs.unkeep(),rhs); // Convert to a bool // Stacked compares? int dir0 = parseCompDir(); @@ -1713,7 +1716,7 @@ public class Parser { // rhs is keeped() and becomes lhs // cmp is NOT keeped() and is the last test Node ifNode = new IfNode(ctrl(), cmp).peephole(); - Node ifT = new CProjNode(ifNode. keep(), 0, "True" ).peephole(); + Node ifT = new CProjNode(ifNode. keep(), 0, "True" ).peephole().keep(); Node ifF = new CProjNode(ifNode.unkeep(), 1, "False").peephole(); // False side does nothing but capture memory & side-effects ScopeNode fail = _scope.dup(); @@ -1726,12 +1729,12 @@ public class Parser { if( Math.abs(dir) != Math.abs(dir0) ) throw error("Mixing relational directions in a chained relational test"); // True side parses next arm of test - ctrl(ifT); + ctrl(ifT.unkeep()); lhs = rhs; // lhs is keeped() and is old RHS rhs = parseShift().keep(); cmp = makeCompBool(dir,lhs.unkeep(),rhs); // Convert to a bool ifNode = new IfNode(ctrl(), cmp).peephole(); - ifT = new CProjNode(ifNode. keep(), 0, "True" ).peephole(); + ifT = new CProjNode(ifNode. keep(), 0, "True" ).peephole().keep(); ifF = new CProjNode(ifNode.unkeep(), 1, "False").peephole(); // Merge result into the fail case ctrl(ifF); @@ -1740,7 +1743,7 @@ public class Parser { dir0 = parseCompDir(); } rhs.unkill(); - ctrl(ifT); + ctrl(ifT.unkeep()); RegionNode r = fail.mergeScopes(_scope, loc()).init(); _scope = fail; return new PhiNode("", r,_code.ZERO,con(1)).peephole(); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java index a83b82a1..24a12e6d 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java @@ -182,24 +182,24 @@ public class CodeGen { // --------------------------- // Test setup; no module nor file with specific argument - public CodeGen( String src ) { this(src, 126L ); } + public CodeGen( String src ) { this(src, 126L, true ); } // Test setup; no module nor file; can alter seed & argument; can re-run same CodeGen public CodeGen( String src, Type arg ) { - this(null,null,null,null, src, 126L, arg); + this(null,null,null,null, src, 126L, true, arg); } // Test setup; no module nor file; can alter seed & argument; can re-run same CodeGen - public CodeGen( String src, long workListSeed ) { - this(null,null,null,null, src, workListSeed, TypeInteger.BOT); + public CodeGen( String src, long workListSeed, boolean resetTypes ) { + this(null,null,null,null, src, workListSeed, resetTypes, TypeInteger.BOT); } // Generic CodeGen, including full module setup public CodeGen( String modDir, String buildDir, Ary externPaths, - String srcName, String src, long workListSeed, Type arg ) { + String srcName, String src, long workListSeed, boolean resetTypes, Type arg ) { // Public singleton to avoid passing about this state to a huge count // of places. Probably becomes a TLS at some point. CODE = this; - Type.reset(); // Reset to recover from failed test + if( resetTypes ) Type.reset(); // Reset to recover from failed test _cwd = System.getProperty("user.dir")+"/"; _modDir = modDir == null ? _cwd : modDir; 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 890a23b0..d9d3e451 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/FunNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/FunNode.java @@ -411,9 +411,9 @@ public class FunNode extends RegionNode { } - // FunNodes must match signature (equivalent: no 2 FunNodes are ever GVN'able) + // no 2 FunNodes are ever GVN'able @Override public boolean eq( Node n ) { - return _sig == ((FunNode)n)._sig; + return this==n; } @Override public int hash() { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/PhiNode.java index 78a2690a..2b6d2666 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/PhiNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/PhiNode.java @@ -141,7 +141,8 @@ public class PhiNode extends Node { if( in(1).getClass() != op.getClass() || op.in(0)!=null || in(1).nIns() != op.nIns() ) return false; // Wrong class or CFG bound or mismatched inputs if( in(1) instanceof MemOpNode mem ) { - assert mem._alias == ((MemOpNode)op)._alias; + // Mismatched aliases + if( mem._alias != ((MemOpNode)op)._alias ) return false; // Load is clobbered somewhere, and can not be pulled forward past the Phi? if( mem instanceof LoadNode ) for( Node use : op.outs() ) diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java index b21734b4..494f503d 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java @@ -18,6 +18,16 @@ import static org.junit.Assert.*; public class Chapter25Test { + @IGnore + @Test + public void testJig() { + String src = "struct _Oan {}; return --arg; arg=++arg;"; + CodeGen code = new CodeGen(src).driver(CodeGen.Phase.TypeCheck); + assertEquals("1",Eval2.eval(code,0)); + } + + + private static final String SYS_BLDDIR = "build/objs/lib_"+TestC.CPU_ABI; private static final File SYS_FILE = new File(SYS_BLDDIR+"/sys.o"); @@ -25,7 +35,7 @@ public class Chapter25Test { public void testForwardConstructor() { CodeGen code = new CodeGen("src/test/java/com/seaofnodes/simple/test_smp/forward_ctor", "build/objs/forward_ctor_parse",null, - "m",null,123L,TypeInteger.BOT); + "m",null,123L,true,TypeInteger.BOT); code.driver(CodeGen.Phase.TypeCheck); } @@ -62,7 +72,6 @@ public class Chapter25Test { assertEquals("1",Eval2.eval(code,0)); } - @Test @Ignore public void testModule0() throws IOException { String MODDIR = "src/test/java/com/seaofnodes/simple/test0"; @@ -77,7 +86,7 @@ public class Chapter25Test { // Since A refers to B also: // Compile MODDIR/A/B.smp into MODDIR/A/B.o CodeGen code1 = new CodeGen(MODDIR, BLDDIR,null, - "A",null,123L,TypeInteger.BOT); + "A",null,123L,true,TypeInteger.BOT); code1.driver(CodeGen.Phase.Export,TestC.CPU_PORT,TestC.CALL_CONVENTION); // Verify produces A.o, A/B.o @@ -94,7 +103,7 @@ public class Chapter25Test { // Compile again A, expecting both A.o and A/B.o to be up-to-date and not compiled CodeGen code2 = new CodeGen(MODDIR, BLDDIR, null, - "A",null,123L,TypeInteger.BOT); + "A",null,123L,true,TypeInteger.BOT); code2.driver(CodeGen.Phase.Export,TestC.CPU_PORT,TestC.CALL_CONVENTION); assertTrue( a_file.exists() ); @@ -108,7 +117,7 @@ public class Chapter25Test { // Touch A.smp and recompile. A/B.o should not recompile. new File(MODDIR+"/A.smp").setLastModified(System.currentTimeMillis()); CodeGen code3 = new CodeGen(MODDIR, BLDDIR,null, - "A",null,123L,TypeInteger.BOT); + "A",null,123L,true,TypeInteger.BOT); code3.driver(CodeGen.Phase.Export,TestC.CPU_PORT,TestC.CALL_CONVENTION); long a_msec3 = a_file.lastModified(); @@ -124,7 +133,7 @@ public class Chapter25Test { // Modify B.smp and recompile A/B.o; it should recompile and A.o should not. writeB(MODDIR,7); CodeGen code4 = new CodeGen(MODDIR, BLDDIR,null, - "A/B",null,123L,TypeInteger.BOT); + "A/B",null,123L,true,TypeInteger.BOT); code4.driver(CodeGen.Phase.Export,TestC.CPU_PORT,TestC.CALL_CONVENTION); long a_msec4 = a_file.lastModified(); @@ -139,7 +148,7 @@ public class Chapter25Test { // Recompile A.o, it should recompile despite not being touched because // it depends on A/B.o which recompiled in the prior step. CodeGen code5 = new CodeGen(MODDIR, BLDDIR,null, - "A",null,123L,TypeInteger.BOT); + "A",null,123L,true,TypeInteger.BOT); code5.driver(CodeGen.Phase.Export,TestC.CPU_PORT,TestC.CALL_CONVENTION); long a_msec5 = a_file.lastModified(); @@ -221,7 +230,7 @@ public class Chapter25Test { String expected = "Hello, World!\n"; String prog = "return sys.io.p_noInline(\""+expected+"\") - "+expected.length()+";"; CodeGen code = new CodeGen(null,"build/objs",new Ary<>(new String[]{SYS_BLDDIR}), - base,prog,123L,TypeInteger.BOT); + base,prog,123L,true,TypeInteger.BOT); code.driver(TestC.CPU_PORT,TestC.CALL_CONVENTION,false,true); String obj = "build/objs/"+base+".o"; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Simple.java b/chapter25/src/test/java/com/seaofnodes/simple/Simple.java index a5d104e7..91f690eb 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Simple.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Simple.java @@ -223,7 +223,7 @@ Options: // Compilation pipeline Ary externPaths = libPaths.isEmpty() ? null : new Ary<>(libPaths.toArray(new String[0])); - CodeGen code = new CodeGen(modPath.toString(), outPath.toString(), externPaths, srcName, src, 456, TypeInteger.BOT ); + CodeGen code = new CodeGen(modPath.toString(), outPath.toString(), externPaths, srcName, src, 456, true, TypeInteger.BOT ); code.driver(Phase.LastPhase,cpu,abi, false, emit_main || do_run || do_eval, dump); if( do_codegen && print_asm ) diff --git a/chapter25/src/test/java/com/seaofnodes/simple/TestC.java b/chapter25/src/test/java/com/seaofnodes/simple/TestC.java index bd8a52cc..b43d117f 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/TestC.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/TestC.java @@ -118,7 +118,7 @@ public abstract class TestC { String obj = pathBase+".o"; String exe = pathBase+(OS.startsWith("Windows") ? ".exe" : ""); // Compile simple, emit ELF - CodeGen code = new CodeGen(null,"build/objs",externPaths,base,src,126L,TypeInteger.BOT); + CodeGen code = new CodeGen(null,"build/objs",externPaths,base,src,126L,true,TypeInteger.BOT); code.driver( CPU_PORT, simple_conv, false, cfile==null ); linkExe(obj, c_conv, cfile, linkObjs(externPaths), exe); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java b/chapter25/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java index c1ffa6c1..37fa03a6 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java @@ -82,10 +82,10 @@ public class Fuzzer { private static void runCheck(String script, boolean valid) { CodeGen code1; try { - code1 = FuzzerUtils.parse(script, 123); + code1 = FuzzerUtils.parse(script, 123, true); } catch (RuntimeException e1) { try { - FuzzerUtils.parse(script, 456); + FuzzerUtils.parse(script, 456, true); } catch (RuntimeException e2) { if (FuzzerUtils.isExceptionFromSameCause(e1, e2)) { if (!valid || e1.getClass() == Parser.ParseException.class) return; @@ -95,7 +95,7 @@ public class Fuzzer { } throw e1; } - CodeGen code2 = FuzzerUtils.parse(script, 456); + CodeGen code2 = FuzzerUtils.parse(script, 456, false); checkGraphs(code1, code2, 0); checkGraphs(code1, code2, 1); checkGraphs(code1, code2, 10); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java b/chapter25/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java index 9175e380..7b3917f4 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java @@ -94,13 +94,13 @@ class FuzzerUtils { /** * Parse script with peepholes enabled or disabled */ - public static CodeGen parse(String script, long workListSeed) { + public static CodeGen parse(String script, long workListSeed, boolean resetTypes ) { var err = System.err; var out = System.out; try { System.setErr(NULL_PRINT_STREAM); System.setOut(NULL_PRINT_STREAM); - var code = new CodeGen(script, workListSeed); + var code = new CodeGen(script, workListSeed, resetTypes); return code.driver(CodeGen.Phase.LocalSched); } finally { System.setErr(err); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java b/chapter25/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java index dde5a1dc..7ecde7c0 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java @@ -83,18 +83,11 @@ public class ScriptGenerator { } } - private static final List INTTYPES = new ArrayList<>(); - static { - for( var e : Parser.TYPES.entrySet() ) { - if( e.getValue() instanceof TypeInteger ) { - INTTYPES.add(new TypeInt(e.getKey())); - } - } - } - - private static final Type TYPE_INT = INTTYPES.stream().filter(t->t.name.equals("int")).findAny().get(); - private static final Type TYPE_BOOL = INTTYPES.stream().filter(t->t.name.equals("bool")).findAny().get(); + private static final TypeInt TYPE_INT = new TypeInt("int"); + private static final TypeInt TYPE_BOOL = new TypeInt("bool"); + private static final TypeInt TYPE_U8 = new TypeInt("u8"); + private static final List INTTYPES = new ArrayList<>(){{add(TYPE_INT); add(TYPE_BOOL); add(TYPE_U8); }}; private static class Variable { final String name; @@ -935,4 +928,4 @@ public class ScriptGenerator { else sb.append(v.name); } -} \ No newline at end of file +} -- cgit v1.2.3