diff options
Diffstat (limited to 'chapter29/src/test/java/com/seaofnodes/simple/Chapter24Test.java')
| -rw-r--r-- | chapter29/src/test/java/com/seaofnodes/simple/Chapter24Test.java | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/chapter29/src/test/java/com/seaofnodes/simple/Chapter24Test.java b/chapter29/src/test/java/com/seaofnodes/simple/Chapter24Test.java new file mode 100644 index 00000000..2bc2ce7f --- /dev/null +++ b/chapter29/src/test/java/com/seaofnodes/simple/Chapter24Test.java @@ -0,0 +1,293 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.isa.eval.EvalRisc5; + +import com.seaofnodes.isa.eval.EvalArm64; + +import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.*; + + +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.node.cpus.riscv.riscv; +import java.io.IOException; +import org.junit.Ignore; +import org.junit.Test; +import static org.junit.Assert.*; + +public class Chapter24Test { + @Test public void testRecursiveWidening() { + String[] srcs = { + // Parm(x) must widen even though the recursive result is constant. + "val f = { int x, int limit -> x >= limit ? 0 : f(x+1,limit); }; return f(0,arg);", + // The growing result has its own cycle, which never crosses Parm(x). + "val f = { int x -> x <= 0 ? 0 : f(x-1)+1; }; return f(3);" + }; + for( int i=0; i<srcs.length; i++ ) + for( long seed : new long[]{0,42,126} ) { + var code = new CodeGen(srcs[i],seed,true).driver(CodeGen.Phase.LocalSched); + assertEquals(i==0 ? "0" : "3",Eval2.eval(code,3)); + } + } + + @Test public void testColdLoopSelfConflict() { com.seaofnodes.simple.codegen.RegAllocTestSupport.coldLoopSelfConflict(); } + + @Test public void testPrintingDeadFunction() throws Exception { + var code = new CodeGen("return 0;").parse(); + var tfp = TypeFunPtr.TEST; + var fun = new FunNode(null,tfp,"deadPrinterTarget",null); + org.junit.Assert.assertTrue(fun.isDead()); + code.link(fun); + var con = ConstantNode.raw(tfp); + var call = new CallNode(null,con,con,con); + con.toString(); + call.name(); + code.funcName(tfp.fidx()); + org.junit.Assert.assertSame(fun,code._link(tfp)); + // Optimizer lookup still performs its usual lazy cleanup. + org.junit.Assert.assertNull(code.link(tfp)); + org.junit.Assert.assertNull(code._link(tfp)); + } + + + @Ignore + @Test + public void testJig() throws IOException { + String src = "int v0=0; v0 = arg && 0== 0 !=0;"; + testCPU(src,"x86_64_v2", "win64" ,-1,null); + testCPU(src,"riscv" , "SystemV",-1,null); + testCPU(src,"arm" , "SystemV",-1,null); + } + + static CodeGen testCPU( String src, String cpu, String os, int spills, String stop ) { + CodeGen code = new CheckedCodeGen(src).driver(CodeGen.Phase.Encoding,cpu,os); + int delta = spills>>3; + if( delta==0 ) delta = 1; + if( spills != -1 && !CodeGen.iterSeedOverridden() ) + assertEquals("Expect spills:",spills,code._regAlloc._spillScaled,delta); + if( stop != null ) + assertEquals(stop, code.print()); + return code; + } + + // test it with function calls + @Test + public void testStack1() throws IOException { + String src =""" +int something_specific = 11; +return (10 < something_specific < 20) + ? 0 // Expected + : 1; // Error +"""; + TestC.runSF( src, "stacked_r_1", "", 0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build( src, "stacked_r_1", 0, 0, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_1", src, 0, 0, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(0,arm.regs[0]); + } + + @Test + public void testStack3() throws IOException { + String src =""" +var sq_noInline = { int x -> + x*x; +}; +int score = 4; +return (sq_noInline(2) <= score < sq_noInline(3)) + ? 0 // Expected + : 1; // Error +"""; + TestC.runSF( src, "stacked_r_3", "", 2); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build( src, "stacked_r_3", 0, 2, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_3", src, 0, 3, false); + int trap_1 = arm.step(100); + assertEquals(0,trap_1); + assertEquals(0,arm.regs[0]); + } + + @Test + public void testStack4() throws IOException { + String src =""" +int something_specific = 9; +return (10 < something_specific < 20) + ? 1 // Error + : 0; // Expected +"""; + + TestC.runSF( src, "stacked_r_4", "", 0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build( src, "stacked_r_4", 0, 0, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(0,R5.regs[riscv.A0]); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_4", src, 0, 0, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(0,arm.regs[0]); + } + + @Test + public void testStack6() { + try { new CodeGen("return 0 < arg > 1;" ).parse(); fail(); } + catch( RuntimeException e ) { assertEquals("Mixing relational directions in a chained relational test",e.getMessage()); } + } + + @Test + public void testStack9() throws IOException { + String src = "var stack9 = { int x -> (x < 1) == 1; };"; + String src2 = "return (0 < 1) == 1;"; + TestC.runC(src, "stacked_r_9x", "1", 0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build( src2, "stacked_r_9", 0, 0, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(1,R5.regs[riscv.A0]); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_9", src2, 0, 0, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(1,arm.regs[0]); + } + + @Test + public void testStack10() throws IOException { + String src ="var stack10 = { int x -> (x < 1) == (1>x);};"; + String src2 ="return (0 < 1) == (1>0);"; + TestC.runC(src, "stacked_r_10x", "1",0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build( src2, "stacked_r_10", 0, 0, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(1,R5.regs[riscv.A0]); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_10", src2,0, 0, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(1,arm.regs[0]); + } + + @Test + public void testStack11() throws IOException { + String src = "var stack11 = { int x -> 0 < x < x+1 < 4;}; "; + String src2 = "return 0 < arg < arg+1 < 4;"; + TestC.runC(src, "stacked_r_11x", "1", 2); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build( src2, "stacked_r_11", 1, 0, false); + R5.regs[riscv.A1] = 1; // Arg in A1, Test.class in A0 + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(1,R5.regs[riscv.A0]); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_11", src2, 1, 0, false); + arm.regs[1] = 1; // Arg in r1, Test.class in r0 + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(1,arm.regs[0]); + } + + // shows that it is parsed as + // ((0 != x) != 2) + @Test + public void testStack12() throws IOException { + String src = "var stack12 = { int x -> 0 != x != 2; };"; + String src2 = "return 0 != arg != 2;"; + TestC.runC(src, "stacked_r_12x", "1",0); + + // Evaluate on RISC5 emulator + EvalRisc5 R5 = TestRisc5.build( src2, "stacked_r_12", 1, 0, false); + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals(1,R5.regs[riscv.A0]); + + // Evaluate on ARM emulator + EvalArm64 arm = TestArm64.build("stacked_r_12", src2, 1, 0, false); + trap = arm.step(100); + assertEquals(0,trap); + assertEquals(1,arm.regs[0]); + } + + + // shows that it is parsed as + // ((0 == x) == 1) + @Test + public void testStack13() throws IOException { + String src = "var stack13 = { int x -> 0 == x == 1; };"; + String src2 = "return 0 == arg == 1;"; + TestC.runC(src, "stacked_r_13x", "1",0); + + // Compile once per target, then check false, true and negative inputs. + EvalRisc5 R5 = TestRisc5.build( src2, "stacked_r_13", 1, 0, false); + for( int arg : new int[]{-1,0,1} ) { + R5._pc = 0; + R5.regs[riscv.A1] = arg; + assertEquals(0,R5.step(100)); + assertEquals(arg==0 ? 1 : 0,R5.regs[riscv.A0]); + } + EvalArm64 arm = TestArm64.build("stacked_r_13", src2, 1, 0, false); + for( int arg : new int[]{-1,0,1} ) { + arm._pc = 0; + arm.regs[1] = arg; + assertEquals(0,arm.step(100)); + assertEquals(arg==0 ? 1 : 0,arm.regs[0]); + } + } + + @Test + public void testSCCP0() { + String src = +""" +int x = 1; +int cnt = 5; +while (cnt) { + cnt -= 1; + if (x == 0) { + x += 1; + } +} +return x; +"""; + CodeGen code = new CodeGen(src).driver(CodeGen.Phase.TypeCheck); + assertEquals("return 1;", code.print()); + } + + @Test + public void testSCCP1() { + String src = +""" +int x = 1; +int cnt = 5; +while( cnt-- ) + if( x == 1 ) + x = 2-x; +return x; +"""; + CodeGen code = new CodeGen(src).driver(CodeGen.Phase.TypeCheck); + assertEquals("return 1;", code.print()); + } + +} |
