don't heap allocate in io.printf

This commit is contained in:
2026-03-14 11:44:14 +01:00
parent 4a60c1fc12
commit 3f9df4a32f
3 changed files with 39 additions and 31 deletions

View File

@@ -14,7 +14,15 @@ pub struct Analyzer {
impl Analyzer {
pub fn new() -> Analyzer {
Analyzer {
functions: HashMap::new(),
functions: HashMap::from([
("_builtin_heap_head".into(), -1),
("_builtin_heap_tail".into(), -1),
("_builtin_read64".into(), -1),
("_builtin_set64".into(), -1),
("_builtin_syscall".into(), -1),
("io.printf".into(), -1),
("_builtin_environ".into(), -1),
]),
constants: HashMap::new(),
structs: HashMap::new(),
}
@@ -160,22 +168,16 @@ impl Analyzer {
args,
} => {
if let Expr::Variable(callee_name) = *callee.clone() {
if callee_name.lexeme.starts_with("_builtin_")
|| self.functions.contains_key(&callee_name.lexeme)
{
if self.functions.contains_key(&callee_name.lexeme) {
// its a function (defined/builtin/extern)
if let Some(arity) = self.functions.get(&callee_name.lexeme) {
if *arity >= 0
&& *arity != args.len() as i32
&& callee_name.lexeme != "io.printf"
// TODO: disgusting hack
{
if *arity >= 0 && *arity != args.len() as i32 {
return error!(
&paren.loc,
format!("expected {} arguments, got {}", arity, args.len())
);
}
} else if !callee_name.lexeme.starts_with("_builtin_") {
} else {
return error!(
&paren.loc,
format!("undefined function: {}", callee_name.lexeme)

View File

@@ -142,6 +142,21 @@ _builtin_syscall:
mov r9, [rsp+8]
syscall
ret
section .text.io.printf
io.printf:
push rbp
mov rbp, rsp
sub rsp, 48
mov [rsp], rsi
mov [rsp + 8], rdx
mov [rsp + 16], rcx
mov [rsp + 24], r8
mov [rsp + 32], r9
lea rsi, [rsp]
call io._printf_impl
leave
ret
"
);
@@ -650,9 +665,7 @@ _builtin_environ:
}
if let Expr::Variable(callee_name) = &**callee {
if callee_name.lexeme.starts_with("_builtin_")
|| self.analyzer.functions.contains_key(&callee_name.lexeme)
{
if self.analyzer.functions.contains_key(&callee_name.lexeme) {
// its a function (defined/builtin/extern)
emit!(&mut self.output, " call {}", callee_name.lexeme);
} else {

View File

@@ -186,36 +186,29 @@ func mem.write32[x: ptr, d: i64] : void
func mem.write64[x: ptr, d: i64] : void
_builtin_set64(x, d)
// TODO: we don't have variadics so we manually skip arity checking in the analyzer
func io.printf[s: str, a1: any, a2: any, a3: any, a4: any, a5: any] : void
// TODO: we really shouldn't heap allocate to print something
let args: Array = [a1, a2, a3, a4, a5]
let arg_idx: i64 = 0
func io._printf_impl[s: str, args: ptr] : void
while s[0]
if s[0] == '%'
s = s + 1
if s[0] == 'd'
io.print_i64(array.nth(args, arg_idx))
arg_idx = arg_idx + 1
io.print_i64(mem.read64(args))
args = args + 8
else if s[0] == 'x'
io.print_i64_hex(array.nth(args, arg_idx))
arg_idx = arg_idx + 1
io.print_i64_hex(mem.read64(args))
args = args + 8
else if s[0] == 's'
io.print(array.nth(args, arg_idx))
arg_idx = arg_idx + 1
else if (s[0] == 'c')
io.print_char(array.nth(args, arg_idx))
arg_idx = arg_idx + 1
else if (s[0] == '%')
io.print(mem.read64(args))
args = args + 8
else if s[0] == 'c'
io.print_char(mem.read64(args))
args = args + 8
else if s[0] == '%'
io.print_char('%')
else
io.print_char(s[0])
s = s + 1
array.free(args)
func io.print_sized[x: str, size: i64] : void
_builtin_syscall(SYS_write, 1, x, size)