don't heap allocate in io.printf
This commit is contained in:
@@ -14,7 +14,15 @@ pub struct Analyzer {
|
|||||||
impl Analyzer {
|
impl Analyzer {
|
||||||
pub fn new() -> Analyzer {
|
pub fn new() -> Analyzer {
|
||||||
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(),
|
constants: HashMap::new(),
|
||||||
structs: HashMap::new(),
|
structs: HashMap::new(),
|
||||||
}
|
}
|
||||||
@@ -160,22 +168,16 @@ impl Analyzer {
|
|||||||
args,
|
args,
|
||||||
} => {
|
} => {
|
||||||
if let Expr::Variable(callee_name) = *callee.clone() {
|
if let Expr::Variable(callee_name) = *callee.clone() {
|
||||||
if callee_name.lexeme.starts_with("_builtin_")
|
if self.functions.contains_key(&callee_name.lexeme) {
|
||||||
|| self.functions.contains_key(&callee_name.lexeme)
|
|
||||||
{
|
|
||||||
// its a function (defined/builtin/extern)
|
// its a function (defined/builtin/extern)
|
||||||
if let Some(arity) = self.functions.get(&callee_name.lexeme) {
|
if let Some(arity) = self.functions.get(&callee_name.lexeme) {
|
||||||
if *arity >= 0
|
if *arity >= 0 && *arity != args.len() as i32 {
|
||||||
&& *arity != args.len() as i32
|
|
||||||
&& callee_name.lexeme != "io.printf"
|
|
||||||
// TODO: disgusting hack
|
|
||||||
{
|
|
||||||
return error!(
|
return error!(
|
||||||
&paren.loc,
|
&paren.loc,
|
||||||
format!("expected {} arguments, got {}", arity, args.len())
|
format!("expected {} arguments, got {}", arity, args.len())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if !callee_name.lexeme.starts_with("_builtin_") {
|
} else {
|
||||||
return error!(
|
return error!(
|
||||||
&paren.loc,
|
&paren.loc,
|
||||||
format!("undefined function: {}", callee_name.lexeme)
|
format!("undefined function: {}", callee_name.lexeme)
|
||||||
|
|||||||
@@ -142,6 +142,21 @@ _builtin_syscall:
|
|||||||
mov r9, [rsp+8]
|
mov r9, [rsp+8]
|
||||||
syscall
|
syscall
|
||||||
ret
|
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 let Expr::Variable(callee_name) = &**callee {
|
||||||
if callee_name.lexeme.starts_with("_builtin_")
|
if self.analyzer.functions.contains_key(&callee_name.lexeme) {
|
||||||
|| self.analyzer.functions.contains_key(&callee_name.lexeme)
|
|
||||||
{
|
|
||||||
// its a function (defined/builtin/extern)
|
// its a function (defined/builtin/extern)
|
||||||
emit!(&mut self.output, " call {}", callee_name.lexeme);
|
emit!(&mut self.output, " call {}", callee_name.lexeme);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -186,36 +186,29 @@ func mem.write32[x: ptr, d: i64] : void
|
|||||||
func mem.write64[x: ptr, d: i64] : void
|
func mem.write64[x: ptr, d: i64] : void
|
||||||
_builtin_set64(x, d)
|
_builtin_set64(x, d)
|
||||||
|
|
||||||
// TODO: we don't have variadics so we manually skip arity checking in the analyzer
|
func io._printf_impl[s: str, args: ptr] : void
|
||||||
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
|
|
||||||
|
|
||||||
while s[0]
|
while s[0]
|
||||||
if s[0] == '%'
|
if s[0] == '%'
|
||||||
s = s + 1
|
s = s + 1
|
||||||
|
|
||||||
if s[0] == 'd'
|
if s[0] == 'd'
|
||||||
io.print_i64(array.nth(args, arg_idx))
|
io.print_i64(mem.read64(args))
|
||||||
arg_idx = arg_idx + 1
|
args = args + 8
|
||||||
else if s[0] == 'x'
|
else if s[0] == 'x'
|
||||||
io.print_i64_hex(array.nth(args, arg_idx))
|
io.print_i64_hex(mem.read64(args))
|
||||||
arg_idx = arg_idx + 1
|
args = args + 8
|
||||||
else if s[0] == 's'
|
else if s[0] == 's'
|
||||||
io.print(array.nth(args, arg_idx))
|
io.print(mem.read64(args))
|
||||||
arg_idx = arg_idx + 1
|
args = args + 8
|
||||||
else if (s[0] == 'c')
|
else if s[0] == 'c'
|
||||||
io.print_char(array.nth(args, arg_idx))
|
io.print_char(mem.read64(args))
|
||||||
arg_idx = arg_idx + 1
|
args = args + 8
|
||||||
else if (s[0] == '%')
|
else if s[0] == '%'
|
||||||
io.print_char('%')
|
io.print_char('%')
|
||||||
else
|
else
|
||||||
io.print_char(s[0])
|
io.print_char(s[0])
|
||||||
s = s + 1
|
s = s + 1
|
||||||
|
|
||||||
array.free(args)
|
|
||||||
|
|
||||||
func io.print_sized[x: str, size: i64] : void
|
func io.print_sized[x: str, size: i64] : void
|
||||||
_builtin_syscall(SYS_write, 1, x, size)
|
_builtin_syscall(SYS_write, 1, x, size)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user