diff options
| author | Cliff Click <cliffc@acm.org> | 2026-09-28 13:30:22 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2026-09-28 13:30:22 -0700 |
| commit | 586c8f65f2d0c0e1f73aadd0aa8d850aa653bddd (patch) | |
| tree | 2f539c308452ddf5fa37826da95b17ba557e8352 /chapter25/src/test/java/com | |
| parent | 8212a66ff27e56531e0b48807088f1c544d75756 (diff) | |
| download | Simple-586c8f65f2d0c0e1f73aadd0aa8d850aa653bddd.tar.gz Simple-586c8f65f2d0c0e1f73aadd0aa8d850aa653bddd.zip | |
Support extern C ver direct updates
FIx minor RISC encodings.
Diffstat (limited to 'chapter25/src/test/java/com')
5 files changed, 130 insertions, 6 deletions
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java index 41225097..bde25ab7 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java @@ -21,6 +21,87 @@ import org.junit.Test; import static org.junit.Assert.*; public class Chapter25Test { + @Test + public void testExternData() throws IOException { + String src = """ + i32 counter="C"; + i8 small="C"; + f64 fraction="C"; + {int} bump="C"; + val test_global={ -> + val before=counter; + counter=before; + counter=++counter+1; + counter+=1; + val mid=bump(); + small++; + fraction=fraction+0.5; + return before*10000+mid*100+counter; + }; + """; + TestC.runC(src,"extern_data","",-1); + } + + @Test + public void testExternDataEncoding() { + for( String cpu : new String[]{"arm","riscv"} ) { + CodeGen code = new CheckedCodeGen("i32 counter=\"C\"; counter=counter+3; return counter;"); + // Exercise signed low-12 relocation arithmetic, past the first page. + int addr = 0x3800; + code._externDataAddresses.put("counter",addr); + code.driver(cpu,"SystemV",true,false); + byte[] image = new byte[1<<20]; + var bits = code._encoding._bits; + System.arraycopy(bits.buf(),0,image,0,bits.size()); + if( cpu.equals("arm") ) { + EvalArm64 arm = new EvalArm64(image,1<<16); + arm.st4(addr,-7); + assertEquals(0,arm.step(1000)); + assertEquals(-4,arm.regs[0]); + assertEquals(-4,arm.ld4s(addr)); + } else { + EvalRisc5 r5 = new EvalRisc5(image,1<<16); + r5.st4(addr,-7); + assertEquals(0,r5.step(1000)); + assertEquals(-4,r5.regs[10]); + assertEquals(-4,r5.ld4s(addr)); + } + } + } + + @Test + public void testExternDataImports() throws IOException { + Path dir = Files.createTempDirectory(Path.of("build/objs"),"extern_data_"); + String globals = "i32 counter=\"C\"; val read={ -> counter; };"; + CodeGen globalCode = new CodeGen(null,dir.toString(),null,"Globals",globals,126,true,TypeInteger.BOT) + .driver(TestC.CPU_PORT,TestC.CALL_CONVENTION,false,false); + var clz = globalCode.compunit()._clz; + int counter = clz.find("counter"); + assertTrue(clz._fields[counter]._extern); + assertEquals(-1,clz.offset(counter)); + assertEquals(clz.remove(counter).size(),clz.size()); + // Load the serialized declaration and ideal graph from Globals.o. + String src = """ + i32 counter="C"; + val test_global={ -> + val before=Globals.counter; + Globals.counter=before+1; + counter+=2; + return before*100+Globals.read(); + }; + """; + Ary<String> paths = new Ary<>(new String[]{dir.toString()}); + for( boolean imported : new boolean[]{true,false} ) { + Path root = dir.resolve(imported ? "binary" : "source"); + Files.createDirectories(root.resolve("Main")); + if( !imported ) Files.writeString(root.resolve("Main/Globals.smp"),globals); + new CodeGen(root.toString(),root.toString(),imported ? paths : null,"Main",src,126,true,TypeInteger.BOT) + .driver(TestC.CPU_PORT,TestC.CALL_CONVENTION,false,false); + assertEquals("",TestC.gcc(root+"/Main.o","",TestC.C_DRIVERS_DIR+"extern_data_import.c", + (String)null,new Ary<>(new String[]{dir+"/Globals.o"}),root+"/main"+(TestC.OS.startsWith("Windows") ? ".exe" : ""))); + } + } + @Test public void testPrintingConstantPool() throws Exception { com.seaofnodes.simple.codegen.PrintRegTestSupport.checkConstantPool(); } @@ -312,6 +393,13 @@ return rez < buf# ? 0 : sys.libc._exit(-2); } @Test + public void testErrnoAccessor() throws IOException { + String src = "sys.libc.close(-1); return sys.libc.errno()==0;"; + TestC.run(src,"errnoAccessor",new Ary<>(new String[]{SYS_BLDDIR}), + TestC.CALL_CONVENTION,null,null,"",-1); + } + + @Test public void testBubbles() throws IOException { String src = Files.readString( Path.of("docs/examples/BubbleSort.smp")); String exe = TestC.compile(src,"BubbleSort",new Ary<>(new String[]{SYS_BLDDIR}), diff --git a/chapter25/src/test/java/com/seaofnodes/simple/EvalRisc5.java b/chapter25/src/test/java/com/seaofnodes/simple/EvalRisc5.java index a4cc7044..633e931e 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/EvalRisc5.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/EvalRisc5.java @@ -252,7 +252,7 @@ public class EvalRisc5 { case 2 -> (rs1 < rs2) ? 1 : 0; case 3 -> (rs1 < rs2) ? 1 : 0; case 4 -> rs1 ^ rs2; - case 5 -> (ir & 0x40000000) != 0 ? (rs1 >>> (rs2 & 0x3F)) : (rs1 >> (rs2 & 0x3F)); + case 5 -> (ir & 0x40000000) != 0 ? (rs1 >> (rs2 & 0x3F)) : (rs1 >>> (rs2 & 0x3F)); case 6 -> rs1 | rs2; case 7 -> rs1 & rs2; default -> rval; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/progs/extern_data.c b/chapter25/src/test/java/com/seaofnodes/simple/progs/extern_data.c new file mode 100644 index 00000000..9325f65e --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/progs/extern_data.c @@ -0,0 +1,22 @@ +#include <stdint.h> +#include <stdio.h> + +int32_t counter=7; +int8_t small=-3; +double fraction=1.25; + +int64_t bump(void) { counter+=5; return counter; } +__attribute__((CALL_CONV)) extern int64_t test_global(void); + +int main(void) { + int64_t result=test_global(); + if(result!=71515 || counter!=15 || small!=-2 || fraction!=1.75) { + printf("result=%lld counter=%d small=%d fraction=%g\n", + (long long)result,counter,small,fraction); + return 1; + } + // A second call must observe C's new values, not a Simple initialization copy. + counter=-2; + result=test_global(); + return result!=-19394 || counter!=6 || small!=-1 || fraction!=2.25; +} diff --git a/chapter25/src/test/java/com/seaofnodes/simple/progs/extern_data_import.c b/chapter25/src/test/java/com/seaofnodes/simple/progs/extern_data_import.c new file mode 100644 index 00000000..f65e5c84 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/progs/extern_data_import.c @@ -0,0 +1,14 @@ +#include <stdint.h> +#include <stdio.h> + +int32_t counter=7; +__attribute__((CALL_CONV)) extern int64_t test_global(void); + +int main(void) { + int64_t result=test_global(); + if(result!=710 || counter!=10) { + printf("result=%lld counter=%d\n",(long long)result,counter); + return 1; + } + return 0; +} diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/README.md b/chapter25/src/test/java/com/seaofnodes/simple/spill/README.md index fae44126..6c78d46f 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/spill/README.md +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/README.md @@ -27,11 +27,11 @@ Chapter 25 cannot parse all earlier sources unchanged. Adaptations are explicit: All entries replay **through RegAlloc**, checking scheduled register constraints. The historical phase column is provenance, not a promise to run those old native -harnesses in Chapter 25. In particular, the adapted Bubble Sort still exposes a -pre-existing ARM extern-data encoding limitation (`i32 errno="C"; return 0;` is -sufficient to reproduce it). Allocation succeeds; ARM encoding does not. That -separate failure remains in the backport queue. Do not count this corpus as -historical runtime coverage. +harnesses in Chapter 25. The adapted Bubble Sort retains its historical +`i32 errno="C"` declaration for allocation comparability. Direct data bindings +now encode on all three targets, but this declaration cannot link to a libc +whose errno is thread-local or accessor-based. Current system-library code uses +`libc.errno()` instead. Do not count this corpus as historical runtime coverage. `SpillStats` then compiles the current system library through encoding at seed 456, and runs Chapter25Test with its existing seeds and native checks. Together |
