From 31b71a5e19b336d99badf61cb1b8e2267613182d Mon Sep 17 00:00:00 2001 From: Toni Date: Sat, 30 May 2026 21:01:01 +0200 Subject: [PATCH] _stackalloc --- examples/chip8.zr | 2 +- examples/puzzles/aoc2024_04.zr | 2 +- examples/puzzles/aoc2025_03.zr | 2 +- examples/tcp_server.zr | 2 +- src/codegen_x86_64.rs | 11 ++++++++ src/std/net.zr | 16 +++++------- src/std/std.zr | 47 +++++++++++++++++----------------- src/symbol_table.rs | 1 + 8 files changed, 46 insertions(+), 37 deletions(-) diff --git a/examples/chip8.zr b/examples/chip8.zr index 871a732..32f1e5a 100644 --- a/examples/chip8.zr +++ b/examples/chip8.zr @@ -36,7 +36,7 @@ func chip8_create[] : CHIP8 fonts := [0xf0, 0x90, 0x90, 0x90, 0xf0, 0x20, 0x60, 0x20, 0x20, 0x70, 0xf0, 0x10, 0xf0, 0x80, 0xf0, 0xf0, 0x10, 0xf0, 0x10, 0xf0, 0x90, 0x90, 0xf0, 0x10, 0x10, 0xf0, 0x80, 0xf0, 0x10, 0xf0, 0xf0, 0x80, 0xf0, 0x90, 0xf0, 0xf0, 0x10, 0x20, 0x40, 0x40, 0xf0, 0x90, 0xf0, 0x90, 0xf0, 0xf0, 0x90, 0xf0, 0x10, 0xf0, 0xf0, 0x90, 0xf0, 0x90, 0x90, 0xe0, 0x90, 0xe0, 0x90, 0xe0, 0xf0, 0x80, 0x80, 0x80, 0xf0, 0xe0, 0x90, 0x90, 0x90, 0xe0, 0xf0, 0x80, 0xf0, 0x80, 0xf0, 0xf0, 0x80, 0xf0, 0x80, 0x80] for i in 0..80 c->memory[i] = array.nth(fonts, i) - mem.free(fonts) + array.free(fonts) c->pc = 0x200 diff --git a/examples/puzzles/aoc2024_04.zr b/examples/puzzles/aoc2024_04.zr index 4d5fbea..536256f 100644 --- a/examples/puzzles/aoc2024_04.zr +++ b/examples/puzzles/aoc2024_04.zr @@ -43,7 +43,7 @@ func part2[lines: Array] : void for x in 1..lines->size-1 for y in 1..str.len(array.nth(lines, x))-1 if array.nth(lines, x)[y] == 'A' - s := mem.alloc(5) as str + s := _stackalloc(5) as str s[0] = array.nth(lines, x - 1)[y - 1] s[1] = array.nth(lines, x + 1)[y - 1] s[2] = array.nth(lines, x + 1)[y + 1] diff --git a/examples/puzzles/aoc2025_03.zr b/examples/puzzles/aoc2025_03.zr index e756798..5c4d2b2 100644 --- a/examples/puzzles/aoc2025_03.zr +++ b/examples/puzzles/aoc2025_03.zr @@ -7,7 +7,7 @@ func part1[lines: Array] : void largest := 0 for j in 0..str.len(line) for k in (j+1)..str.len(line) - s := mem.alloc(3) as str + s := _stackalloc(3) as str s[0] = line[j] s[1] = line[k] s[2] = 0 diff --git a/examples/tcp_server.zr b/examples/tcp_server.zr index 1c22de3..5372d07 100644 --- a/examples/tcp_server.zr +++ b/examples/tcp_server.zr @@ -6,7 +6,7 @@ func main[] : i64 io.println("Listening on port 8000...") resp := mem.alloc(60000) - addr := mem.alloc(16) + addr := _stackalloc(16) while true conn := net.accept(s, addr) if conn < 0 diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index 80bd322..9a88f14 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -645,6 +645,17 @@ _builtin_environ: return self.emit_var_arg(env, &args[0]); } + if let ExprKind::Variable(callee_name) = &callee.kind + && callee_name.lexeme == "_stackalloc" + { + self.compile_expr(env, &args[0])?; + emit!(&mut self.output, " add rax, 15"); + emit!(&mut self.output, " and rax, -16"); + emit!(&mut self.output, " sub rsp, rax"); + emit!(&mut self.output, " mov rax, rsp"); + return Ok(()); + } + for arg in args { self.compile_expr(env, arg)?; emit!(&mut self.output, " push rax"); diff --git a/src/std/net.zr b/src/std/net.zr index 4aac2e3..7cc5397 100644 --- a/src/std/net.zr +++ b/src/std/net.zr @@ -4,6 +4,10 @@ const SOCK_DGRAM = 2 const SOL_SOCKET = 1 const SO_REUSEADDR = 2 +const DNS_TYPE_A = 1 +const DNS_CLASS_IN = 1 +const DNS_RECURSION_DESIRED = 256 + func net.listen[packed_host: i64, port: i64] : i64, bool s := _builtin_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0) if s < 0 @@ -14,7 +18,7 @@ func net.listen[packed_host: i64, port: i64] : i64, bool _builtin_syscall(SYS_close, s) return -1, false - sa := mem.alloc(16) + sa := _stackalloc(16) mem.zero(sa, 16) sa[0] = 2 sa[1] = 0 @@ -27,9 +31,7 @@ func net.listen[packed_host: i64, port: i64] : i64, bool if _builtin_syscall(SYS_bind, s, sa, 16) < 0 _builtin_syscall(SYS_close, s) - mem.free(sa) return -1, false - mem.free(sa) if _builtin_syscall(SYS_listen, s, 128) < 0 _builtin_syscall(SYS_close, s) @@ -42,7 +44,7 @@ func net.connect[packed_host: i64, port: i64] : i64, bool if s < 0 return -1, false - sa := mem.alloc(16) + sa := _stackalloc(16) mem.zero(sa, 16) sa[0] = AF_INET sa[1] = 0 @@ -54,11 +56,9 @@ func net.connect[packed_host: i64, port: i64] : i64, bool sa[7] = packed_host & 255 if _builtin_syscall(SYS_connect, s, sa, 16) < 0 - mem.free(sa) _builtin_syscall(SYS_close, s) return -1, false - mem.free(sa) return s, true func net.accept[s: i64, addr: ptr] : i64 @@ -140,10 +140,6 @@ func net.UDPSocket.close_and_free[s: net.UDPSocket] : void mem.free(s->addr) mem.free(s) -const DNS_TYPE_A = 1 -const DNS_CLASS_IN = 1 -const DNS_RECURSION_DESIRED = 256 - func net.encode_dns_name[domain: str] : Blob domain_len := str.len(domain) buf := Blob.alloc(domain_len + 2) diff --git a/src/std/std.zr b/src/std/std.zr index 5885faa..2ff4879 100644 --- a/src/std/std.zr +++ b/src/std/std.zr @@ -1,3 +1,16 @@ +const S_IFDIR = 0o040000 +const S_IFMT = 0o170000 +const PROT_READ = 1 +const PROT_WRITE = 2 +const MAP_PRIVATE = 2 +const MAP_ANONYMOUS = 32 +const O_RDONLY = 0 +const O_WRONLY = 1 +const O_CREAT = 64 +const O_TRUNC = 512 +const SEEK_SET = 0 +const SEEK_END = 2 + func panic[msg: str] : void io.print("PANIC: ") io.println(msg) @@ -36,10 +49,7 @@ func mem._request_space[size: i64] : mem.Block needed := size + MEM_BLOCK_SIZE alloc_size := (needed + 4095) & -4096 - // PROT_READ | PROT_WRITE = 3 - // MAP_PRIVATE | MAP_ANONYMOUS = 34 - // fd = -1, offset = 0 - blk := _builtin_syscall(SYS_mmap, 0, alloc_size, 3, 34, -1, 0) as mem.Block + blk := _builtin_syscall(SYS_mmap, 0, alloc_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) as mem.Block if (blk as ptr as i64) == -1 panic("mem._request_space: failed to mmap") @@ -310,29 +320,22 @@ func Blob.free[buf: Blob] : void func io.file_exists[path: str] : bool return _builtin_syscall(SYS_faccessat, -100, path, 0, 0) == 0 -const S_IFDIR = 0o040000 -const S_IFMT = 0o170000 - func io.is_a_directory[path: str] : bool - st := mem.alloc(256) // it has 21 mixed-size fields so no struct for now + st := _stackalloc(256) // it has 21 mixed-size fields so no struct for now rc := _builtin_syscall(SYS_newfstatat, -100, path, st, 0) if rc != 0 - mem.free(st) return false - out : bool = (mem.read32(st + 24) & S_IFMT) == S_IFDIR - - mem.free(st) - return out + return (mem.read32(st + 24) & S_IFMT) == S_IFDIR func io.read_text_file[path: str] : str, bool - fd := _builtin_syscall(SYS_openat, -100, path, 0, 0) + fd := _builtin_syscall(SYS_openat, -100, path, O_RDONLY, 0) if fd < 0 return 0 as str, false - size := _builtin_syscall(SYS_lseek, fd, 0, 2) - _builtin_syscall(SYS_lseek, fd, 0, 0) + size := _builtin_syscall(SYS_lseek, fd, 0, SEEK_END) + _builtin_syscall(SYS_lseek, fd, 0, SEEK_SET) buffer := mem.alloc(size + 1) n := _builtin_syscall(SYS_read, fd, buffer, size) @@ -369,7 +372,7 @@ func io.write_file[path: str, content: str] : bool return io.write_binary_file(path, content as ptr, str.len(content)) func io.write_binary_file[path: str, content: ptr, size: i64] : bool - fd := _builtin_syscall(SYS_openat, -100, path, 0x241, 0o644) + fd := _builtin_syscall(SYS_openat, -100, path, O_WRONLY|O_CREAT|O_TRUNC, 0o644) if fd < 0 return false @@ -533,7 +536,7 @@ func str.from_i64[n: i64] : str if n == -9223372036854775808 return str.make_copy("-9223372036854775808") n = -n - buf := mem.alloc(21) as str // enough to fit -MAX_I64 + buf := _stackalloc(21) as str // enough to fit -MAX_I64 end := 20 buf[end] = 0 end = end - 1 @@ -545,7 +548,6 @@ func str.from_i64[n: i64] : str buf[end] = '-' end = end - 1 s := str.make_copy((buf as ptr + end + 1) as str) - mem.free(buf) return s func str.hex_from_i64[n: i64] : str @@ -558,7 +560,7 @@ func str.hex_from_i64[n: i64] : str return out mask := (1 << 60) - 1 - buf := mem.alloc(17) as str + buf := _stackalloc(17) as str len := 0 while n != 0 @@ -573,7 +575,6 @@ func str.hex_from_i64[n: i64] : str j = j + 1 out[len] = 0 - mem.free(buf) return out func str.from_char[c: u8] : str @@ -928,7 +929,7 @@ func os.sleep[ms: i64] : void func os.urandom[n: i64]: ptr buffer := mem.alloc(n) - fd := _builtin_syscall(SYS_openat, -100, "/dev/urandom", 0, 0) + fd := _builtin_syscall(SYS_openat, -100, "/dev/urandom", O_RDONLY, 0) if fd < 0 panic("os.urandom: failed to open /dev/urandom") @@ -979,7 +980,7 @@ func os.run_shell_command[command: str] : i64, bool return -(st & 0x7f), true func os.list_directory[path: str] : Array, bool - fd := _builtin_syscall(SYS_openat, -100, path, 0, 0) + fd := _builtin_syscall(SYS_openat, -100, path, O_RDONLY, 0) if fd < 0 return 0 as Array, false diff --git a/src/symbol_table.rs b/src/symbol_table.rs index ccbbf2b..6b27bd2 100644 --- a/src/symbol_table.rs +++ b/src/symbol_table.rs @@ -54,6 +54,7 @@ impl SymbolTable { ("_builtin_syscall".into(), FnType::new_variadic("i64")), ("_builtin_environ".into(), FnType::new("ptr", vec![])), ("_var_arg".into(), FnType::new("any", vec!["i64"])), + ("_stackalloc".into(), FnType::new("ptr", vec!["i64"])), ]), constants: HashMap::new(), structs: HashMap::new(),