From b5c0a41aa42410379d8bbcba2ed34446f562caa7 Mon Sep 17 00:00:00 2001 From: janis Date: Mon, 20 Oct 2025 22:44:27 +0200 Subject: [PATCH] move panic out, add stack frames, proper rust test --- lang/Makefile | 2 +- lang/src/lib.asm | 15 +++------------ lang/src/panic.asm | 19 +++++++++++++++++++ lang/src/vec.asm | 30 ++++++++++++++++++++++++++++++ lang/tests/vec.rs | 21 +++++++++++++++++---- 5 files changed, 70 insertions(+), 17 deletions(-) create mode 100644 lang/src/panic.asm diff --git a/lang/Makefile b/lang/Makefile index bd8c4a3..3cb046b 100644 --- a/lang/Makefile +++ b/lang/Makefile @@ -4,7 +4,7 @@ TARGET_DIR := target SRC := src/lib.asm src/int_to_str.asm src/vec.asm OBJ := $(patsubst src/%.asm,$(TARGET_DIR)/%.o,$(SRC)) -BIN_SRC := src/main.asm +BIN_SRC := src/main.asm src/panic.asm BIN_OBJ := $(patsubst src/%.asm,$(TARGET_DIR)/%.o,$(BIN_SRC)) BIN := $(TARGET_DIR)/main diff --git a/lang/src/lib.asm b/lang/src/lib.asm index 1876a55..8b1a1ab 100644 --- a/lang/src/lib.asm +++ b/lang/src/lib.asm @@ -3,7 +3,7 @@ default rel section .rdata panic_msg db "panic occured!", 10 panic_msg_len equ $ - panic_msg - oom_msg db "panic: oom!", 10 + oom_msg db "oom!", 10 oom_msg_len equ $ - oom_msg error_msg db "Error: " error_msg_len equ $ - error_msg @@ -11,7 +11,6 @@ section .rdata section .text global oom -global panic global strlen global strcmp global strchr @@ -30,20 +29,12 @@ global is_numeric global is_id_continue global is_id_start +extern panic + ;; ============================== ;; Helper functions ;; ============================== -;; Abort the program with a default panic message -panic: - lea rdi, [panic_msg] - lea rsi, [panic_msg_len] - call eprint_str - ; exit with error code 1 - mov rax, 60 ; syscall: exit - mov rdi, 1 ; status: 1 - syscall - ;; Abort the program with a default panic message oom: lea rdi, [oom_msg] diff --git a/lang/src/panic.asm b/lang/src/panic.asm new file mode 100644 index 0000000..1cec8be --- /dev/null +++ b/lang/src/panic.asm @@ -0,0 +1,19 @@ +default rel +section .rdata + panic_msg db "panic occured!", 10 + panic_msg_len equ $ - panic_msg + +extern eprint_str + +section .text +global panic + +;; Abort the program with a default panic message +panic: + lea rdi, [panic_msg] + lea rsi, [panic_msg_len] + call eprint_str + ; exit with error code 1 + mov rax, 60 ; syscall: exit + mov rdi, 1 ; status: 1 + syscall diff --git a/lang/src/vec.asm b/lang/src/vec.asm index abc92d6..2cc89ba 100644 --- a/lang/src/vec.asm +++ b/lang/src/vec.asm @@ -38,6 +38,8 @@ global vec_tests ;; rdx: drop function pointer ;; fn vec_init(vec: *mut Vec, item_size: usize, drop: Option) vec_init: + push rbp + mov rbp, rsp push rdx push rsi push rdi @@ -57,12 +59,15 @@ vec_init: mov qword [r15 + 16], rax pop rdx mov qword [r15 + 32], rdx ; drop + pop rbp ret ;; rdi: pointer to Vec struct ;; rsi: index ;; fn vec_get(vec: *mut Vec, index: usize) -> *mut u8 vec_get: + push rbp + mov rbp, rsp ; if (index >= vec.len) panic(); mov rax, [rdi + 8] ; len cmp rsi, rax @@ -72,9 +77,11 @@ vec_get: mul rsi ; index * item_size mov rsi, [rdi] ; data add rax, rsi ; data + index * item_size + pop rbp ret .panic: call panic + pop rbp ret @@ -83,6 +90,8 @@ vec_get: ;; rdx: size of data to push ;; fn vec_push(vec: *mut Vec, data: &[u8]) vec_push: + push rbp + mov rbp, rsp ; if data.len() != vec.item_size panic(); mov rax, [rdi + 24] cmp rdx, rax @@ -105,15 +114,19 @@ vec_push: mov rax, [rsp] ; vec add qword [rax + 8], 1 add rsp, 24 + pop rbp ret .panic: call panic + pop rbp ret ;; rdi: pointer to Vec struct ;; fn vec_pop(vec: *mut Vec) vec_pop: + push rbp + mov rbp, rsp ; if vec.len == 0 panic(); mov rax, [rdi + 8] ; len test rax, rax @@ -132,10 +145,12 @@ vec_pop: mov rdi, rsi call r8 .ret: + pop rbp ret ; } .underflow: call panic + pop rbp ret @@ -144,6 +159,8 @@ vec_pop: ;; rdx: index b ;; fn vec_swap(vec: *mut Vec, a: usize, b: usize) vec_swap: + push rbp + mov rbp, rsp push rbx ; let vec, a, b; sub rsp, 24 @@ -176,9 +193,11 @@ vec_swap: call memswap add rsp, 24 pop rbx + pop rbp ret .panic: call panic + pop rbx ret @@ -186,6 +205,8 @@ vec_swap: ;; rsi: index ;; fn vec_remove(vec: *mut Vec, index: usize) vec_remove: + push rbp + mov rbp, rsp ; if (index >= vec.len) panic(); mov rax, [rdi + 8] ; len cmp rsi, rax @@ -214,14 +235,18 @@ vec_remove: call r8 ; } .ret: + pop rbp ret .panic: call panic + pop rbp ret ;; rdi: pointer to Vec struct ;; fn vec_try_grow(vec: *mut Vec, push_size: usize) -> bool vec_try_grow: + push rbp + mov rbp, rsp push rbx mov rax, [rdi + 16] ; capacity mov rbx, [rdi + 8] ; len @@ -229,6 +254,7 @@ vec_try_grow: jg .grow pop rbx xor rax, rax + pop rbp ret .grow: ; let vec; @@ -266,10 +292,13 @@ vec_try_grow: add rsp, 24 pop rbx xor rax, rax + pop rbp ret ;; rdi: pointer to Vec struct vec_drop: + push rbp + mov rbp, rsp push r12 push r13 push r14 @@ -301,4 +330,5 @@ vec_drop: pop r14 pop r13 pop r12 + pop rbp ret diff --git a/lang/tests/vec.rs b/lang/tests/vec.rs index e9a45f6..a4943a1 100644 --- a/lang/tests/vec.rs +++ b/lang/tests/vec.rs @@ -7,12 +7,17 @@ pub struct BlobVec { pub drop: Option, } +#[no_mangle] +extern "C" fn panic() -> ! { + panic!("Called panic from external code."); +} + unsafe impl Send for BlobVec {} unsafe impl Sync for BlobVec {} unsafe extern "C" { unsafe fn vec_init(vec: *mut BlobVec, elem_size: usize, drop: Option); - unsafe fn vec_push(vec: *mut BlobVec, elem: *const u8); + unsafe fn vec_push(vec: *mut BlobVec, elem: *const u8, size: usize); unsafe fn vec_pop(vec: *mut BlobVec); unsafe fn vec_get(vec: *mut BlobVec, index: usize) -> *mut u8; unsafe fn vec_remove(vec: *mut BlobVec, index: usize); @@ -31,6 +36,11 @@ fn main() { drop: None, }; + fn as_slice(vec: &BlobVec) -> &[T] { + assert_eq!(vec.elem_size, core::mem::size_of::()); + unsafe { core::slice::from_raw_parts(vec.data as *const T, vec.len) } + } + extern "C" fn drop(ptr: *mut u8) { unsafe { DROPS *= ptr.cast::().read() as usize; @@ -41,8 +51,9 @@ fn main() { vec_init(&mut vec, 4, Some(drop)); let mut value: u32 = 2; assert_eq!(vec.len, 0); - vec_push(&mut vec, &value as *const u32 as *const u8); + vec_push(&mut vec, &value as *const u32 as *const u8, 4); assert_eq!(vec.len, 1); + assert_eq!(as_slice::(&vec), &[2]); let retrieved = *(vec_get(&mut vec, 0) as *mut u32); assert_eq!(retrieved, 2); assert_eq!(DROPS, 1); @@ -50,9 +61,11 @@ fn main() { assert_eq!(vec.len, 0); assert_eq!(DROPS, 2); value = 3; - vec_push(&mut vec, &value as *const u32 as *const u8); + vec_push(&mut vec, &value as *const u32 as *const u8, 4); + assert_eq!(as_slice::(&vec), &[3]); value = 5; - vec_push(&mut vec, &value as *const u32 as *const u8); + vec_push(&mut vec, &value as *const u32 as *const u8, 4); + assert_eq!(as_slice::(&vec), &[3, 5]); assert_eq!(vec.len, 2); vec_pop(&mut vec); vec_pop(&mut vec);