diff options
Diffstat (limited to 'chapter28a/src/test/java/com/seaofnodes')
4 files changed, 107 insertions, 0 deletions
diff --git a/chapter28a/src/test/java/com/seaofnodes/simple/IndirectCallTest.java b/chapter28a/src/test/java/com/seaofnodes/simple/IndirectCallTest.java new file mode 100644 index 00000000..e65ce3d1 --- /dev/null +++ b/chapter28a/src/test/java/com/seaofnodes/simple/IndirectCallTest.java @@ -0,0 +1,32 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.codegen.RegMask; +import com.seaofnodes.simple.codegen.IndirectCallTestSupport; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeFunPtr; +import org.junit.Test; +import static org.junit.Assert.*; + +public class IndirectCallTest { + @Test public void testTargetOperand() { + for( String cpu : new String[]{"x86_64_v2","riscv","arm"} ) { + CodeGen code = new CodeGen("return 0;").driver(CodeGen.Phase.Select,cpu,"SystemV"); + Node target = PhiNode.make("target",TypeFunPtr.BOT,code._start); + target._type = TypeFunPtr.BOT; + CallNode ideal = new CallNode(null,code._start,null,target); + CallNode call = (CallNode)code._mach.instSelect(ideal); + // The last input is the call target, not another argument. + assertEquals("callr",((MachNode)call).op()); + RegMask mask = ((MachNode)call).regmap(call.nIns()-1); + assertTrue(mask.test(5)); + assertTrue(mask.test(6)); + if( cpu.equals("arm") ) IndirectCallTestSupport.checkArmEncoding(code,call); + // Machine operands can lose their ideal type (e.g. a spill reload). + // The call still needs the original signature for argument masks. + target._type = Type.BOTTOM; + assertSame(TypeFunPtr.BOT,call.tfp()); + } + } +} diff --git a/chapter28a/src/test/java/com/seaofnodes/simple/ParseAllTest.java b/chapter28a/src/test/java/com/seaofnodes/simple/ParseAllTest.java new file mode 100644 index 00000000..f74ee7cd --- /dev/null +++ b/chapter28a/src/test/java/com/seaofnodes/simple/ParseAllTest.java @@ -0,0 +1,42 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.codegen.ParseAllTestSupport; +import com.seaofnodes.simple.type.TypeInteger; +import java.nio.file.Files; +import java.nio.file.Path; +import org.junit.Test; +import static org.junit.Assert.*; + +public class ParseAllTest { + @Test public void testTypeOnlyFileHasNoConstructor() throws Exception { + Path base = Path.of("build/objs"); + Files.createDirectories(base); + Path root = Files.createTempDirectory(base,"type-only-"); + Files.createDirectory(root.resolve("A")); + Files.writeString(root.resolve("A/B.smp"),"int x = 0;"); + for( String src : new String[]{ + "B? b = null; return 0;", + "val readB = { B b -> 0; }; return 0;"} ) { + Files.writeString(root.resolve("A.smp"),src); + CodeGen code = new CodeGen(root.toString(),root.resolve("obj").toString(), + "A",null,123,true,TypeInteger.BOT).driver(CodeGen.Phase.TypeCheck); + assertEquals("0",Eval2.eval(code,0)); + } + } + + @Test public void testRequiredTypesBelongToTheirSource() throws Exception { + Path base = Path.of("build/objs"); + Files.createDirectories(base); + Path root = Files.createTempDirectory(base,"required-types-"); + Files.createDirectory(root.resolve("App")); + Files.writeString(root.resolve("App.smp"),"val marker = 0;"); + Files.writeString(root.resolve("App/Main.smp"),"return A.x+C.y;"); + Files.writeString(root.resolve("App/A.smp"),"int x = 0; val readB = { B b -> b.x; };"); + Files.writeString(root.resolve("App/B.smp"),"int x = 0;"); + Files.writeString(root.resolve("App/C.smp"),"int y = 0;"); + CodeGen code = new CodeGen(root.toString(),root.resolve("obj").toString(), + "App/Main",null,123,true,TypeInteger.BOT).parse(); + ParseAllTestSupport.checkRequiredTypes(code); + } +} diff --git a/chapter28a/src/test/java/com/seaofnodes/simple/codegen/IndirectCallTestSupport.java b/chapter28a/src/test/java/com/seaofnodes/simple/codegen/IndirectCallTestSupport.java new file mode 100644 index 00000000..3c27036a --- /dev/null +++ b/chapter28a/src/test/java/com/seaofnodes/simple/codegen/IndirectCallTestSupport.java @@ -0,0 +1,17 @@ +package com.seaofnodes.simple.codegen; + +import com.seaofnodes.simple.node.*; +import static org.junit.Assert.*; + +public class IndirectCallTestSupport { + public static void checkArmEncoding(CodeGen code, CallNode call) { + Encoding enc = new Encoding(code) { + @Override public short reg(Node n) { + assertSame(call.fptr(),n); + return 7; + } + }; + ((MachNode)call).encoding(enc); + assertEquals(0xd63f00e0,enc.read4(0)); // BLR X7 + } +} diff --git a/chapter28a/src/test/java/com/seaofnodes/simple/codegen/ParseAllTestSupport.java b/chapter28a/src/test/java/com/seaofnodes/simple/codegen/ParseAllTestSupport.java new file mode 100644 index 00000000..2ce97a8e --- /dev/null +++ b/chapter28a/src/test/java/com/seaofnodes/simple/codegen/ParseAllTestSupport.java @@ -0,0 +1,16 @@ +package com.seaofnodes.simple.codegen; + +import static org.junit.Assert.*; + +public class ParseAllTestSupport { + public static void checkRequiredTypes(CodeGen code) { + CompUnit a = code._compunits.get("App/A"); + CompUnit b = code._compunits.get("App/B"); + CompUnit c = code._compunits.get("App/C"); + assertNotNull(b); + assertTrue(a._deps.find(b)!=-1); + // C was parsed after A, while B's layout was still unresolved. + // Only A used that layout; C must not inherit A's build dependency. + assertNull(c._deps); + } +} |
