calculate needed stack space with a disgusting hack

This commit is contained in:
2026-06-05 20:24:50 +02:00
parent be42267a59
commit a6d44ec5e0
5 changed files with 28 additions and 26 deletions

View File

@@ -12,8 +12,6 @@ struct Var {
pub var_type: String,
}
const STACK_SIZE: usize = 256; // TODO: eww
pub struct Env {
scopes: Vec<HashMap<String, Var>>,
next_offset: usize,
@@ -173,9 +171,8 @@ _start:
mov [rax], rdx
; align stack
and rsp, -16
; main()
; exit(main())
call main
; exit
mov rdi, rax
mov rax, 60
syscall
@@ -354,8 +351,9 @@ _builtin_environ:
emit!(&mut self.output, "{}:", name.lexeme);
emit!(&mut self.output, " push rbp");
emit!(&mut self.output, " mov rbp, rsp");
let stack_size = (STACK_SIZE + 15) & !15;
emit!(&mut self.output, " sub rsp, {}", stack_size);
let prologue_offset = self.output.len();
emit!(&mut self.output, " sub rsp, {:<10}", 0);
match params {
Params::Normal(params) => {
@@ -399,6 +397,11 @@ _builtin_environ:
emit!(&mut self.output, " pop rbp");
emit!(&mut self.output, " ret");
}
// patch the stack size after we know how much we actually need
let patch = format!(" sub rsp, {:<10}", (env.next_offset + 15) & !15);
self.output
.replace_range(prologue_offset..prologue_offset + patch.len(), &patch);
}
Stmt::Return { keyword: _, exprs } => {
if exprs.len() == 2 {

View File

@@ -35,9 +35,9 @@ fn compile_file(args: Args) -> Result<(), ZernError> {
let mut statements = Vec::new();
if args.include_stdlib {
parse_std_file!(statements, "std/syscalls.zr");
parse_std_file!(statements, "std/std.zr");
parse_std_file!(statements, "std/net.zr");
parse_std_file!(statements, "std/linux_constants.zr");
}
let tokenizer = tokenizer::Tokenizer::new(filename.to_owned(), source);

View File

@@ -1,4 +1,16 @@
// https://github.com/torvalds/linux/blob/19272b37aa4f83ca52bdf9c16d5d81bdd1354494/arch/x86/entry/syscalls/syscall_64.tbl
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
const SYS_read = 0
const SYS_write = 1
const SYS_open = 2

View File

@@ -1,16 +1,3 @@
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)
@@ -26,7 +13,7 @@ struct mem.Block
next: mem.Block
prev: mem.Block
func mem._align[x: i64] : i64
func mem.align[x: i64] : i64
return (x + 7) & -8
func mem._split_block[blk: mem.Block, needed: i64] : void
@@ -70,7 +57,7 @@ func mem.alloc[size: i64] : ptr
if size <= 0
panic("mem.alloc: called with nonpositive size")
size = mem._align(size)
size = mem.align(size)
cur := mem.read64(_builtin_heap_head()) as mem.Block
while cur as ptr
@@ -145,7 +132,7 @@ func mem.realloc[x: ptr, new_size: i64] : ptr
mem.free(x)
return 0 as ptr
new_size = mem._align(new_size)
new_size = mem.align(new_size)
blk := (x - MEM_BLOCK_SIZE) as mem.Block
if blk->size >= new_size
@@ -1081,7 +1068,7 @@ func os.run_shell_command[command: str] : i64, bool
if pid == 0
argv := ["sh", "-c", command, 0] // gets freed after child process exits
_builtin_syscall(SYS_execve, "/bin/sh", argv->data, _builtin_environ())
_builtin_syscall(SYS_exit, 1)
os.exit(1)
else
status := 0
wp := _builtin_syscall(SYS_wait4, pid, ^status, 0, 0)