summaryrefslogtreecommitdiff
path: root/chapter18/src/test/java
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2024-12-29 16:06:07 -0800
committerCliff Click <cliffc@acm.org>2025-01-15 15:07:30 -0800
commit5400096ec10da839cf2006a8a02e11ffeff521dd (patch)
tree863bae81b376d855a3e5dd6f448239d7e1830ac6 /chapter18/src/test/java
parent01f23ae95f2bb609d2d76e0d2d66eecbedd0619d (diff)
downloadSimple-5400096ec10da839cf2006a8a02e11ffeff521dd.tar.gz
Simple-5400096ec10da839cf2006a8a02e11ffeff521dd.zip
More precise error reporting
Demand CFG cleanup, even if peeps are off; cleans up some tests & a lot of fuzzer bugs related to trying to find infinite loops in dead code. Logical subclass for better error reporting on &,|,^,>>,<<,>>> More precise error reporting on multi returns and trinaries Fuzzer uses new Eval2
Diffstat (limited to 'chapter18/src/test/java')
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter02Test.java2
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter03Test.java2
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter09Test.java4
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter17Test.java11
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Eval2.java1
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java41
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java9
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java5
8 files changed, 36 insertions, 39 deletions
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter02Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter02Test.java
index 4254f0a6..324ebf41 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter02Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter02Test.java
@@ -12,7 +12,7 @@ public class Chapter02Test {
public void testParseGrammar() {
CodeGen code = new CodeGen("return 1+2*3+-5;");
code.parse(true); // Disable peepholes
- assertEquals("return Phi(Region,((1+(2*3))+(-5)));", code.print());
+ assertEquals("return ((1+(2*3))+(-5));", code.print());
}
@Test
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter03Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter03Test.java
index 2e45ee2a..a7fc3ae5 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter03Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter03Test.java
@@ -30,7 +30,7 @@ public class Chapter03Test {
public void testVarScopeNoPeephole() {
CodeGen code = new CodeGen("int a=1; int b=2; int !c=0; { int b=3; c=a+b; } return c; ");
code.parse(true);
- assertEquals("return Phi(Region,(1+3));", code.print());
+ assertEquals("return (1+3);", code.print());
}
@Test
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter09Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter09Test.java
index 5b764013..b210f7e9 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter09Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter09Test.java
@@ -194,7 +194,7 @@ int v0=0!=0<-0;
return -0+0+0;
""");
code.parse().opto();
- assertEquals("return 0;", code.print());
+ assertEquals("return Top;", code.print());
}
@@ -243,7 +243,7 @@ while(1) {
return 0!=0;
""");
code.parse().opto();
- assertEquals("return 0;", code.print());
+ assertEquals("return Top;", code.print());
}
@Test
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter17Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter17Test.java
index 4bcb9daa..5247f122 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter17Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter17Test.java
@@ -353,6 +353,17 @@ return f; // missing widening
assertEquals("1.2", Eval2.eval(code, 0));
}
+
+ @Test
+ public void testTrinary6() {
+ CodeGen code = new CodeGen("""
+struct S{};
+return arg ? 7 : new S;
+""");
+ try { code.parse().opto().typeCheck(); fail(); }
+ catch( Exception e ) { assertEquals("No common type amongst int and reference",e.getMessage()); }
+ }
+
// ---------------------------------------------------------------
@Test
public void testFor0() {
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Eval2.java b/chapter18/src/test/java/com/seaofnodes/simple/Eval2.java
index f7f58f32..77cbf115 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Eval2.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Eval2.java
@@ -115,6 +115,7 @@ public abstract class Eval2 {
case MinusNode sub -> - x(sub.in(1));
case MulNode mul -> x(mul.in(1)) * x(mul.in(2));
case NewNode alloc -> alloc(alloc);
+ case NotNode not -> x(not.in(1)) == 0 ? 1L : 0L;
case OrNode or -> x(or .in(1)) | x(or .in(2));
case ProjNode proj -> proj._type instanceof TypeMem ? "$mem" : val(proj.in(0));
case ReadOnlyNode read -> val(read.in(1));
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java b/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java
index 6f5307bc..66395a74 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java
@@ -1,7 +1,8 @@
package com.seaofnodes.simple.fuzzer;
+import com.seaofnodes.simple.Utils;
+import com.seaofnodes.simple.Eval2;
import com.seaofnodes.simple.CodeGen;
-import com.seaofnodes.simple.evaluator.Evaluator;
import com.seaofnodes.simple.node.Node;
import com.seaofnodes.simple.node.StopNode;
import java.util.ArrayList;
@@ -55,18 +56,8 @@ public class Fuzzer {
private static boolean neq(Object a, Object b) {
if (Objects.equals(a, b)) return false;
- if (a instanceof Evaluator.Obj ea && b instanceof Evaluator.Obj eb) {
- if (ea.struct() != eb.struct()) return true;
- for(int i=0;i<ea.fields().length;i++) {
- if (neq(ea.fields()[i], eb.fields()[i])) return true;
- }
- return false;
- }
- if( a==null && b == Long.valueOf(0) )
- return false;
- if( b==null && a == Long.valueOf(0) )
- return false;
- return true;
+ // Deep compare?
+ throw Utils.TODO();
}
/**
@@ -75,11 +66,11 @@ public class Fuzzer {
* @param e2 Evaluator for the second graph
* @param in The input value to both graphs to test for an equal output
*/
- private static void checkGraphs(Evaluator e1, Evaluator e2, long in) {
- var r1 = e1.evaluate(in, EVAL_TIMEOUT);
- var r2 = e2.evaluate(in, EVAL_TIMEOUT);
- if (r1 == Evaluator.Status.TIMEOUT || r2 == Evaluator.Status.TIMEOUT) return;
- if (neq(r1, r2))
+ private static void checkGraphs(CodeGen code1, CodeGen code2, long in) {
+ var r1 = Eval2.eval(code1, in, EVAL_TIMEOUT);
+ var r2 = Eval2.eval(code2, in, EVAL_TIMEOUT);
+ if( r1 == null || r2 == null ) return;
+ if( neq(r1, r2) )
throw new RuntimeException("Different calculations values " + r1 + " vs " + r2);
}
@@ -91,9 +82,9 @@ public class Fuzzer {
* @param valid If the script is definitely valid. If not some exceptions may be suppressed.
*/
private static void runCheck(String script, boolean valid) {
- StopNode stop1;
+ CodeGen code1;
try {
- stop1 = FuzzerUtils.parse(script, false);
+ code1 = FuzzerUtils.parse(script, false);
} catch (RuntimeException e1) {
try {
FuzzerUtils.parse(script, true);
@@ -106,12 +97,10 @@ public class Fuzzer {
}
throw e1;
}
- var stop2 = FuzzerUtils.parse(script, true);
- var e1 = new Evaluator(stop1);
- var e2 = new Evaluator(stop2);
- checkGraphs(e1, e2, 0);
- checkGraphs(e1, e2, 1);
- checkGraphs(e1, e2, 10);
+ CodeGen code2 = FuzzerUtils.parse(script, true);
+ checkGraphs(code1, code2, 0);
+ checkGraphs(code1, code2, 1);
+ checkGraphs(code1, code2, 10);
}
/**
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java b/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java
index 81977522..62a149a8 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java
@@ -114,7 +114,7 @@ class FuzzerUtils {
/**
* Parse script with peepholes enabled or disabled
*/
- public static StopNode parse(String script, boolean runPeeps) {
+ public static CodeGen parse(String script, boolean runPeeps) {
var err = System.err;
var out = System.out;
try {
@@ -126,12 +126,7 @@ class FuzzerUtils {
throw rethrow(e);
}
var code = new CodeGen(script);
- Node._disablePeephole = !runPeeps;
- code.parse();
- if( runPeeps ) code.opto();
- code.typeCheck();
- if( runPeeps ) code.GCM(); // Fixup infinite loops
- return code._stop;
+ return code.parse(!runPeeps).opto().typeCheck().GCM().localSched();
} finally {
NodeWalkVisit.clear();
System.setErr(err);
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java b/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java
index d3cbb0ee..86dbe66a 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java
@@ -483,7 +483,7 @@ public class ScriptGenerator {
fields[i] = new TypeStruct.Field(fieldName.toString(), type, struct);
}
indentation -= INDENTATION;
- printIndentation().append("}");
+ printIndentation().append("};");
struct.fields = fields;
forwardStructs.remove(struct);
structs.add(struct);
@@ -683,7 +683,8 @@ public class ScriptGenerator {
public int genDecl() {
var type = getType();
var name = getVarName();
- sb.append(generateInvalid() ? getRandomName() : type.name).append(" ").append(name);
+ // Always make them mutable
+ sb.append(generateInvalid() ? getRandomName() : type.name).append(" !").append(name);
if (!(type instanceof TypeNullable) || random.nextBoolean()) {
sb.append("=");
genExpression(type, true);