summaryrefslogtreecommitdiff
path: root/chapter25/src/main/smp/sys
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-08-20 10:56:30 -0700
committerCliff Click <cliffc@acm.org>2026-08-20 10:56:30 -0700
commit3568f3deed586327f885ac98b73d07ae3ade6e57 (patch)
treefce7865468dc9e2beabeb68342f23bfea5bdae1a /chapter25/src/main/smp/sys
parent1cb8279a64f4f79615ac8358927b11237df29bf2 (diff)
downloadSimple-3568f3deed586327f885ac98b73d07ae3ade6e57.tar.gz
Simple-3568f3deed586327f885ac98b73d07ae3ade6e57.zip
Squashed commit of the following:
commit c05d7df4f9c90984d2c04126772be3fee1d81fd1 Author: Cliff Click <cliffc@acm.org> Date: Thu Aug 20 10:52:58 2026 -0700 Fix local frefs, deferred inlining, and sys FileIO support - Defer non-trivial inlining out of CallEnd idealization and run it from IterPeeps after normal peepholes reach a fixed point. - Keep forward refs local to their lexical scope, promote them outward on scope pop, and track created FRefNodes directly for dependency discovery. - Preserve loop scope shape when frefs are first seen inside loop bodies. - Treat frefs as final constants from creation and force lazy self lookups before implicit calls. - Reset imported pointer/struct types conservatively for post-parse Iter. - Pin Start-owned global machine value chains and clone global constants per function during GCM. - Improve late ASM printing before encoding and namespace constant-pool symbols. - Add optional regalloc function-local edge verifier and improve empty-mask splitting for multi-def/fixed-register LRGs. - Add sys array compare, safer array copy bounds, libc open/creat/close/unlink bindings, aryu8.str0, and higher-level sys.io file operations. - Add docs/examples/FileIO.smp and a Chapter25 FileIO test. - Update spill/code-size goldens after the allocator and scheduling changes. commit ef5316979732ac118612d310b75923c8f59ecdc1 Author: Cliff Click <cliffc@acm.org> Date: Fri Aug 14 16:29:56 2026 -0700 Dijkstra uses bitset. TestC.exec for repeated test runs with different stdins. Support &= and |= op-update forms. commit 728a527587f19bb49860f02ae5ac5968ab01ae33 Author: Cliff Click <cliffc@acm.org> Date: Fri Aug 14 12:13:28 2026 -0700 Fix live demo commit e4c069b9ef2cbfafe28d8edfcbff55396cde085e Author: Cliff Click <cliffc@acm.org> Date: Fri Aug 14 09:52:24 2026 -0700 Update Dijkstra.smp commit b8015739b4056e3f7a715a030e846a441021a9f1 Author: Cliff Click <cliffc@acm.org> Date: Fri Aug 14 09:41:17 2026 -0700 Better looking Dijkstra commit 7cce587804c6169b24829e0b5bdc10be94357a31 Author: Cliff Click <cliffc@acm.org> Date: Fri Aug 14 09:33:33 2026 -0700 Fix CmpMemX86 encoding Use sys.aryu8 for number printing commit 310b5d8c9978a3b09622a4b89dac97f0e5e6f3fb Author: Cliff Click <cliffc@acm.org> Date: Fri Aug 14 09:04:58 2026 -0700 Progress dijlstra Fix NotX86 encoding. Allow Not-sinking through Phis; the Nots both take Scalar and might take different types (ptr vs int). Better guard installing during && || opers. Drop the csv parse flavor in sys lib. commit 5917d5322521dd5e762c4698d34e5d7ac9b3a37f Author: Cliff Click <cliffc@acm.org> Date: Thu Aug 13 14:44:12 2026 -0700 missed commit da35ad4d8a330559a21c04ae6326536e0fd62c48 Author: Cliff Click <cliffc@acm.org> Date: Thu Aug 13 14:43:42 2026 -0700 Major cleanup of allocation All the graph-gen is moved to the <ctor> declaration and not at the alloc site. commit c4223216099ccbc526d282bb263972532d48c5b2 Author: Cliff Click <cliffc@acm.org> Date: Thu Aug 13 13:26:01 2026 -0700 Some work from Dykstra (more coming) commit a03bc567f61dc7e4355e453ee4be16ac2528d1ab Author: Cliff Click <cliffc@acm.org> Date: Thu Aug 13 09:32:55 2026 -0700 Spill correctness and improvements Had the callee-save pick-risky backwards vs cloneables. commit 2d306e4430225f916cb7fb999f4926e52f6fb70a Author: Cliff Click <cliffc@acm.org> Date: Wed Aug 12 19:40:04 2026 -0700 Tighter parser handling of missing fields Bug fix add libc.errno, read can return -1, sys.ary exists commit b7eeefda4cafa1e86153170dca6f13d45ef63f69 Author: Cliff Click <cliffc@acm.org> Date: Wed Aug 12 16:22:48 2026 -0700 Printer improvements commit 8b9112226f1d2d1c843b080eecefe0d5ddc1f8cf Author: Cliff Click <cliffc@acm.org> Date: Wed Aug 12 15:30:46 2026 -0700 Remove GLB commit ae566f5c610b9c30831906d3f024901d8930a227 Author: Cliff Click <cliffc@acm.org> Date: Wed Aug 12 14:38:51 2026 -0700 Add Capitalize example Rename Ary to ary. Fix bug || carrying state along. Fix bug load-array removing control. Add sys.char tolower/upper
Diffstat (limited to 'chapter25/src/main/smp/sys')
-rw-r--r--chapter25/src/main/smp/sys/Ary.smp10
-rw-r--r--chapter25/src/main/smp/sys/adt.smp4
-rw-r--r--chapter25/src/main/smp/sys/adt/bitset.smp58
-rw-r--r--chapter25/src/main/smp/sys/ary.smp25
-rw-r--r--chapter25/src/main/smp/sys/aryi64.smp26
-rw-r--r--chapter25/src/main/smp/sys/aryu8.smp38
-rw-r--r--chapter25/src/main/smp/sys/char.smp9
-rw-r--r--chapter25/src/main/smp/sys/io.smp65
-rw-r--r--chapter25/src/main/smp/sys/libc.smp28
-rw-r--r--chapter25/src/main/smp/sys/scan.smp (renamed from chapter25/src/main/smp/sys/Scan.smp)8
10 files changed, 218 insertions, 53 deletions
diff --git a/chapter25/src/main/smp/sys/Ary.smp b/chapter25/src/main/smp/sys/Ary.smp
deleted file mode 100644
index 0f667695..00000000
--- a/chapter25/src/main/smp/sys/Ary.smp
+++ /dev/null
@@ -1,10 +0,0 @@
-// -*- mode: java; -*-
-
-// Array utilities
-
-// Copy byte array contents
-val copy = { u8[] dst, int doff, u8[~] src, int soff, int len ->
- for( int i=0; i<len; i++ )
- dst[i+doff] = src[i+soff];
- return dst;
-};
diff --git a/chapter25/src/main/smp/sys/adt.smp b/chapter25/src/main/smp/sys/adt.smp
new file mode 100644
index 00000000..efdad395
--- /dev/null
+++ b/chapter25/src/main/smp/sys/adt.smp
@@ -0,0 +1,4 @@
+// -*- mode: java; -*-
+
+// Abstract data types.
+val bitset = bitset;
diff --git a/chapter25/src/main/smp/sys/adt/bitset.smp b/chapter25/src/main/smp/sys/adt/bitset.smp
new file mode 100644
index 00000000..f56f1cce
--- /dev/null
+++ b/chapter25/src/main/smp/sys/adt/bitset.smp
@@ -0,0 +1,58 @@
+// -*- mode: java; -*-
+
+// A set of non-negative integers, represented one bit per value.
+struct bitset {
+ i64[] !_bits;
+
+ new bitset = { ->
+ _bits = new i64[1];
+ };
+
+ // Return 0 for missing, non-zero for true
+ val get = { int bit ->
+ if( (bit >> 6) >= _bits# ) return false;
+ i64 mask = 1 << (bit & 63);
+ return (_bits[bit >> 6] & mask);
+ };
+
+ val _grow = { int bit ->
+ int x = bit >> 6;
+ int len = _bits#;
+ if( x < len ) return self;
+ while( x >= len ) len *= 2;
+ var bits = new i64[len];
+ for( int i=0; i<_bits#; i++ )
+ bits[i] = _bits[i];
+ _bits = bits;
+ return self;
+ };
+
+ // Set
+ val set = { int bit ->
+ i64 mask = 1 << (bit & 63);
+ _grow(bit)._bits[bit >> 6] |= mask;
+ return self;
+ };
+
+ // Test and set
+ val tset = { int bit ->
+ int idx = bit >> 6;
+ i64 mask = 1 << (bit & 63);
+ if( _grow(bit)._bits[idx] & mask )
+ return true; // Already set
+ _bits[idx] |= mask;
+ return false; // Was false (and now set)
+ };
+
+ val clr = { int bit ->
+ if( (bit >> 6) >= _bits# ) return self;
+ i64 mask = 1 << (bit & 63);
+ _bits[bit >> 6] &= (mask ^ -1);
+ return self;
+ };
+
+ val clear = { ->
+ for( int i=0; i<_bits#; i++ ) _bits[i] = 0;
+ return self;
+ };
+};
diff --git a/chapter25/src/main/smp/sys/ary.smp b/chapter25/src/main/smp/sys/ary.smp
new file mode 100644
index 00000000..feade0f5
--- /dev/null
+++ b/chapter25/src/main/smp/sys/ary.smp
@@ -0,0 +1,25 @@
+// -*- mode: java; -*-
+
+// Array utilities
+
+// Copy byte array contents. Copies the shorter of the buffers and len
+val copy = { u8[] dst, int doff, u8[~] src, int soff, int len ->
+ if( len > dst# - doff ) len = dst# - doff;
+ if( len > src# - soff ) len = src# - soff;
+ for( int i=0; i<len; i++ )
+ dst[i+doff] = src[i+soff];
+ return dst;
+};
+
+// Compare lexigraphically array contents. Compares up to shorter array or
+// len. Returns <0 or >0 for first non-matching byte. Returns <0 or >0 for
+// the larger array after that, or 0 if both arrays are fully equal.
+val cmp = { u8[~] src1, u32 off1, u8[~] src2, u32 off2, u32 len ->
+ u32 len1 = len > src1# - off1 ? src1# - off1 : len;
+ u32 len2 = len > src2# - off2 ? src2# - off2 : len;
+ u32 max = len1 > len2 ? len2 : len1;
+ for( int i=0; i<max; i++ )
+ if( src1[off1+i] != src2[off2+i] )
+ return src1[off1+i] - src2[off2+i]; // Bytes determine compare
+ return len1 - len2; // Length determines compare
+};
diff --git a/chapter25/src/main/smp/sys/aryi64.smp b/chapter25/src/main/smp/sys/aryi64.smp
index c2bc394f..e4c39ac3 100644
--- a/chapter25/src/main/smp/sys/aryi64.smp
+++ b/chapter25/src/main/smp/sys/aryi64.smp
@@ -27,21 +27,16 @@ struct aryi64 {
self;
};
- // Write to aryu8
+ val get = { int index -> return buf[index]; };
+
+ // Write the bracketed array-list form to aryu8.
val str = { ->
// TODO: clunky default constructor syntax
- var str = new aryu8(new u8[1]).add('[');
- for( int i=0; i<len; i++ )
- str.num(buf[i]).add(',').add(' ');
- str.undo(2).add(']');
- };
-
- // Comma-separated form used by command-line examples.
- val csv = { ->
- var str = new aryu8(new u8[1]);
+ var str = new aryu8().add('[');
for( int i=0; i<len; i++ )
str.num(buf[i]).add(',').add(' ');
- str.undo(2).add('\n');
+ if( len ) str.undo(2);
+ return str.add(']');
};
val swap = { int i, int j ->
@@ -53,12 +48,13 @@ struct aryi64 {
};
+
// Parse a comma-separated list of numbers, wrapped with square brackets,
// with optional whitespace e.g. "[ -17, 0,99,12456789 ] ".
// parseAryI64 & aryi64.str are bijections modulo whitespace.
// Returns null if the parse failed, without giving a clue as to why.
val parseAryI64 = { u8[~] str ->
- Scan !s = new Scan(str);
+ scan !s = new scan(str);
if( !s.match('[') ) return null;
// Array of parsed results
var nums = new aryi64(new i64[1]);
@@ -79,3 +75,9 @@ val parseAryI64 = { u8[~] str ->
s.skip();
return s.x == s.buf# ? nums : null;
};
+
+val copy = { i64[] dst, int doff, i64[~] src, int soff, int len ->
+ for( int i=0; i<len; i++ )
+ dst[i+doff] = src[i+soff];
+ return dst;
+};
diff --git a/chapter25/src/main/smp/sys/aryu8.smp b/chapter25/src/main/smp/sys/aryu8.smp
index 0ce4bd23..186a45a3 100644
--- a/chapter25/src/main/smp/sys/aryu8.smp
+++ b/chapter25/src/main/smp/sys/aryu8.smp
@@ -5,9 +5,7 @@ struct aryu8 {
u32 !len = 0;
u8[] !buf;
- new aryu8 = { u8[] b ->
- buf = b;
- };
+ new aryu8 = { -> buf = new u8[1]; };
// Grow as needed
val _grow = { int len2 ->
@@ -15,7 +13,7 @@ struct aryu8 {
int newlen = buf# * 2;
while( len+len2 >= newlen ) newlen *= 2;
u8[] !buf2 = new u8[newlen];
- Ary.copy(buf2,0,buf,0,buf#);
+ ary.copy(buf2,0,buf,0,buf#);
buf = buf2;
self;
};
@@ -29,10 +27,10 @@ struct aryu8 {
};
// Add all of a plain array to the aryu8
- val addAry = { u8[~] ary ->
- _grow(ary#);
- Ary.copy(buf,len,ary,0,ary#);
- len += ary#;
+ val addAry = { u8[~] xs ->
+ _grow(xs#);
+ ary.copy(buf,len,xs,0,xs#);
+ len += xs#;
self;
};
@@ -64,3 +62,27 @@ struct aryu8 {
libc.write(fd,ptr,len);
};
};
+
+
+// Parse one integer, ignore trailing data; returns 0 with an empty string.
+// If you want a more robust parsing, use the `scan` class
+val atoi = { u8[~] str ->
+ int x = 0;
+ while( x < str# && str[x] <= ' ' ) x++;
+ if( x == str# ) return 0;
+ bool neg = false;
+ if( str[x]=='-' ) { neg=true; x++; }
+ i64 n = 0;
+ while( x < str# && '0' <= str[x] <= '9' )
+ n = n*10 + str[x++]-'0';
+ return neg ? -n : n;
+};
+
+// Zero-terminate string for libc strings. No error checking, just copies and
+// appends a zero.
+{ u8[~] -> u8[] } str0 = { u8[~] str ->
+ u8[] !strz = new u8[str#+1];
+ ary.copy(strz,0,str,0,str#);
+ strz[str#] = '\0';
+ strz;
+};
diff --git a/chapter25/src/main/smp/sys/char.smp b/chapter25/src/main/smp/sys/char.smp
new file mode 100644
index 00000000..de37968e
--- /dev/null
+++ b/chapter25/src/main/smp/sys/char.smp
@@ -0,0 +1,9 @@
+// -*- mode: java; -*-
+
+val toupper = { u8 c ->
+ return c >= 'a' && c <= 'z' ? c - ('a' - 'A') : c;
+};
+
+val tolower = { u8 c ->
+ return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;
+};
diff --git a/chapter25/src/main/smp/sys/io.smp b/chapter25/src/main/smp/sys/io.smp
index b94e89fa..3d6be512 100644
--- a/chapter25/src/main/smp/sys/io.smp
+++ b/chapter25/src/main/smp/sys/io.smp
@@ -3,30 +3,63 @@
// Simple I/O Library
// Write byte array to stdout
-val p = { u8[~] str ->
- i64 ptr = str; // cast array base to i64
- return libc.write(1,ptr,str#);
-};
-
-val p_noInline = { u8[~] str ->
- i64 ptr = str; // cast array base to i64
- return libc.write(1,ptr,str#);
-};
+val p = { u8[~] str -> write(1,str); };
+val p_noInline = { u8[~] str -> write(1,str); };
-// Return stdin as a u8[].
-val stdin = { ->
+// Return fd contents as a u8[].
+val read = { i32 fd ->
var buf = new u8[8*1024];
i64 ptr = buf;
int len = 0;
while( true ) {
- int rez = libc.read(0,ptr,buf#);
- if( rez < 0 ) libc._exit(libc.errno);
+ i32 rez = libc.read(fd,ptr,buf#);
+ if( rez > buf# ) libc._exit(libc.errno);
len += rez;
if( rez < buf# )
break;
libc._exit(-2); // Need to implement for more than 8K input
}
- // Compress
- var dst = new u8[len];
- return Ary.copy(dst,0,buf,0,len);
+ var out = new u8[len];
+ ary.copy(out,0,buf,0,len);
+};
+
+// Write all of str to fd.
+val write = { i32 fd, u8[~] str ->
+ i64 ptr = str; // Convert array pointer to a i64 for the native call
+ libc.write(fd,ptr,str#);
+};
+
+// Write all of str to fd.
+val writeOff = { i32 fd, u8[~] str, u32 off, u32 len ->
+ i64 ptr = str; // Convert array pointer to a i64 for the native call
+ ptr += off; // Skip offset
+ // Cap at available length
+ if( len > str# - off ) len = str# - off;
+ // Do the write
+ libc.write(fd,ptr,len);
+};
+
+// Return stdin as a u8[].
+val stdin = { -> read(0); };
+
+// Create file for writing. Return fd, or -1 and errno has the error code
+val create = { u8[~] str ->
+ i64 ptr = sys.aryu8.str0(str);
+ i32 perms = 6*64 + 6*8 + 6; // 0666
+ return libc.creat(ptr, perms);
+};
+
+// Open file for reading. Return fd, or -1 and errno has the error code
+val open = { u8[~] str ->
+ i64 ptr = sys.aryu8.str0(str);
+ return libc.open(ptr, sys.libc.O_RDONLY, 0);
+};
+
+// Close an open fd. Return 0, or -1 and errno has the error code
+val close = { i32 fd -> return libc.close(fd); };
+
+// Remove a file. Return 0, or -1 and errno has the error code
+val remove = { u8[~] str ->
+ i64 ptr = sys.aryu8.str0(str);
+ return libc.unlink(ptr);
};
diff --git a/chapter25/src/main/smp/sys/libc.smp b/chapter25/src/main/smp/sys/libc.smp
index 42fc7313..6d750f7b 100644
--- a/chapter25/src/main/smp/sys/libc.smp
+++ b/chapter25/src/main/smp/sys/libc.smp
@@ -3,12 +3,36 @@
// libc bindings:
// https://www.man7.org/linux/man-pages/man2/<libc call>.2.html
+// The buffers are int-versions of zero-terminated strings.
+// int buf = aryu8.str0("some_file");
+// buf mode perm-> fd
+{ i64 i32 i32 -> i32 } open = "C";
+// buf perm -> fd
+{ i64 i32 -> i32 } creat = "C";
+
// fd buf len -> len
-{ i32 i64 u32 -> u32 } write = "C";
+{ i32 i64 u32 -> i32 } write = "C";
// fd buf len -> len
-{ i32 i64 u32 -> u32 } read = "C";
+{ i32 i64 u32 -> i32 } read = "C";
+// fd -> err
+{ i32 -> i32 } close = "C";
+// path -> err
+{ i64 -> i32 } unlink = "C";
+
+i32 O_RDONLY = 0;
+i32 O_WRONLY = 1;
+i32 O_RDWR = 2;
+i32 O_CREAT = 512; // 02000 on x86_64-pc-cygwin
+i32 O_TRUNC = 1024; // 04000 on x86_64-pc-cygwin
+
+i32 STDIN = 0;
+i32 STDOUT = 1;
+i32 STDERR = 2;
+
// status
{ i32 -> i32 } _exit = "C";
+// Error return from many native calls
+i32 errno = "C";
// addr len prot flags fd off -> void*
{ i64 i64 i32 i32 i32 i32 -> i64 } mmap = "C";
// mmap flags
diff --git a/chapter25/src/main/smp/sys/Scan.smp b/chapter25/src/main/smp/sys/scan.smp
index acf9fbb8..ba91003e 100644
--- a/chapter25/src/main/smp/sys/Scan.smp
+++ b/chapter25/src/main/smp/sys/scan.smp
@@ -1,14 +1,12 @@
// -*- mode: java; -*-
// Scanner; a simple string parser.
-struct Scan {
+struct scan {
int !x; // Cursor
bool !bad; // True after a malformed token
- u8[~] buf; // Immutable byte array, must be set in 2nd constructor
+ u8[~] buf; // Buffer to parse
- new Scan = { u8[~] b ->
- buf = b;
- };
+ new scan = { u8[~] b -> buf = b; };
// Skip whitespace
val skip = { ->