From a93274d8ac62c831ee5baea077e7281302bcb9db Mon Sep 17 00:00:00 2001 From: Toni Date: Fri, 13 Jun 2025 14:16:02 +0200 Subject: [PATCH] strip unused functions, rc4, base64 --- examples/euler8.zr | 2 +- src/codegen_x86_64.rs | 38 +++++++++++++++++++- src/main.rs | 12 +++++-- src/std.zr | 82 ++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 125 insertions(+), 9 deletions(-) diff --git a/examples/euler8.zr b/examples/euler8.zr index 0cab906..2209be9 100644 --- a/examples/euler8.zr +++ b/examples/euler8.zr @@ -7,7 +7,7 @@ func main[] : I64 let s: I64 = 1 let j: I64 = 0 while j < 13 - s = s * Char.parse_i64(String.nth(n, i + j)) + s = s * U8.parse_i64(String.nth(n, i + j)) j = j + 1 if s > out out = s diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index aaff40c..b9bc8b7 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -59,7 +59,7 @@ macro_rules! emit { static REGISTERS: [&str; 6] = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"]; // TODO: currently they are all just 8 byte values -static TYPES: [&str; 6] = ["I64", "String", "Bool", "Ptr", "Char", "Array"]; +static TYPES: [&str; 6] = ["U8", "I64", "String", "Bool", "Ptr", "Array"]; pub struct CodegenX86_64 { output: String, @@ -127,14 +127,43 @@ extern closedir extern exit extern gettimeofday +section .text.Bit.lshift +Bit.lshift: + mov rcx, rsi + mov rax, rdi + shl rax, cl + ret + +section .text.Bit.rshift +Bit.rshift: + mov rcx, rsi + mov rax, rdi + sar rax, cl + ret + +section .text.Bit.and +Bit.and: + mov rax, rdi + and rax, rsi + ret + +section .text.Bit.or +Bit.or: + mov rax, rdi + or rax, rsi + ret + +section .text.String.nth String.nth: movzx rax, byte [rdi + rsi] ret +section .text.String.set String.set: mov [rdi + rsi], dl ret +section .text.OS.time OS.time: push rbx sub rsp, 16 @@ -152,6 +181,7 @@ OS.time: pop rbx ret +section .text.OS.listdir OS.listdir: push r14 push rbx @@ -193,16 +223,19 @@ OS.listdir: pop r14 ret +section .text.Array.nth Array.nth: mov rax, [rdi] mov rax, [rax + rsi*8] ret +section .text.Array.set Array.set: mov rax, [rdi] mov [rax + rsi*8], rdx ret +section .text.Array.push Array.push: push r14 push rbx @@ -231,10 +264,12 @@ Array.push: pop r14 ret +section .text.Array.size Array.size: mov rax, [rdi + 16] ret +section .text.Array.free Array.free: push rbx mov rbx, rdi @@ -315,6 +350,7 @@ Array.free: if name.lexeme == "main" { emit!(&mut self.output, "global {}", name.lexeme); } + emit!(&mut self.output, "section .text.{}", name.lexeme); emit!(&mut self.output, "{}:", name.lexeme); emit!(&mut self.output, " push rbp"); emit!(&mut self.output, " mov rbp, rsp"); diff --git a/src/main.rs b/src/main.rs index 46b6dd7..4cfc9f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -50,7 +50,7 @@ fn compile_file(path: String) -> Result<(), ZernError> { } if !Command::new("nasm") - .args(["-f", "elf64", "-w+all", "-o", "out.o", "out.s"]) + .args(["-f", "elf64", "-o", "out.o", "out.s"]) .status() .unwrap() .success() @@ -60,7 +60,15 @@ fn compile_file(path: String) -> Result<(), ZernError> { // TODO: drop libc entirely if !Command::new("./musl-1.2.4/root/bin/musl-gcc") - .args(["-static", "-o", "out", "out.o"]) + .args([ + "-static", + "-o", + "out", + "out.o", + "-flto", + "-Os", + "-Wl,--gc-sections", + ]) .status() .unwrap() .success() diff --git a/src/std.zr b/src/std.zr index a2f69ce..e4ede9c 100644 --- a/src/std.zr +++ b/src/std.zr @@ -11,7 +11,7 @@ func print_i64[x: I64] : I64 printf("%ld\n", x) return 0 -func String.is_whitespace[c: Char] : Bool +func String.is_whitespace[c: U8] : Bool return c == 10 || c == 32 || c == 13 || c == 9 func String.concat[a: String, b: String] : String @@ -20,6 +20,12 @@ func String.concat[a: String, b: String] : String strcat(c, b) return c +func String.find[s: String, needle: U8] : I64 + for i in 0:strlen(s) + if String.nth(s, i) == needle + return i + return -1 + func String.substr[s: String, start: I64, length: I64] : String let out: String = malloc(length + 1) strlcpy(out, s + start, length + 1) @@ -42,8 +48,7 @@ func String.rev[s: String] : String let out: String = malloc(len + 1) for i in 0:len - let c: Char = String.nth(s, len - i - 1) - String.set(out, i, c) + String.set(out, i, String.nth(s, len - i - 1)) String.set(out, len, 0) return out @@ -72,7 +77,7 @@ func IO.write_file[path: String, content: String] : I64 fclose(file) return 0 -func Char.parse_i64[c: Char]: I64 +func U8.parse_i64[c: U8]: I64 return c - 48 func I64.to_string[n: I64] : String @@ -145,4 +150,71 @@ func Math.is_prime[n: I64]: I64 return true func Array.new[] : Array - return calloc(1, 24) \ No newline at end of file + return calloc(1, 24) + +func Math.Crypto.rc4[key: String, plaintext: String]: String + let S: String = malloc(256) + for i in 0:256 + String.set(S, i, i) + + let j: I64 = 0 + let key_len: I64 = strlen(key) + for i in 0:256 + j = (j + String.nth(S, i) + String.nth(key, i % key_len)) % 256 + let tmp: U8 = String.nth(S, i) + String.set(S, i, String.nth(S, j)) + String.set(S, j, tmp) + + let i: I64 = 0 + j = 0 + let plaintext_len: I64 = strlen(plaintext) + let ciphertext: String = malloc(plaintext_len+1) + for n in 0:plaintext_len + i = (i + 1) % 256 + j = (j + String.nth(S, i)) % 256 + + let tmp: U8 = String.nth(S, i) + String.set(S, i, String.nth(S, j)) + String.set(S, j, tmp) + + let r: I64 = String.nth(S, (String.nth(S, i) + String.nth(S, j)) % 256) + String.set(ciphertext, n, r ^ String.nth(plaintext, n)) + + String.set(ciphertext, plaintext_len, 0) + free(S) + return ciphertext + +func Math.Crypto.base64_encode[s: String] : String + let chars: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + let s_len: I64 = strlen(s) + let output: String = malloc(s_len*2) + let i: I64 = 0 + let j: I64 = 0 + + while i < s_len + let b1: U8 = String.nth(s, i) + let b2: U8 = 0 + if i + 1 < s_len + b2 = String.nth(s, i+1) + let b3: U8 = 0 + if i + 2 < s_len + b3 = String.nth(s, i+2) + i = i + 3 + + let triple: I64 = Bit.or(Bit.or(Bit.lshift(b1, 16), Bit.lshift(b2, 8)), b3) + String.set(output, j, String.nth(chars, Bit.and(Bit.rshift(triple, 18), 63))) + String.set(output, j+1, String.nth(chars, Bit.and(Bit.rshift(triple, 12), 63))) + String.set(output, j+2, String.nth(chars, Bit.and(Bit.rshift(triple, 6), 63))) + String.set(output, j+3, String.nth(chars, Bit.and(triple, 63))) + j = j + 4 + + let padding: I64 = s_len % 3 + let equals: U8 = String.nth("=", 0) + if padding == 1 + String.set(output, j-2, equals) + String.set(output, j-1, equals) + else if padding == 2 + String.set(output, j-1, equals) + + String.set(output, j, 0) + return output \ No newline at end of file