summaryrefslogtreecommitdiff
path: root/chapter28b/src/test
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-10-29 10:53:23 -0700
committerCliff Click <cliffc@acm.org>2026-10-29 10:53:23 -0700
commitf47c7d1ffcd044b74620715072e8721b91819b61 (patch)
treee0eea89e23c4903823b12c581ab8dcb3b977fd54 /chapter28b/src/test
parentf7fcac0ac9ebfc11549272fa8c166c26e5418e3f (diff)
downloadSimple-f47c7d1ffcd044b74620715072e8721b91819b61.tar.gz
Simple-f47c7d1ffcd044b74620715072e8721b91819b61.zip
Removing hook between encode and export
Diffstat (limited to 'chapter28b/src/test')
-rw-r--r--chapter28b/src/test/java/com/seaofnodes/simple/PhaseTest.java59
1 files changed, 59 insertions, 0 deletions
diff --git a/chapter28b/src/test/java/com/seaofnodes/simple/PhaseTest.java b/chapter28b/src/test/java/com/seaofnodes/simple/PhaseTest.java
index f2d09c7c..6505009d 100644
--- a/chapter28b/src/test/java/com/seaofnodes/simple/PhaseTest.java
+++ b/chapter28b/src/test/java/com/seaofnodes/simple/PhaseTest.java
@@ -4,6 +4,10 @@ import com.seaofnodes.graph.GraphObserver;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.codegen.CodeGen.Phase;
import com.seaofnodes.simple.node.Node;
+import com.seaofnodes.simple.node.FunNode;
+import com.seaofnodes.simple.type.TypeInteger;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.ArrayList;
import org.junit.Test;
import static org.junit.Assert.*;
@@ -71,11 +75,19 @@ public class PhaseTest {
assertEquals(Phase.Serialize,code._phase);
code.driver(Phase.Encoding,"riscv","SystemV");
assertNotNull(code._serial);
+ assertNotNull(code._encoding);
CodeGen memory = new CodeGen(SRC).driver("riscv","SystemV",true,false);
assertNull(memory._serial);
assertEquals(Phase.Export,memory._phase);
+ // Keeping ideal IR must not force separate images when the caller
+ // explicitly requests in-memory linking.
+ CodeGen saved = new CodeGen(SRC).driver(Phase.Serialize);
+ saved.driver("riscv","SystemV",true,false);
+ assertNotNull(saved._serial);
+ assertArrayEquals(memory._encoding._bits.toByteArray(),saved._encoding._bits.toByteArray());
+
CodeGen late = new CodeGen(SRC).driver(Phase.Encoding,"riscv","SystemV");
try {
late.exportELF(false,false);
@@ -84,4 +96,51 @@ public class PhaseTest {
assertTrue(expected.getMessage().contains("Serialize before Lower"));
}
}
+
+ @Test public void testStagedObjectExport() throws Exception {
+ Path root = Files.createTempDirectory(Files.createDirectories(Path.of("build/objs")),"phase-export-");
+ Path src = Files.createDirectories(root.resolve("src"));
+ Files.createDirectories(src.resolve("Main"));
+ Files.writeString(src.resolve("Main.smp"),"val run_noInline = { int n -> Helper.twice_noInline(n)+1; };");
+ Files.writeString(src.resolve("Main/Helper.smp"),"val twice_noInline = { int n -> n*2; };");
+ Path cfile = root.resolve("driver.c");
+ Files.writeString(cfile,"""
+ __attribute__((CALL_CONV)) extern long long run_noInline(long long);
+ int main(void) { return run_noInline(20)!=41 || run_noInline(-3)!=-5; }
+ """);
+ for( boolean direct : new boolean[]{false,true} ) {
+ Path obj = Files.createDirectories(root.resolve(direct ? "direct" : "driver"));
+ CodeGen code = new CodeGen(src.toString(),obj.toString(),null,"Main",null,123,true,TypeInteger.BOT)
+ .driver(Phase.Serialize);
+ if( direct ) {
+ code.driver(Phase.RegAlloc,TestC.CPU_PORT,TestC.CALL_CONVENTION);
+ code.encode();
+ } else {
+ code.driver(Phase.Encoding,TestC.CPU_PORT,TestC.CALL_CONVENTION);
+ }
+ // Encoding has already separated the entry object's code from
+ // its dependency. Export only writes the prepared encodings.
+ assertNotNull(code._encoding);
+ for( var block : code._encoding._cfg )
+ if( block instanceof FunNode fun )
+ assertSame(code._compunits.get("Main"),fun._compunit);
+ assertFalse(Files.exists(obj.resolve("Main.o")));
+ if( direct ) code.exportELF(false,false);
+ else code.driver(TestC.CPU_PORT,TestC.CALL_CONVENTION,false,false);
+ assertTrue(Files.exists(obj.resolve("Main.o")));
+ assertTrue(Files.exists(obj.resolve("Main/Helper.o")));
+ String exe = obj.resolve(TestC.OS.startsWith("Windows") ? "run.exe" : "run").toString();
+ assertEquals("",TestC.gcc(code,TestC.CALL_CONVENTION.equals("win64") ? "ms_abi" : "sysv_abi",
+ cfile.toString(),null,exe));
+ }
+ // The same serialized units can instead form one linked memory image.
+ CodeGen memory = new CodeGen(src.toString(),root.resolve("memory").toString(),null,
+ "Main",null,123,true,TypeInteger.BOT).driver(Phase.Serialize);
+ memory.driver("riscv","SystemV",true,false);
+ boolean helper = false;
+ for( var block : memory._encoding._cfg )
+ if( block instanceof FunNode fun && fun._compunit==memory._compunits.get("Main/Helper") )
+ helper = true;
+ assertTrue("The combined image includes dependency bodies",helper);
+ }
}