diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index 13e5c9d..68aa3b8 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -106,7 +106,7 @@ section .text ); // take that rustfmt - for name in "syscall,malloc,realloc,free,snprintf,strtol,system,opendir,readdir,closedir,gettimeofday,send,write,read,close,getchar,gethostbyname".split(",") + for name in "malloc,realloc,free,snprintf,system,gettimeofday,send,write,read,close,getchar,gethostbyname".split(",") { emit!(&mut self.output, "extern {}", name); emit!(&mut self.output, "c.{} equ {}", name, name); @@ -121,6 +121,12 @@ _builtin_read8: mov al, byte [rdi] ret +section .text._builtin_read16 +_builtin_read16: + xor rax, rax + mov ax, word [rdi] + ret + section .text._builtin_read32 _builtin_read32: mov eax, dword [rdi] @@ -140,6 +146,18 @@ section .text._builtin_set64 _builtin_set64: mov [rdi], rsi ret + +section .text._builtin_syscall +_builtin_syscall: + mov rax, rdi + mov rdi, rsi + mov rsi, rdx + mov rdx, rcx + mov r10, r8 + mov r8, r9 + mov r9, [rsp+8] + syscall + ret " ); Ok(()) diff --git a/src/std.zr b/src/std.zr index e2c83e8..52461f8 100644 --- a/src/std.zr +++ b/src/std.zr @@ -16,6 +16,9 @@ func mem.zero[x: I64, size: I64] : Void func mem.read8[x: Ptr] : U8 return _builtin_read8(x) +func mem.read16[x: Ptr] : I64 + return _builtin_read16(x) + func mem.read32[x: Ptr] : I64 return _builtin_read32(x) @@ -29,7 +32,7 @@ func mem.write64[x: Ptr, d: I64] : Void _builtin_set64(x, d) func io.print[x: String] : Void - c.syscall(1, 1, x, str.len(x)) + _builtin_syscall(1, 1, x, str.len(x)) func io.println[x: String] : Void io.print(x) @@ -38,7 +41,7 @@ func io.println[x: String] : Void func io.print_char[x: U8] : Void let s: String = mem.alloc(1) str.set(s, 0, x) - c.syscall(1, 1, s, 1) + _builtin_syscall(1, 1, s, 1) mem.free(s) func io.print_i64[x: I64] : Void @@ -53,33 +56,33 @@ func io.println_i64[x: I64] : Void func io.read_stdin[]: String let buffer: String = mem.alloc(1025) - let n: I64 = c.syscall(0, 0, buffer, 1024) + let n: I64 = _builtin_syscall(0, 0, buffer, 1024) if n < 0 return "" str.set(buffer, n, 0) return buffer func io.read_file[path: String]: String - let fd: I64 = c.syscall(2, path, 0, 0) // open + let fd: I64 = _builtin_syscall(2, path, 0, 0) // open if fd <= 0 dbg.panic("failed to open file") - let size: I64 = c.syscall(8, fd, 0, 2) // lseek to the end - c.syscall(8, fd, 0, 0) // lseek back to start + let size: I64 = _builtin_syscall(8, fd, 0, 2) // lseek to the end + _builtin_syscall(8, fd, 0, 0) // lseek back to start let buffer: String = mem.alloc(size + 1) - let n: I64 = c.syscall(0, fd, buffer, size) // read + let n: I64 = _builtin_syscall(0, fd, buffer, size) // read str.set(buffer, n, 0) - c.syscall(3, fd) // close + _builtin_syscall(3, fd) // close return buffer func io.write_file[path: String, content: String] : Void - let fd: Ptr = c.syscall(2, path, 0x241, 0o644) // open + let fd: Ptr = _builtin_syscall(2, path, 0x241, 0o644) // open if fd < 0 dbg.panic("failed to open file") - c.syscall(1, fd, content, str.len(content)) // write - c.syscall(3, fd) // close + _builtin_syscall(1, fd, content, str.len(content)) // write + _builtin_syscall(3, fd) // close func str.len[s: String] : I64 let i: I64 = 0 @@ -195,7 +198,22 @@ func str.from_i64[n: I64] : String return x func str.parse_i64[s: String] : I64 - return c.strtol(s, 0, 0) + let len: I64 = str.len(s) + let i: I64 = 0 + + let sign: I64 = 1 + if i < len & s[i] == '-' + sign = -1 + i = i + 1 + + let num: I64 = 0 + while i < len + let d: U8 = s[i] + if d < '0' | d > '9' + break + num = num * 10 + (d - '0') + i = i + 1 + return num * sign func str.hex_encode[s: String] : String let hex_chars: String = "0123456789abcdef" @@ -297,9 +315,9 @@ func math.is_prime[n: I64]: Bool func math.urandom[]: I64 let buffer: Ptr = mem.alloc(8) - let fd: I64 = c.syscall(2, "/dev/urandom", 0, 0) // open - c.syscall(0, fd, buffer, 8) // read - c.syscall(3, fd) // close + let fd: I64 = _builtin_syscall(2, "/dev/urandom", 0, 0) // open + _builtin_syscall(0, fd, buffer, 8) // read + _builtin_syscall(3, fd) // close let n: I64 = mem.read64(buffer) mem.free(buffer) return n @@ -370,7 +388,7 @@ func alg._partition[arr: Array, low: I64, high: I64] : I64 return i + 1 func os.exit[code: I64] : Void - c.syscall(60, code) + _builtin_syscall(60, code) func os.time[] : I64 let tv: Ptr = mem.alloc(16) @@ -381,29 +399,40 @@ func os.time[] : I64 return seconds * 1000 + microseconds / 1000 func os.listdir[path: String] : Array - let dir: Ptr = c.opendir(path) - let files: Array = [] + let fd: I64 = _builtin_syscall(2, path, 0, 0) // open + if fd < 0 + return [] + let files: Array = [] + let buf: Ptr = mem.alloc(1024) while true - let entry: Ptr = c.readdir(dir) - if entry == 0 + let n: I64 = _builtin_syscall(217, fd, buf, 1024) // getdents64 + if n <= 0 break - let skip: Bool = false - if entry[19] == '.' - if entry[20] == 0 - skip = true - else if entry[20] == '.' - if entry[21] == 0 - skip = true + let pos: I64 = 0 + while pos < n + let len: I64 = mem.read16(buf + pos + 16) + let name: String = buf + pos + 19 + if name[0] + let skip: Bool = false + // skip if name is exactly '.' or '..' + if name[0] == '.' + if name[1] == 0 + skip = true + else if name[1] == '.' + if name[2] == 0 + skip = true + if !skip + array.push(files, str.copy(name)) + pos = pos + len - if !skip - array.push(files, str.copy(entry + 19)) - c.closedir(dir) + mem.free(buf) + _builtin_syscall(3, fd) // close return files func net.listen[port: I64] : I64 - let s: I64 = c.syscall(41, 2, 1, 0) // socket + let s: I64 = _builtin_syscall(41, 2, 1, 0) // socket if s < 0 return -1 @@ -414,13 +443,13 @@ func net.listen[port: I64] : I64 mem.write8(sa + 2, (port >> 8) & 255) mem.write8(sa + 3, port & 255) - if c.syscall(49, s, sa, 16) < 0 // bind - c.syscall(3, s) // close + if _builtin_syscall(49, s, sa, 16) < 0 // bind + _builtin_syscall(3, s) // close return -1 mem.free(sa) - if c.syscall(50, s, 1) < 0 // listen - c.syscall(3, s) // close + if _builtin_syscall(50, s, 1) < 0 // listen + _builtin_syscall(3, s) // close return -1 return s @@ -432,7 +461,7 @@ func net.connect[host: String, port: I64] : I64 let ip_ptr: Ptr = mem.read64(mem.read64(he + 24)) - let s: I64 = c.syscall(41, 2, 1, 0) // socket + let s: I64 = _builtin_syscall(41, 2, 1, 0) // socket if s < 0 return -1 @@ -446,9 +475,9 @@ func net.connect[host: String, port: I64] : I64 mem.write8(sa + 6, ip_ptr[2]) mem.write8(sa + 7, ip_ptr[3]) - if c.syscall(42, s, sa, 16) < 0 // connect + if _builtin_syscall(42, s, sa, 16) < 0 // connect mem.free(sa) - c.syscall(3, s) // close + _builtin_syscall(3, s) // close return -1 mem.free(sa)