summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2025-02-07 08:58:36 -0800
committerCliff Click <cliffc@acm.org>2025-02-07 08:58:36 -0800
commit2aa8c5d1d0659bd1c828134f1a1f14d025a2d0f1 (patch)
tree0532f3ba5d74de006fcaa906dad9b787ebb06e2e /src/test
parent68dc63b9390bbe4ec50cc1b814d4e559e459c057 (diff)
downloadSimple-2aa8c5d1d0659bd1c828134f1a1f14d025a2d0f1.tar.gz
Simple-2aa8c5d1d0659bd1c828134f1a1f14d025a2d0f1.zip
Ch# Chapter 19: Instruction Selection and Portable Compilationlinear-chapter19
Co-authored-by: hadha <helsgithub15@gmail.com> Co-authored-by: Tamás Hadházy <85063808+Hels15@users.noreply.github.com>
Diffstat (limited to 'src/test')
-rw-r--r--src/test/java/com/seaofnodes/simple/BrainFuckTest.java2
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter02Test.java4
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter03Test.java6
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter04Test.java21
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter05Test.java64
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter06Test.java30
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter07Test.java12
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter08Test.java4
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter09Test.java4
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter13Test.java2
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter14Test.java2
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter15Test.java12
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter17Test.java8
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter18Test.java34
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter19Test.java398
-rw-r--r--src/test/java/com/seaofnodes/simple/Eval2.java6
-rw-r--r--src/test/java/com/seaofnodes/simple/Main.java17
-rw-r--r--src/test/java/com/seaofnodes/simple/SchedulerTest.java1
-rw-r--r--src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java10
-rw-r--r--src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java2
-rw-r--r--src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java19
-rw-r--r--src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java34
-rw-r--r--src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java16
-rw-r--r--src/test/java/com/seaofnodes/simple/progs/fcn.smp15
-rw-r--r--src/test/java/com/seaofnodes/simple/progs/fcn2.smp5
-rw-r--r--src/test/java/com/seaofnodes/simple/progs/fcn3.smp42
-rw-r--r--src/test/java/com/seaofnodes/simple/progs/sieve.smp32
27 files changed, 629 insertions, 173 deletions
diff --git a/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
index 37ecde1c..8f09cb3d 100644
--- a/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
+++ b/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
@@ -63,7 +63,7 @@ for( int pc = 0; pc < program#; pc++ ) {
}
return output;
""");
- code.parse().opto().typeCheck().GCM();
+ code.parse().opto().typeCheck()/*.instSelect("x86_64_v2", "SystemV")*/.GCM().localSched();
assertEquals("Hello World!\n", Eval2.eval(code, 0, 10000));
}
}
diff --git a/src/test/java/com/seaofnodes/simple/Chapter02Test.java b/src/test/java/com/seaofnodes/simple/Chapter02Test.java
index 324ebf41..d8607c32 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter02Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter02Test.java
@@ -11,8 +11,8 @@ public class Chapter02Test {
@Test
public void testParseGrammar() {
CodeGen code = new CodeGen("return 1+2*3+-5;");
- code.parse(true); // Disable peepholes
- assertEquals("return ((1+(2*3))+(-5));", code.print());
+ code.parse(); // No more disable peepholes
+ assertEquals("return 2;", code.print());
}
@Test
diff --git a/src/test/java/com/seaofnodes/simple/Chapter03Test.java b/src/test/java/com/seaofnodes/simple/Chapter03Test.java
index 825235cc..4f9b2490 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter03Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter03Test.java
@@ -29,8 +29,8 @@ public class Chapter03Test {
@Test
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 (1+3);", code.print());
+ code.parse(); // Peepholes always run now
+ assertEquals("return 4;", code.print());
}
@Test
@@ -53,7 +53,7 @@ public class Chapter03Test {
@Test
public void testRedeclareVar() {
try {
- new Parser("int a=1; int b=2; int c=0; int b=3; c=a+b;").parse();
+ new CodeGen("int a=1; int b=2; int c=0; int b=3; c=a+b;").parse();
fail();
} catch( RuntimeException e ) {
assertEquals("Redefining name 'b'",e.getMessage());
diff --git a/src/test/java/com/seaofnodes/simple/Chapter04Test.java b/src/test/java/com/seaofnodes/simple/Chapter04Test.java
index afed67d1..d09b1748 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter04Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter04Test.java
@@ -34,14 +34,14 @@ public class Chapter04Test {
public void testAddAddMul() {
CodeGen code = new CodeGen("return arg+0+arg;");
code.parse();
- assertEquals("return (arg*2);", code.print());
+ assertEquals("return (arg<<1);", code.print());
}
@Test
public void testPeephole3() {
CodeGen code = new CodeGen("return 1+arg+2+arg+3; ");
code.parse();
- assertEquals("return ((arg*2)+6);", code.print());
+ assertEquals("return ((arg<<1)+6);", code.print());
}
@Test
@@ -62,8 +62,7 @@ public class Chapter04Test {
// Adding functions means `main` does not constant fold the incoming arg value
@Ignore @Test
public void testConstantArg() {
- CodeGen code = new CodeGen("return arg; ", TypeInteger.constant(2));
- code.parse();
+ CodeGen code = new CodeGen("return arg; ", TypeInteger.constant(2), 123L).parse();
assertEquals("return 2;", code.expr().in(1).toString());
}
@@ -111,12 +110,8 @@ public class Chapter04Test {
@Test
public void testBug3() {
- try {
- new Parser("inta=1; return a;").parse();
- fail();
- } catch( RuntimeException e ) {
- assertEquals("Undefined name 'inta'",e.getMessage());
- }
+ try { new CodeGen("inta=1; return a;").parse(); fail(); }
+ catch( RuntimeException e ) { assertEquals("Undefined name 'inta'",e.getMessage()); }
}
@Test
@@ -128,8 +123,8 @@ public class Chapter04Test {
@Test
public void testBug5() {
- Parser parser = new Parser("return arg--2;");
- StopNode ret = parser.parse();
- assertEquals("return (arg--2);", ret.print());
+ CodeGen code = new CodeGen("return arg--2;");
+ code.parse();
+ assertEquals("return (arg--2);", code.print());
}
}
diff --git a/src/test/java/com/seaofnodes/simple/Chapter05Test.java b/src/test/java/com/seaofnodes/simple/Chapter05Test.java
index f4db5624..86ec4136 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter05Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter05Test.java
@@ -64,7 +64,7 @@ else
b=a+1;
return a+b;""");
code.parse().opto();
- assertEquals("return ((arg*2)+Phi(Region,2,3));", code.print());
+ assertEquals("return ((arg<<1)+Phi(Region,2,3));", code.print());
}
@Test
@@ -79,7 +79,7 @@ else
a=b+1;
return a+b;""");
code.parse().opto();
- assertEquals("return ((Phi(Region,(arg*2),arg)+arg)+Phi(Region,4,5));", code.print());
+ assertEquals("return ((Phi(Region,(arg<<1),arg)+arg)+Phi(Region,4,5));", code.print());
}
@Test
@@ -135,79 +135,51 @@ return a;
@Test
public void testTrue() {
- StopNode stop = new Parser("return true;").parse();
- assertEquals("return 1;",stop.ret().print());
+ CodeGen code = new CodeGen("return true;").parse();
+ assertEquals("return 1;",code.print());
}
@Test
public void testHalfDef() {
- try {
- new CodeGen("if( arg==1 ) int b=2; return b;").parse();
- fail();
- } catch( RuntimeException e ) {
- assertEquals("Cannot define a 'b' on one arm of an if",e.getMessage());
- }
+ try { new CodeGen("if( arg==1 ) int b=2; return b;").parse(); fail(); }
+ catch( RuntimeException e ) { assertEquals("Cannot define a 'b' on one arm of an if",e.getMessage()); }
}
@Test
public void testHalfDef2() {
- try {
- new Parser("if( arg==1 ) { int b=2; } else { int b=3; } return b;").parse();
- fail();
- } catch( RuntimeException e ) {
- assertEquals("Undefined name 'b'",e.getMessage());
- }
+ try { new CodeGen("if( arg==1 ) { int b=2; } else { int b=3; } return b;").parse(); fail(); }
+ catch( RuntimeException e ) { assertEquals("Undefined name 'b'",e.getMessage()); }
}
@Test
public void testRegress1() {
- try {
- new CodeGen("if(arg==2) int a=1; else int b=2; return a;").parse();
- fail();
- } catch( RuntimeException e ) {
- assertEquals("Cannot define a 'a' on one arm of an if",e.getMessage());
- }
+ try { new CodeGen("if(arg==2) int a=1; else int b=2; return a;").parse(); fail(); }
+ catch( RuntimeException e ) { assertEquals("Cannot define a 'a' on one arm of an if",e.getMessage()); }
}
@Test
public void testBadNum() {
- try {
- new Parser("return 1-;").parse();
- fail();
- } catch( RuntimeException e ) {
- assertEquals("Syntax error, expected an identifier or expression: ;",e.getMessage());
- }
+ try { new CodeGen("return 1-;").parse(); fail(); }
+ catch( RuntimeException e ) { assertEquals("Syntax error, expected an identifier or expression: ;",e.getMessage()); }
}
@Test
public void testKeyword1() {
- try {
- new Parser("int true=0; return true;").parse();
- fail();
- } catch( RuntimeException e ) {
- assertEquals("Expected an identifier, found 'true'",e.getMessage());
- }
+ try { new CodeGen("int true=0; return true;").parse(); fail(); }
+ catch( RuntimeException e ) { assertEquals("Expected an identifier, found 'true'",e.getMessage()); }
}
@Test
public void testKeyword2() {
- try {
- new Parser("int else=arg; if(else) else=2; else else=1; return else;").parse();
- fail();
- } catch( RuntimeException e ) {
- assertEquals("Expected an identifier, found 'else'",e.getMessage());
- }
+ try { new CodeGen("int else=arg; if(else) else=2; else else=1; return else;").parse(); fail(); }
+ catch( RuntimeException e ) { assertEquals("Expected an identifier, found 'else'",e.getMessage()); }
}
@Test
public void testKeyword3() {
- try {
- new CodeGen("int a=1; ififif(arg);a=2;return a;").parse();
- fail();
- } catch( RuntimeException e ) {
- assertEquals("Undefined name 'ififif'",e.getMessage());
- }
+ try { new CodeGen("int a=1; ififif(arg);a=2;return a;").parse(); fail(); }
+ catch( RuntimeException e ) { assertEquals("Undefined name 'ififif'",e.getMessage()); }
}
}
diff --git a/src/test/java/com/seaofnodes/simple/Chapter06Test.java b/src/test/java/com/seaofnodes/simple/Chapter06Test.java
index 2107cdb0..117531f0 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter06Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter06Test.java
@@ -103,8 +103,7 @@ else if( arg==3 )
else
a=5;
return a;
-""", TypeInteger.constant(2));
- code.parse().opto();
+""", TypeInteger.constant(2), 123L).parse().opto();
assertEquals("return 5;", code.print());
}
@@ -124,8 +123,7 @@ else if( arg==3 )
else
a=5;
return a;
-""", TypeInteger.constant(1));
- code.parse().opto();
+""", TypeInteger.constant(1), 123L).parse().opto();
assertEquals("return 3;", code.print());
}
@@ -165,7 +163,7 @@ else if( arg==3 )
else
a=5;
return a;
-""", TypeInteger.constant(1));
+""", TypeInteger.constant(1), 123L);
code.parse().opto();
assertEquals("return 3;", code.print());
}
@@ -186,7 +184,7 @@ else if( arg==3 )
else
a=5;
return a;
-""", TypeInteger.constant(3));
+""", TypeInteger.constant(3), 123L);
code.parse().opto();
assertEquals("return 4;", code.print());
}
@@ -210,7 +208,8 @@ return a+b;
@Test
public void testDemo1True() {
- CodeGen code = new CodeGen("""
+ CodeGen code = new CodeGen(
+"""
arg=1;
int a = 0;
int b = 1;
@@ -220,14 +219,15 @@ if( arg ) {
else b = 3;
}
return a+b;
-""", TypeInteger.constant(1));
+""", TypeInteger.constant(1), 123L);
code.parse().opto();
assertEquals("return 4;", code.print());
}
@Test
public void testDemo1False() {
- CodeGen code = new CodeGen("""
+ CodeGen code = new CodeGen(
+"""
arg=0;
int a = 0;
int b = 1;
@@ -237,7 +237,7 @@ if( arg ) {
else b = 3;
}
return a+b;
-""", TypeInteger.constant(0));
+""", TypeInteger.constant(0), 123L);
code.parse().opto();
assertEquals("return 1;", code.print());
}
@@ -263,7 +263,8 @@ return a+b+c;
@Test
public void testDemo2True() {
- CodeGen code = new CodeGen("""
+ CodeGen code = new CodeGen(
+"""
arg=1;
int a = 0;
int b = 1;
@@ -275,14 +276,15 @@ if( arg ) {
else b = 3;
}
return a+b+c;
-""", TypeInteger.constant(1));
+""", TypeInteger.constant(1), 123L);
code.parse().opto();
assertEquals("return 6;", code.print());
}
@Test
public void testDemo2arg2() {
- CodeGen code = new CodeGen("""
+ CodeGen code = new CodeGen(
+"""
arg=2;
int a = 0;
int b = 1;
@@ -294,7 +296,7 @@ if( arg ) {
else b = 3;
}
return a+b+c;
-""", TypeInteger.constant(2));
+""", TypeInteger.constant(2), 123L);
code.parse().opto();
assertEquals("return 5;", code.print());
}
diff --git a/src/test/java/com/seaofnodes/simple/Chapter07Test.java b/src/test/java/com/seaofnodes/simple/Chapter07Test.java
index 7cef0d9c..6d6a3ce7 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter07Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter07Test.java
@@ -16,11 +16,9 @@ while(arg < 10) {
}
return arg;
""");
- Node._disablePeephole = true;
code.parse();
assertEquals("return Phi(Loop,arg,(Phi_arg+1));", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
- Node._disablePeephole = false;
}
@Test
@@ -71,11 +69,9 @@ while(a < 10) {
}
return b;
""");
- Node._disablePeephole = true;
code.parse();
assertEquals("return Phi(Loop,2,Phi(Region,Phi_b,4));", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
- Node._disablePeephole = false;
}
@Test
@@ -109,11 +105,9 @@ while(a < 10) {
}
return a;
""");
- Node._disablePeephole = true;
code.parse();
assertEquals("return Phi(Loop,1,(Phi_a+3));", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
- Node._disablePeephole = false;
}
@Test
@@ -140,11 +134,9 @@ int a = 1;
while(arg) a = 2;
return a;
""");
- Node._disablePeephole = true;
code.parse();
assertEquals("return Phi(Loop,1,2);", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
- Node._disablePeephole = false;
}
@Test
@@ -171,11 +163,9 @@ while(a < 10) {
}
return a;
""");
- Node._disablePeephole = true;
code.parse();
assertEquals("return Phi(Loop,1,(Phi_a+3));", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
- Node._disablePeephole = false;
}
@Test
@@ -206,11 +196,9 @@ while(a < 10) {
}
return a;
""");
- Node._disablePeephole = true;
code.parse();
assertEquals("return Phi(Loop,1,(Phi_a+3));", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
- Node._disablePeephole = false;
}
@Test
diff --git a/src/test/java/com/seaofnodes/simple/Chapter08Test.java b/src/test/java/com/seaofnodes/simple/Chapter08Test.java
index 03a2c50a..350df18b 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter08Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter08Test.java
@@ -1,8 +1,6 @@
package com.seaofnodes.simple;
-import com.seaofnodes.simple.evaluator.Evaluator;
import com.seaofnodes.simple.node.*;
-import com.seaofnodes.simple.type.TypeInteger;
import org.junit.Assert;
import org.junit.Test;
@@ -147,7 +145,7 @@ return arg;
@Test
public void testBreakOutsideLoop() {
try {
- new Parser("""
+ new CodeGen("""
if(arg <= 10) {
break;
arg = arg + 1;
diff --git a/src/test/java/com/seaofnodes/simple/Chapter09Test.java b/src/test/java/com/seaofnodes/simple/Chapter09Test.java
index b210f7e9..10f4a78b 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter09Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter09Test.java
@@ -41,7 +41,7 @@ else {
return x;
""");
code.parse().opto();
- assertEquals("return Phi(Region,(arg*2),(Mul+1));", code.print());
+ assertEquals("return Phi(Region,(arg<<1),(Shl+1));", code.print());
Assert.assertEquals( "2", Eval2.eval(code, 1));
Assert.assertEquals("23", Eval2.eval(code, 11));
}
@@ -255,7 +255,7 @@ while(0==1) while(v0)
v0=1+v0;
""");
code.parse().opto();
- assertEquals("return ~int;", code.print());
+ assertEquals("return 0;", code.print());
}
@Test
diff --git a/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/src/test/java/com/seaofnodes/simple/Chapter13Test.java
index 6aa64bf9..d05fd7d8 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter13Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter13Test.java
@@ -168,7 +168,7 @@ return new S1.s=new S2;
struct I {int i;};
struct P { I? pi; };
P !p1 = new P;
-P p2 = new P;
+P !p2 = new P;
p2.pi = new I;
p2.pi.i = 2;
if (arg) p1 = new P;
diff --git a/src/test/java/com/seaofnodes/simple/Chapter14Test.java b/src/test/java/com/seaofnodes/simple/Chapter14Test.java
index a3025001..17708c37 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter14Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter14Test.java
@@ -174,7 +174,7 @@ while(v1) break;
return v1;
""");
code.parse().opto();
- assertEquals("return (Phi(Loop,((1<<arg)&1),0)&Phi(Loop,Shl,4294967295));", code.print());
+ assertEquals("return Phi(Loop,(((1<<arg)&1)&Shl),0);", code.print());
assertEquals("1", Eval2.eval(code, 0));
}
diff --git a/src/test/java/com/seaofnodes/simple/Chapter15Test.java b/src/test/java/com/seaofnodes/simple/Chapter15Test.java
index 86f5007d..546eb0e9 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter15Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter15Test.java
@@ -140,7 +140,7 @@ struct S { int x; flt y; };
S !s = new S; s.x=99; s.y = 3.14;
// Double-d array of Ss. Fill in one row.
-S?[]?[] iss = new S?[]?[2];
+S?[]?[] !iss = new S?[]?[2];
iss[0] = new S?[7];
iss[0][2] = s;
@@ -149,10 +149,12 @@ flt rez = 1.2;
if( iss[arg] )
if( iss[arg][2] )
rez = iss[arg][2].y;
-return rez;
-""");
- try { code.parse().opto().typeCheck(); fail(); }
- catch( Exception e ) { assertEquals("Might be null accessing 'y'",e.getMessage()); }
+return rez;""");
+ code.parse().opto().typeCheck();
+ assertEquals("return Phi(Region,Phi(Region,.y,1.2),1.2);", code.print());
+ assertEquals("3.14", Eval2.eval(code, 0));
+ try { Eval2.eval(code, 10); fail(); } // Fails AIOOBE in Eval2, no range checks
+ catch( Exception e ) { assertEquals("Index 10 out of bounds for length 2",e.getMessage()); }
}
@Test
diff --git a/src/test/java/com/seaofnodes/simple/Chapter17Test.java b/src/test/java/com/seaofnodes/simple/Chapter17Test.java
index 8ec95f33..a1d0f8b9 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter17Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter17Test.java
@@ -37,7 +37,7 @@ return arg++;
return arg+++arg++;
""");
code.parse().opto();
- assertEquals("return ((arg*2)+1);", code.print());
+ assertEquals("return ((arg<<1)+1);", code.print());
assertEquals("1", Eval2.eval(code, 0));
}
@@ -48,7 +48,7 @@ return arg+++arg++;
return -arg---arg--;
""");
code.parse().opto();
- assertEquals("return (-((arg*2)+-1));", code.print());
+ assertEquals("return (-((arg<<1)+-1));", code.print());
assertEquals("1", Eval2.eval(code, 0));
}
@@ -342,7 +342,7 @@ var b = arg ? new Bar : null;
return b ? b.x++ + b.x++ : -1;
""");
code.parse().opto();
- assertEquals("return Phi(Region,((.x*2)+1),-1);", code.print());
+ assertEquals("return Phi(Region,((.x<<1)+1),-1);", code.print());
assertEquals("-1", Eval2.eval(code, 0));
assertEquals("1", Eval2.eval(code, 1));
}
@@ -355,7 +355,7 @@ var b = arg ? new Bar;
return b ? b.x++ + b.x++ : -1;
""");
code.parse().opto();
- assertEquals("return Phi(Region,((.x*2)+1),-1);", code.print());
+ assertEquals("return Phi(Region,((.x<<1)+1),-1);", code.print());
assertEquals("-1", Eval2.eval(code, 0));
assertEquals("1", Eval2.eval(code, 1));
}
diff --git a/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/src/test/java/com/seaofnodes/simple/Chapter18Test.java
index 60f9b847..db970f60 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter18Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter18Test.java
@@ -64,7 +64,7 @@ return sq;
""");
code.parse().opto();
assertEquals("Stop[ return { sq}; return (Parm_x(sq,int)*x); ]", code._stop.toString());
- assertEquals("{ sq}", Eval2.eval(code, 3));
+ assertEquals("{ int -> int #1}", Eval2.eval(code, 3));
}
@Test
@@ -76,7 +76,7 @@ var sq = { int x ->
};
return sq(arg)+sq(3);
""");
- code.parse().opto();
+ code.parse().opto().typeCheck().GCM().localSched();
assertEquals("Stop[ return (sq( 3)+sq( arg)); return (Parm_x(sq,int,3,arg)*x); ]", code._stop.toString());
assertEquals("13", Eval2.eval(code, 2));
}
@@ -115,7 +115,7 @@ var fcn = arg ? { int x -> x*x; } : { int x -> x+x; };
return fcn(3);
""");
code.parse().opto();
- assertEquals("Stop[ return Phi(Region,{ int -> int #1},{ int -> int #2})( 3); return (Parm_x($fun,int,3)*x); return (Parm_x($fun,int,3)*2); ]", code._stop.toString());
+ assertEquals("Stop[ return Phi(Region,{ int -> int #1},{ int -> int #2})( 3); return (Parm_x($fun,int,3)*x); return (Parm_x($fun,int,3)<<1); ]", code._stop.toString());
assertEquals("6", Eval2.eval(code, 0));
assertEquals("9", Eval2.eval(code, 1));
}
@@ -124,7 +124,7 @@ return fcn(3);
@Test
public void testFcn5() {
CodeGen code = new CodeGen("val fact = { int x -> x <= 1 ? 1 : x*fact(x-1); }; return fact(arg);");
- code.parse().opto();
+ code.parse().opto().typeCheck();
assertEquals("Stop[ return fact( arg); return Phi(Region,1,(Parm_x(fact,int,arg,(x-1))*fact( Sub))); ]", code._stop.toString());
assertEquals( "1", Eval2.eval(code, 0));
assertEquals( "1", Eval2.eval(code, 1));
@@ -179,7 +179,6 @@ for(;;) {
assertEquals("3", Eval2.eval(code, 0));
}
-
@Test
public void testFcn9() {
CodeGen code = new CodeGen(
@@ -196,6 +195,31 @@ for(;;) {
assertEquals(null, Eval2.eval(code, 0));
}
+
+ @Test
+ public void testFcn10() {
+ CodeGen code = new CodeGen(
+"""
+struct Person {
+ int age;
+};
+
+val fcn = { Person?[] ps, int x ->
+ val tmp = ps[x];
+ if( ps[x] )
+ ps[x].age++;
+};
+
+var ps = new Person?[2];
+ps[0] = new Person;
+ps[1] = new Person;
+fcn(ps,1);
+""");
+ code.parse().opto().typeCheck().GCM().localSched();
+ assertEquals("return 0;", code._stop.toString());
+ assertEquals("0", Eval2.eval(code, 0));
+ }
+
// Function break
@Test
public void testErr1() {
diff --git a/src/test/java/com/seaofnodes/simple/Chapter19Test.java b/src/test/java/com/seaofnodes/simple/Chapter19Test.java
new file mode 100644
index 00000000..a4857a01
--- /dev/null
+++ b/src/test/java/com/seaofnodes/simple/Chapter19Test.java
@@ -0,0 +1,398 @@
+package com.seaofnodes.simple;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+import static org.junit.Assert.fail;
+import org.junit.Ignore;
+
+public class Chapter19Test {
+
+ @Test
+ public void testJig() {
+ CodeGen code = new CodeGen("""
+return 0;
+""");
+ code.parse().opto().typeCheck();
+ assertEquals("return 0;", code._stop.toString());
+ assertEquals("0", Eval2.eval(code, 2));
+ }
+
+
+ @Test
+ public void testString() {
+ CodeGen code = new CodeGen(
+"""
+struct String {
+ u8[] cs;
+ int _hashCode;
+};
+
+val equals = { String self, String s ->
+ if( self == s ) return true;
+ if( self.cs# != s.cs# ) return false;
+ for( int i=0; i< self.cs#; i++ )
+ if( self.cs[i] != s.cs[i] )
+ return false;
+ return true;
+};
+
+val hashCode = { String self ->
+ self._hashCode
+ ? self._hashCode
+ : (self._hashCode = _hashCodeString(self));
+};
+
+val _hashCodeString = { String self ->
+ int hash=0;
+ if( self.cs ) {
+ for( int i=0; i< self.cs#; i++ )
+ hash = hash*31 + self.cs[i];
+ }
+ if( !hash ) hash = 123456789;
+ return hash;
+};
+
+String !s = new String { cs = new u8[17]; };
+s.cs[0] = 67; // C
+s.cs[1] = 108; // l
+hashCode(s);""");
+ code.parse().opto().typeCheck().GCM().localSched();
+ assertEquals("Stop[ return Phi(Region,123456789,Phi(Loop,0,(.[]+((Phi_hash<<5)-Phi_hash)))); return Phi(Region,1,0,0,1); ]", code._stop.toString());
+ assertEquals("-2449306563677080489", Eval2.eval(code, 2));
+ }
+
+ @Test
+ public void testBasic0() {
+ CodeGen code = new CodeGen("return 0;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return 0;", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic1() {
+ CodeGen code = new CodeGen("return arg+1;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (inc,arg);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic2() {
+ CodeGen code = new CodeGen("return -17;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return -17;", code._stop.toString());
+ }
+
+
+ @Test
+ public void testBasic3() {
+ CodeGen code = new CodeGen("return arg==1;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (set==,(cmp,arg));", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic4() {
+ CodeGen code = new CodeGen("return arg<<1;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (shli,arg);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic5() {
+ CodeGen code = new CodeGen("return arg >> 1;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (sari,arg);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic6() {
+ CodeGen code = new CodeGen("return arg >>> 1;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (shri,arg);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic7() {
+ CodeGen code = new CodeGen("return arg / 2;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (div,arg,2);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic8() {
+ CodeGen code = new CodeGen("return arg * 6;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (muli,arg);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic9() {
+ CodeGen code = new CodeGen("return arg & 2;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (andi,arg);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic10() {
+ CodeGen code = new CodeGen("return arg | 2;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (ori,arg);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic11() {
+ CodeGen code = new CodeGen("return arg ^ 2;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (xori,arg);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic12() {
+ CodeGen code = new CodeGen("return arg + 2.0;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (addf,(i2f8,arg),2.0f);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic13() {
+ CodeGen code = new CodeGen("return arg - 2.0;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (subf,(i2f8,arg),2.0f);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic14() {
+ CodeGen code = new CodeGen("return arg * 2.0;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (mulf,(i2f8,arg),2.0f);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic15() {
+ CodeGen code = new CodeGen("return arg / 2.0;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (divf,(i2f8,arg),2.0f);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic16() {
+ CodeGen code = new CodeGen(
+"""
+int arg1 = arg + 1;
+return arg1 / arg;""");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (div,(inc,arg),arg);", code._stop.toString());
+ }
+
+ @Test
+ public void testBasic17() {
+ CodeGen code = new CodeGen(
+"""
+int arg1 = arg + 1;
+return arg1 * arg;
+""");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (mul,(inc,arg),arg);", code._stop.toString());
+ }
+
+ @Test
+ public void testToFloat() {
+ CodeGen code = new CodeGen("""
+ int a = arg;
+ return a + 2.0;
+ """
+ ).parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (addf,(i2f8,arg),2.0f);", code._stop.toString());
+ }
+
+ @Test
+ public void testIfStmt() {
+ CodeGen code = new CodeGen(
+"""
+int a = 1;
+if (arg == 1)
+ a = arg+2;
+else {
+ a = arg-3;
+}
+return a;""");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return Phi(Region,(addi,arg),(addi,arg));", code.print());
+ }
+
+ @Test
+ public void testIfMerge2() {
+ CodeGen code = new CodeGen(
+"""
+int a=arg+1;
+int b=arg+2;
+if( arg==1 )
+ b=b+a;
+else
+ a=b+1;
+return a+b;""");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (add,(add,Phi(Region,(shli,arg),arg),arg),Phi(Region,4,5));", code.print());
+ }
+
+ @Test
+ public void testLoop() {
+ CodeGen code = new CodeGen(
+"""
+int sum=0;
+for( int i=0; i<arg; i++ )
+ sum += i;
+return sum;""");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return Phi(Loop,0,(add,Phi_sum,Phi(Loop,0,(inc,Phi_i))));", code.print());
+ }
+
+ @Test
+ public void testAlloc1() {
+ CodeGen code = new CodeGen(
+"""
+struct S { int a; S? c; };
+return new S;""");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return S;", code.print());
+ }
+
+ @Test
+ public void testLea1() {
+ CodeGen code = new CodeGen("int x = arg/3; return arg+x+7;");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (lea,arg,(div,arg,3));", code.print());
+ }
+
+ @Test
+ public void testLea2() {
+ CodeGen code = new CodeGen("int x = arg/3; return arg+x*4+7;");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (lea,arg,(div,arg,3));", code.print());
+ }
+
+ @Test
+ public void testLea3() {
+ CodeGen code = new CodeGen("int x = arg/3; return x*4+arg;");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return (lea,arg,(div,arg,3));", code.print());
+ }
+
+ @Test
+ public void testAlloc2() {
+ CodeGen code = new CodeGen("int[] !xs = new int[3]; xs[arg]=1; return xs[arg&1];");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return .[];", code.print());
+ }
+
+ @Test
+ public void testAlloc3() {
+ CodeGen code = new CodeGen("int[] !xs = new int[3]; xs[arg]=1; return xs[arg&1]+3;");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return .[];", code.print());
+ }
+
+ @Test
+ public void testArray1() {
+ CodeGen code = new CodeGen(
+"""
+int[] !ary = new int[arg];
+// Fill [0,1,2,3,4,...]
+for( int i=0; i<ary#; i++ )
+ ary[i] = i;
+// Fill [0,1,3,6,10,...]
+for( int i=0; i<ary#-1; i++ )
+ ary[i+1] += ary[i];
+return ary[1] * 1000 + ary[3]; // 1 * 1000 + 6
+""");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return .[];", code.print());
+ }
+
+ @Test
+ public void testArray2() {
+ CodeGen code = new CodeGen(
+"""
+flt[] !A = new flt[arg], !B = new flt[arg];
+// Fill [0,1,2,3,4,...]
+for( int i=0; i<A#; i++ )
+ A[i] = i;
+for( int i=0; i<A#; i++ )
+ B[i] += A[i];
+""");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return 0;", code.print());
+ }
+
+ @Test
+ public void testArray3() {
+ CodeGen code = new CodeGen(
+"""
+byte[] !A = new byte[arg];
+for( int i=0; i<A#; i++ )
+ A[i]++;
+return A[1];
+""");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return .[];", code.print());
+ }
+
+ @Test
+ public void testNewton() {
+ CodeGen code = new CodeGen(
+"""
+// Newtons approximation to the square root
+val sqrt = { flt x ->
+ flt guess = x;
+ while( 1 ) {
+ flt next = (x/guess + guess)/2;
+ if( next == guess ) return guess;
+ guess = next;
+ }
+};
+flt farg = arg;
+return sqrt(farg);
+""");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return Phi(Loop,(i2f8,arg),(divf,(addf,(divf,i2f8,Phi_guess),Phi_guess),2.0f));", code.print());
+ };
+
+
+ @Test
+ public void sieveOfEratosthenes() {
+ CodeGen code = new CodeGen(
+"""
+var ary = new bool[arg], primes = new int[arg];
+var nprimes=0, p=0;
+// Find primes while p^2 < arg
+for( p=2; p*p < arg; p++ ) {
+ // skip marked non-primes
+ while( ary[p] ) p++;
+ // p is now a prime
+ primes[nprimes++] = p;
+ // Mark out the rest non-primes
+ for( int i = p + p; i < ary#; i += p )
+ ary[i] = true;
+}
+// Now just collect the remaining primes, no more marking
+for( ; p < arg; p++ )
+ if( !ary[p] )
+ primes[nprimes++] = p;
+// Copy/shrink the result array
+var !rez = new int[nprimes];
+for( int j=0; j<nprimes; j++ )
+ rez[j] = primes[j];
+return rez;
+""");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("return [int];", code.print());
+ //assertEquals("int[ 2,3,5,7,11,13,17,19]",Eval2.eval(code, 20));
+ }
+
+
+ @Test
+ public void testFcn1() {
+ CodeGen code = new CodeGen(
+"""
+val fcn = arg ? { int x -> x*x; } : { int x -> x+x; };
+return fcn(2)*10 + fcn(3);
+""");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("Stop[ return (add,Phi(Region,{ int -> int #1},{ int -> int #2})( 3),(muli,Phi_( 2))); return (mul,Parm_x($fun,int,3,2),x); return (shli,Parm_x($fun,int,3,2)); ]", code.print());
+ }
+
+ @Test
+ public void testFcn2() {
+ CodeGen code = new CodeGen(
+"""
+val sq = { int x -> x*x; };
+return sq(arg) + sq(3);
+""");
+ code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched();
+ assertEquals("Stop[ return (add,sq(),sq()); return (mul,Parm_x(sq,int,3,arg),x); ]", code.print());
+ }
+}
diff --git a/src/test/java/com/seaofnodes/simple/Eval2.java b/src/test/java/com/seaofnodes/simple/Eval2.java
index 2da834e5..6ae8427c 100644
--- a/src/test/java/com/seaofnodes/simple/Eval2.java
+++ b/src/test/java/com/seaofnodes/simple/Eval2.java
@@ -179,7 +179,7 @@ public abstract class Eval2 {
int path = r._inputs.find( prior );
// Parameters read from prior frame, Phis from local frame
Frame frame = (r instanceof FunNode ? F._prior : F);
- boolean isMain = r instanceof FunNode fun && fun.sig().isa(TypeFunPtr.MAIN);
+ boolean isMain = r instanceof FunNode fun && fun.sig().isa(CodeGen.CODE._main);
// Parallel assign Phis. First parallel read and cache
int i;
@@ -341,7 +341,7 @@ public abstract class Eval2 {
int num = type._fields.length;
Object[] ptr = new Object[num];
for( int i=0; i<num; i++ )
- ptr[i] = val(alloc.in(2+i+num));
+ ptr[i] = con(type._fields[i]._type.makeZero());
return ptr;
}
@@ -357,6 +357,8 @@ public abstract class Eval2 {
}
private static Object store( StoreNode st ) {
+ if( st._name.equals("#") )
+ return "$mem"; // Eval stores the length in the java object[], no need to set it now
TypeMemPtr tmp = (TypeMemPtr)st.ptr()._type;
Object[] fs = (Object[])val(st.ptr());
int idx = tmp._obj.isAry()
diff --git a/src/test/java/com/seaofnodes/simple/Main.java b/src/test/java/com/seaofnodes/simple/Main.java
new file mode 100644
index 00000000..523bd306
--- /dev/null
+++ b/src/test/java/com/seaofnodes/simple/Main.java
@@ -0,0 +1,17 @@
+package com.seaofnodes.simple;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class Main {
+ // Compile and run a simple program
+ public static void main( String[] args ) throws Exception {
+ // First arg is file, 2nd+ args are program args
+ String src = Files.readString(Path.of(args[0]));
+ int arg = Integer.valueOf(args[1]);
+ CodeGen code = new CodeGen(src);
+ code.parse().opto().typeCheck().GCM().localSched();
+ System.out.println(code._stop);
+ System.out.println(Eval2.eval(code,arg,100000));
+ }
+}
diff --git a/src/test/java/com/seaofnodes/simple/SchedulerTest.java b/src/test/java/com/seaofnodes/simple/SchedulerTest.java
index e869e133..d50c302a 100644
--- a/src/test/java/com/seaofnodes/simple/SchedulerTest.java
+++ b/src/test/java/com/seaofnodes/simple/SchedulerTest.java
@@ -30,7 +30,6 @@ int i=v.f;
if (arg) v.f=1;
return i;
""");
- StopNode._disablePeephole = true;
code.parse();//.opto();
var eval = new Evaluator(code._stop);
assertEquals(2L, eval.evaluate(1, 10));
diff --git a/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java b/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java
index 92b424df..a3b87e90 100644
--- a/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java
+++ b/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java
@@ -202,8 +202,12 @@ public class Evaluator {
body[0] = vall(alloc.in(2+2));
} else {
body = new Object[num = type._fields.length];
- for (int i=0; i<num; i++)
- body[i] = val(alloc.in(2+i+num));
+ for( int i=0; i<num; i++ )
+ body[i] = switch( alloc._ptr._obj._fields[i]._type ) {
+ case TypeInteger ti -> 0L;
+ case TypeFloat tf -> 0;
+ default -> null;
+ };
}
Object[] mems = new Object[type._fields.length+2];
// mems[0] is control
@@ -342,7 +346,7 @@ public class Evaluator {
assert block != null;
for (; i < block.nodes().length; i++) {
if (!(block.nodes()[i] instanceof PhiNode phi)) break;
- var val = region instanceof FunNode fun && "main".equals(fun.sig()._name) && ((ParmNode)phi)._idx==2 && exit==1
+ var val = region instanceof FunNode fun && "main".equals(fun._name) && ((ParmNode)phi)._idx==2 && exit==1
? parameter
: val(phi.in(exit));
phiCache.add(val);
diff --git a/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java b/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java
index 52d8f3e3..4bfa7628 100644
--- a/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java
+++ b/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java
@@ -508,7 +508,7 @@ public class Scheduler {
private static CFGNode findSingleCFGOut(Node node) {
if (node instanceof StartNode) {
for(var n:node._outputs)
- if (n instanceof FunNode fun && "main".equals(fun.sig()._name) )
+ if (n instanceof FunNode fun && "main".equals(fun._name) )
return fun;
return null;
}
diff --git a/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java b/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java
index f57a0031..f7e0c4ad 100644
--- a/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java
+++ b/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, false);
+ code1 = FuzzerUtils.parse(script, 123);
} catch (RuntimeException e1) {
try {
- FuzzerUtils.parse(script, true);
+ FuzzerUtils.parse(script, 456);
} 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, true);
+ CodeGen code2 = FuzzerUtils.parse(script, 456);
checkGraphs(code1, code2, 0);
checkGraphs(code1, code2, 1);
checkGraphs(code1, code2, 10);
@@ -126,17 +126,16 @@ public class Fuzzer {
var code = new CodeGen(sb.toString());
code.parse();
- int parse_peeps= Node.ITER_CNT;
- int parse_nops = Node.ITER_NOP_CNT;
+ int nids = code.UID();
+ if( nids <= max_nids ) return max_nids; // Smaller, looking for trends as we grow
+ int parse_peeps= code._iter_cnt;
+ int parse_nops = code._iter_nop_cnt;
double parse_nop_ratio = (double)parse_nops/parse_peeps;
- int nids = Node.UID();
- if( nids <= max_nids ) return max_nids;
-
double parse_peeps_per_node = (double)parse_peeps/nids;
code.opto();
- int iter_peeps= Node.ITER_CNT;
- int iter_nops = Node.ITER_NOP_CNT;
+ int iter_peeps= code._iter_cnt;
+ int iter_nops = code._iter_nop_cnt;
double iter_nop_ratio = (double)iter_nops/iter_peeps;
double iter_peeps_per_node = (double)iter_peeps/nids;
diff --git a/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java b/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java
index 62a149a8..0781ad67 100644
--- a/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java
+++ b/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java
@@ -4,6 +4,7 @@ import com.seaofnodes.simple.CodeGen;
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.node.Node;
import com.seaofnodes.simple.node.StopNode;
+import com.seaofnodes.simple.type.TypeInteger;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.invoke.MethodHandle;
@@ -47,31 +48,10 @@ class FuzzerUtils {
}
/**
- * Copy of Node.WVISIST
- * Used to clear as exceptions might happen in the walk and left this bitset not cleared
- */
- private static final BitSet NodeWalkVisit;
-
- /**
- * Write access to Iterate.MID_ASSERT
- * Exception could happen mid assert and left this at true. Used to reset to false prior to parsing.
- */
- private static final MethodHandle set_MID_ASSERT;
-
- /**
* Some problems might trigger debug output. Suppress this output with a null print stream during fuzzing.
*/
public static final PrintStream NULL_PRINT_STREAM = new PrintStream(OutputStream.nullOutputStream());
- static {
- try {
- NodeWalkVisit = getFieldValue(Node.class, "WVISIT");
- set_MID_ASSERT = MethodHandles.lookup().unreflectSetter(getField( IterPeeps.class, "MID_ASSERT"));
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
/**
* Check that the messages are similar.
*/
@@ -114,21 +94,15 @@ class FuzzerUtils {
/**
* Parse script with peepholes enabled or disabled
*/
- public static CodeGen parse(String script, boolean runPeeps) {
+ public static CodeGen parse(String script, long workListSeed) {
var err = System.err;
var out = System.out;
try {
System.setErr(NULL_PRINT_STREAM);
System.setOut(NULL_PRINT_STREAM);
- try {
- set_MID_ASSERT.invokeExact(false);
- } catch (Throwable e) {
- throw rethrow(e);
- }
- var code = new CodeGen(script);
- return code.parse(!runPeeps).opto().typeCheck().GCM().localSched();
+ var code = new CodeGen(script, TypeInteger.BOT, workListSeed);
+ return code.parse().opto().typeCheck().GCM().localSched();
} finally {
- NodeWalkVisit.clear();
System.setErr(err);
System.setOut(out);
}
diff --git a/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java b/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java
index 86dbe66a..f119fa1a 100644
--- a/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java
+++ b/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java
@@ -3,12 +3,13 @@ package com.seaofnodes.simple.fuzzer;
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.node.ScopeNode;
import com.seaofnodes.simple.type.TypeInteger;
-
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.function.Predicate;
+import static com.seaofnodes.simple.Parser.KEYWORDS;
+
/**
* Generate a pseudo random script.
@@ -34,18 +35,6 @@ public class ScriptGenerator {
* Valid characters for identifiers. The last 10 are not valid for the first character.
*/
private static final String VAR_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789";
- /**
- * List of keywords not valid for identifiers.
- */
- private static final HashSet<String> KEYWORDS;
-
- static {
- try {
- KEYWORDS = FuzzerUtils.getFieldValue(new Parser(""), "KEYWORDS");
- } catch (Throwable e) {
- throw new ExceptionInInitializerError(e);
- }
- }
/**
* Flag for a statement that it does not pass on control flow to the next statement.
@@ -108,7 +97,6 @@ public class ScriptGenerator {
private static final List<TypeInt> INTTYPES = new ArrayList<>();
static {
- new Parser("", TypeInteger.BOT);
for( var e : Parser.defaultTypes().entrySet() ) {
if( e.getValue() instanceof TypeInteger ) {
INTTYPES.add(new TypeInt(e.getKey()));
diff --git a/src/test/java/com/seaofnodes/simple/progs/fcn.smp b/src/test/java/com/seaofnodes/simple/progs/fcn.smp
new file mode 100644
index 00000000..188e0a9f
--- /dev/null
+++ b/src/test/java/com/seaofnodes/simple/progs/fcn.smp
@@ -0,0 +1,15 @@
+
+struct Person {
+ int age;
+};
+
+val fcn = { Person?[] ps, int x ->
+ val tmp = ps[x];
+ if( ps[x] )
+ ps[x].age++;
+};
+
+Person?[] !ps = new Person?[2];
+ps[0] = new Person;
+ps[1] = new Person;
+fcn(ps,1);
diff --git a/src/test/java/com/seaofnodes/simple/progs/fcn2.smp b/src/test/java/com/seaofnodes/simple/progs/fcn2.smp
new file mode 100644
index 00000000..049132d9
--- /dev/null
+++ b/src/test/java/com/seaofnodes/simple/progs/fcn2.smp
@@ -0,0 +1,5 @@
+
+val fcn = (arg&1)
+ ? { int x -> x*x; }
+ : { int x -> x+x; };
+fcn(arg);
diff --git a/src/test/java/com/seaofnodes/simple/progs/fcn3.smp b/src/test/java/com/seaofnodes/simple/progs/fcn3.smp
new file mode 100644
index 00000000..a64564f0
--- /dev/null
+++ b/src/test/java/com/seaofnodes/simple/progs/fcn3.smp
@@ -0,0 +1,42 @@
+
+//val fact = { int n -> n <= 1 ? 1 : fact(n-1)*n; }
+struct LL { LL? next; int payload; };
+
+
+struct String {
+
+ val _hashCodeString = { ->
+ int hash=0;
+ for( int i=0; i< cs#; i++ )
+ hash = hash*31 + cs[i];
+ if( !hash ) hash = 123456789;
+ return hash;
+ };
+
+ val equals = { String s ->
+ if( self == s ) return true;
+ if( cs# != s.cs# ) return false;
+ for( int i=0; i< #; i++ )
+ if( [i] != s.cs[i] )
+ return false;
+ return true;
+ };
+
+ int _hashCode = hash();
+ u8[] cs;
+};
+
+
+
+val hashCode= { String self ->
+ int hash = self._hashCode
+ ? self._hashCode
+ : self._hashCode = _hashCodeString(self);
+ return hash;
+};
+
+
+String s = new String { cs = new u8[17]; };
+s.cs[0] = 67; // C
+s.cs[1] = 108; // l
+hashCode(s);
diff --git a/src/test/java/com/seaofnodes/simple/progs/sieve.smp b/src/test/java/com/seaofnodes/simple/progs/sieve.smp
new file mode 100644
index 00000000..0788e6c5
--- /dev/null
+++ b/src/test/java/com/seaofnodes/simple/progs/sieve.smp
@@ -0,0 +1,32 @@
+
+int[] !ary = new int[arg], !primes = new int[arg];
+int nprimes = 0, p=2;
+// Find primes while p^2 < arg
+while( p*p < arg ) {
+ // skip marked non-primes
+ while( ary[p]==1 ) p = p + 1;
+ // p is now a prime
+ primes[nprimes] = p; nprimes = nprimes + 1;
+ // Mark out the rest non-primes
+ int i = p + p;
+ while( i < ary# ) {
+ ary[i] = 1;
+ i = i + p;
+ }
+ p = p + 1;
+}
+// Now just collect the remaining primes, no more marking
+while( p < arg ) {
+ if( ary[p] == 0 ) {
+ primes[nprimes] = p; nprimes = nprimes + 1;
+ }
+ p = p + 1;
+}
+// Copy/shrink the result array
+int[] !rez = new int[nprimes];
+int j = 0;
+while( j < nprimes ) {
+ rez[j] = primes[j];
+ j = j + 1;
+}
+return rez;