move panic out, add stack frames, proper rust test

This commit is contained in:
janis 2025-10-20 22:44:27 +02:00
parent 9a235e625a
commit b5c0a41aa4
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
5 changed files with 70 additions and 17 deletions

View file

@ -4,7 +4,7 @@ TARGET_DIR := target
SRC := src/lib.asm src/int_to_str.asm src/vec.asm SRC := src/lib.asm src/int_to_str.asm src/vec.asm
OBJ := $(patsubst src/%.asm,$(TARGET_DIR)/%.o,$(SRC)) 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_OBJ := $(patsubst src/%.asm,$(TARGET_DIR)/%.o,$(BIN_SRC))
BIN := $(TARGET_DIR)/main BIN := $(TARGET_DIR)/main

View file

@ -3,7 +3,7 @@ default rel
section .rdata section .rdata
panic_msg db "panic occured!", 10 panic_msg db "panic occured!", 10
panic_msg_len equ $ - panic_msg panic_msg_len equ $ - panic_msg
oom_msg db "panic: oom!", 10 oom_msg db "oom!", 10
oom_msg_len equ $ - oom_msg oom_msg_len equ $ - oom_msg
error_msg db "Error: " error_msg db "Error: "
error_msg_len equ $ - error_msg error_msg_len equ $ - error_msg
@ -11,7 +11,6 @@ section .rdata
section .text section .text
global oom global oom
global panic
global strlen global strlen
global strcmp global strcmp
global strchr global strchr
@ -30,20 +29,12 @@ global is_numeric
global is_id_continue global is_id_continue
global is_id_start global is_id_start
extern panic
;; ============================== ;; ==============================
;; Helper functions ;; 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 ;; Abort the program with a default panic message
oom: oom:
lea rdi, [oom_msg] lea rdi, [oom_msg]

19
lang/src/panic.asm Normal file
View file

@ -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

View file

@ -38,6 +38,8 @@ global vec_tests
;; rdx: drop function pointer ;; rdx: drop function pointer
;; fn vec_init(vec: *mut Vec, item_size: usize, drop: Option<fn(*mut u8)>) ;; fn vec_init(vec: *mut Vec, item_size: usize, drop: Option<fn(*mut u8)>)
vec_init: vec_init:
push rbp
mov rbp, rsp
push rdx push rdx
push rsi push rsi
push rdi push rdi
@ -57,12 +59,15 @@ vec_init:
mov qword [r15 + 16], rax mov qword [r15 + 16], rax
pop rdx pop rdx
mov qword [r15 + 32], rdx ; drop mov qword [r15 + 32], rdx ; drop
pop rbp
ret ret
;; rdi: pointer to Vec struct ;; rdi: pointer to Vec struct
;; rsi: index ;; rsi: index
;; fn vec_get(vec: *mut Vec, index: usize) -> *mut u8 ;; fn vec_get(vec: *mut Vec, index: usize) -> *mut u8
vec_get: vec_get:
push rbp
mov rbp, rsp
; if (index >= vec.len) panic(); ; if (index >= vec.len) panic();
mov rax, [rdi + 8] ; len mov rax, [rdi + 8] ; len
cmp rsi, rax cmp rsi, rax
@ -72,9 +77,11 @@ vec_get:
mul rsi ; index * item_size mul rsi ; index * item_size
mov rsi, [rdi] ; data mov rsi, [rdi] ; data
add rax, rsi ; data + index * item_size add rax, rsi ; data + index * item_size
pop rbp
ret ret
.panic: .panic:
call panic call panic
pop rbp
ret ret
@ -83,6 +90,8 @@ vec_get:
;; rdx: size of data to push ;; rdx: size of data to push
;; fn vec_push(vec: *mut Vec, data: &[u8]) ;; fn vec_push(vec: *mut Vec, data: &[u8])
vec_push: vec_push:
push rbp
mov rbp, rsp
; if data.len() != vec.item_size panic(); ; if data.len() != vec.item_size panic();
mov rax, [rdi + 24] mov rax, [rdi + 24]
cmp rdx, rax cmp rdx, rax
@ -105,15 +114,19 @@ vec_push:
mov rax, [rsp] ; vec mov rax, [rsp] ; vec
add qword [rax + 8], 1 add qword [rax + 8], 1
add rsp, 24 add rsp, 24
pop rbp
ret ret
.panic: .panic:
call panic call panic
pop rbp
ret ret
;; rdi: pointer to Vec struct ;; rdi: pointer to Vec struct
;; fn vec_pop(vec: *mut Vec) ;; fn vec_pop(vec: *mut Vec)
vec_pop: vec_pop:
push rbp
mov rbp, rsp
; if vec.len == 0 panic(); ; if vec.len == 0 panic();
mov rax, [rdi + 8] ; len mov rax, [rdi + 8] ; len
test rax, rax test rax, rax
@ -132,10 +145,12 @@ vec_pop:
mov rdi, rsi mov rdi, rsi
call r8 call r8
.ret: .ret:
pop rbp
ret ret
; } ; }
.underflow: .underflow:
call panic call panic
pop rbp
ret ret
@ -144,6 +159,8 @@ vec_pop:
;; rdx: index b ;; rdx: index b
;; fn vec_swap(vec: *mut Vec, a: usize, b: usize) ;; fn vec_swap(vec: *mut Vec, a: usize, b: usize)
vec_swap: vec_swap:
push rbp
mov rbp, rsp
push rbx push rbx
; let vec, a, b; ; let vec, a, b;
sub rsp, 24 sub rsp, 24
@ -176,9 +193,11 @@ vec_swap:
call memswap call memswap
add rsp, 24 add rsp, 24
pop rbx pop rbx
pop rbp
ret ret
.panic: .panic:
call panic call panic
pop rbx
ret ret
@ -186,6 +205,8 @@ vec_swap:
;; rsi: index ;; rsi: index
;; fn vec_remove(vec: *mut Vec, index: usize) ;; fn vec_remove(vec: *mut Vec, index: usize)
vec_remove: vec_remove:
push rbp
mov rbp, rsp
; if (index >= vec.len) panic(); ; if (index >= vec.len) panic();
mov rax, [rdi + 8] ; len mov rax, [rdi + 8] ; len
cmp rsi, rax cmp rsi, rax
@ -214,14 +235,18 @@ vec_remove:
call r8 call r8
; } ; }
.ret: .ret:
pop rbp
ret ret
.panic: .panic:
call panic call panic
pop rbp
ret ret
;; rdi: pointer to Vec struct ;; rdi: pointer to Vec struct
;; fn vec_try_grow(vec: *mut Vec, push_size: usize) -> bool ;; fn vec_try_grow(vec: *mut Vec, push_size: usize) -> bool
vec_try_grow: vec_try_grow:
push rbp
mov rbp, rsp
push rbx push rbx
mov rax, [rdi + 16] ; capacity mov rax, [rdi + 16] ; capacity
mov rbx, [rdi + 8] ; len mov rbx, [rdi + 8] ; len
@ -229,6 +254,7 @@ vec_try_grow:
jg .grow jg .grow
pop rbx pop rbx
xor rax, rax xor rax, rax
pop rbp
ret ret
.grow: .grow:
; let vec; ; let vec;
@ -266,10 +292,13 @@ vec_try_grow:
add rsp, 24 add rsp, 24
pop rbx pop rbx
xor rax, rax xor rax, rax
pop rbp
ret ret
;; rdi: pointer to Vec struct ;; rdi: pointer to Vec struct
vec_drop: vec_drop:
push rbp
mov rbp, rsp
push r12 push r12
push r13 push r13
push r14 push r14
@ -301,4 +330,5 @@ vec_drop:
pop r14 pop r14
pop r13 pop r13
pop r12 pop r12
pop rbp
ret ret

