move panic out, add stack frames, proper rust test
This commit is contained in:
parent
9a235e625a
commit
b5c0a41aa4
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
19
lang/src/panic.asm
Normal file
19
lang/src/panic.asm
Normal 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
|
||||
|
|
@ -38,6 +38,8 @@ global vec_tests
|
|||
;; rdx: drop function pointer
|
||||
;; fn vec_init(vec: *mut Vec, item_size: usize, drop: Option<fn(*mut u8)>)
|
||||
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
|
||||
|
|
|
|||
|
|
@ -7,12 +7,17 @@ pub struct BlobVec {
|
|||
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 Sync for BlobVec {}
|
||||
|
||||
unsafe extern "C" {
|
||||
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_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<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) {
|
||||
unsafe {
|
||||
DROPS *= ptr.cast::<u32>().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::<u32>(&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::<u32>(&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::<u32>(&vec), &[3, 5]);
|
||||
assert_eq!(vec.len, 2);
|
||||
vec_pop(&mut vec);
|
||||
vec_pop(&mut vec);
|
||||
|
|
|
|||
Loading…
Reference in a new issue