View file

@ -7,12 +7,17 @@ pub struct BlobVec {
pub drop: Option<extern "C" fn(*mut u8)>, pub drop: Option<extern "C" fn(*mut u8)>,
} }
#[no_mangle]
extern "C" fn panic() -> ! {
panic!("Called panic from external code.");
}
unsafe impl Send for BlobVec {} unsafe impl Send for BlobVec {}
unsafe impl Sync for BlobVec {} unsafe impl Sync for BlobVec {}
unsafe extern "C" { unsafe extern "C" {
unsafe fn vec_init(vec: *mut BlobVec, elem_size: usize, drop: Option<extern "C" fn(*mut u8)>); unsafe fn vec_init(vec: *mut BlobVec, elem_size: usize, drop: Option<extern "C" fn(*mut u8)>);
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_pop(vec: *mut BlobVec);
unsafe fn vec_get(vec: *mut BlobVec, index: usize) -> *mut u8; unsafe fn vec_get(vec: *mut BlobVec, index: usize) -> *mut u8;
unsafe fn vec_remove(vec: *mut BlobVec, index: usize); unsafe fn vec_remove(vec: *mut BlobVec, index: usize);
@ -31,6 +36,11 @@ fn main() {
drop: None, drop: None,
}; };
fn as_slice<T>(vec: &BlobVec) -> &[T] {
assert_eq!(vec.elem_size, core::mem::size_of::<T>());
unsafe { core::slice::from_raw_parts(vec.data as *const T, vec.len) }
}
extern "C" fn drop(ptr: *mut u8) { extern "C" fn drop(ptr: *mut u8) {
unsafe { unsafe {
DROPS *= ptr.cast::<u32>().read() as usize; DROPS *= ptr.cast::<u32>().read() as usize;
@ -41,8 +51,9 @@ fn main() {
vec_init(&mut vec, 4, Some(drop)); vec_init(&mut vec, 4, Some(drop));
let mut value: u32 = 2; let mut value: u32 = 2;
assert_eq!(vec.len, 0); 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!(vec.len, 1);
assert_eq!(as_slice::<u32>(&vec), &[2]);
let retrieved = *(vec_get(&mut vec, 0) as *mut u32); let retrieved = *(vec_get(&mut vec, 0) as *mut u32);
assert_eq!(retrieved, 2); assert_eq!(retrieved, 2);
assert_eq!(DROPS, 1); assert_eq!(DROPS, 1);
@ -50,9 +61,11 @@ fn main() {
assert_eq!(vec.len, 0); assert_eq!(vec.len, 0);
assert_eq!(DROPS, 2); assert_eq!(DROPS, 2);
value = 3; 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::<u32>(&vec), &[3]);
value = 5; 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::<u32>(&vec), &[3, 5]);
assert_eq!(vec.len, 2); assert_eq!(vec.len, 2);
vec_pop(&mut vec); vec_pop(&mut vec);
vec_pop(&mut vec); vec_pop(&mut vec);