From ac2f3a04b23b8aaffaf165ff08d6fcf72650f96e Mon Sep 17 00:00:00 2001 From: janis Date: Mon, 20 Oct 2025 17:47:36 +0200 Subject: [PATCH] add item size to vec struct rather than arg --- lang/src/vec.asm | 158 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 111 insertions(+), 47 deletions(-) diff --git a/lang/src/vec.asm b/lang/src/vec.asm index bf0a272..2523cf4 100644 --- a/lang/src/vec.asm +++ b/lang/src/vec.asm @@ -23,13 +23,21 @@ global vec_free ;; data: *mut u8, ;; len: usize, ;; capacity: usize, +;; item_size: usize, +;; drop: Option, ;; } +;; size: 40 bytes +;; align: 8 bytes ;; Initialize a new vector ;; rdi: pointer to Vec struct -;; fn vec_init(vec: *mut Vec) +;; rsi: item_size +;; rdx: drop function pointer +;; fn vec_init(vec: *mut Vec, item_size: usize, drop: Option) vec_init: + push rdx + push rsi push rdi ; (*vec).data = allocate(INIT_CAPACITY); mov rdi, INIT_CAPACITY @@ -38,8 +46,14 @@ vec_init: mov [r15], rax ; (*vec).len = 0; mov qword [r15 + 8], 0 - ; (*vec).capacity = INIT_CAPACITY; - mov qword [r15 + 16], INIT_CAPACITY + pop rsi + mov qword [r15 + 24], rsi ; item_size + ; (*vec).capacity = INIT_CAPACITY / item_size; + mov rax, INIT_CAPACITY + idiv rax, rsi + mov qword [r15 + 16], rax + pop rdx + mov qword [r15 + 32], rdx ; drop ret ;; rdi: pointer to Vec struct @@ -47,13 +61,17 @@ vec_init: ;; rdx: size of data to push ;; fn vec_push(vec: *mut Vec, data: &[u8]) vec_push: + ; if data.len() != vec.item_size panic(); + mov rax, [rdi + 24] + cmp rdx, rax + jne .panic ; let vec, ptr, size; sub rsp, 24 mov [rsp], rdi ; save vec mov [rsp + 8], rsi ; save data ptr mov [rsp + 16], rdx ; save data size ; vec_try_grow(vec, size); - mov rsi, rdx + mov rsi, [rdi + 24] ; item_size call vec_try_grow ; memcpy(&vec.data[vec.len], data, size); mov rax, [rsp] ; vec @@ -62,24 +80,39 @@ vec_push: mov rsi, [rsp + 8] ; data ptr mov rdx, [rsp + 16] ; data size call memcpy - ; vec.len += size; + ; vec.len += 1; mov rax, [rsp] ; vec - mov rbx, [rsp + 16] ; size - add [rax + 8], rbx + add [rax + 8], 1 add rsp, 24 ret +.panic: + call panic + ret ;; rdi: pointer to Vec struct -;; rsi: size of data to pop -;; fn vec_pop(vec: *mut Vec, size: usize) +;; fn vec_pop(vec: *mut Vec) vec_pop: + ; if vec.len == 0 panic(); mov rax, [rdi + 8] ; len - cmp rax, rsi - jl .underflow - sub rax, rsi + test rax, rax + je .underflow + ; vec.len -= 1; + sub rax, 1 mov [rdi + 8], rax + ; if let Some(drop) = vec.drop { + mov r8, [rdi + 32] + test r8, r8 + je .ret + ; drop(&mut vec.data[vec.len..vec.len + vec.item_size]); + imul rax, [rdi + 24] ; len * item_size + mov rsi, [rdi] ; data + add rsi, rax ; data + len * item_size + mov rdi, rsi + call r8 +.ret: ret + ; } .underflow: call panic ret @@ -88,19 +121,12 @@ vec_pop: ;; rdi: pointer to Vec struct ;; rsi: index a ;; rdx: index b -;; rcx: step size -;; fn vec_swap(vec: *mut Vec, a: usize, b: usize, step: usize) +;; fn vec_swap(vec: *mut Vec, a: usize, b: usize) vec_swap: - sub rsp, 32 + push rbx + ; let vec, a, b; + sub rsp, 24 mov [rsp], rdi - mov [rsp + 8], rcx - ; let a = a * step; - imul rsi, rcx - mov [rsp + 16], rax - ; let b = b * step; - imul rdx, rcx - mov [rsp + 24], rbx - ; let max_index = max(a, b); mov rbx, rsi cmp rbx, rdx @@ -109,74 +135,112 @@ vec_swap: mov rax, [rdi + 8] ; len cmp rbx, rax jge .panic - ; // a and b must not overlap + + ; a = a * item_size; + mov rbx, [rdi + 24] ; item_size + imul rdx, rbx ; b * item_size + mov [rsp + 16], rax + ; b = b * item_size; + imul rsi, rbx ; a * item_size + mov [rsp + 8], rax + + ; // SAFETY: a and b must not overlap + ; memswap(&mut vec.data.add(a), &mut vec.data.add(b), vec.item_size); + mov rcx, [rdi + 24] ; item_size lea rdi, [rdi] ; vec.data mov rsi, rdi add rdi [rsp + 16] ; data + a add rsi, [rsp + 24] ; data + b - mov rcx, [rsp + 8] ; step call memswap - add rsp, 32 + add rsp, 24 + pop rbx + ret +.panic: + call panic ret ;; rdi: pointer to Vec struct ;; rsi: index -;; rdx: step size - ;; fn vec_remove(vec: *mut Vec, index: usize, step: usize) +;; fn vec_remove(vec: *mut Vec, index: usize) vec_remove: - ; if (index * step >= vec.len) panic(); - ; if (vec.len - step == index * step { - ; vec.len -= step; - ; } else { - ; vec_swap(vec, index, vec.len / step - 1, step); + ; if (index >= vec.len) panic(); + mov rax, [rdi + 8] ; len + cmp rsi, rax + jge .panic + ; if (vec.len - 1 != index { + sub rax, 1 + cmp rsi, rax + je .remove_last + ; vec_swap(vec, index, vec.len - 1); + mov rdx, rax ; len - 1 + call vec_swap ; } - - - - + ; vec.len -= 1; +.remove_last: + mov rax, [rdi + 8] ; len + sub rax, 1 + mov [rdi + 8], rax + ; if let Some(drop) = vec.drop { + mov r8, [rdi + 32] + test r8, r8 + je .ret + ; drop(&mut vec.data[vec.len..vec.len + vec.item_size]); + imul rax, [rdi + 24] ; len * item_size + lea rdi, [rdi] ; data + add rdi, rax ; data + len * item_size + call r8 + ; } +.ret: + ret ;; rdi: pointer to Vec struct ;; rsi: push size ;; fn vec_try_grow(vec: *mut Vec, push_size: usize) -> bool vec_try_grow: + push rbx mov rax, [rdi + 16] ; capacity mov rbx, [rdi + 8] ; len add rbx, rsi cmp rbx, rax jg .grow + pop rbx xor rax, rax ret .grow: ; let vec; ; let new_capacity; - sub rsp, 16 + ; let new_data; + sub rsp, 24 mov [rsp], rdi - ; new_capacity = max(capacity * 2, len + push_size) + ; new_capacity = max(capacity * 2, len + 1) mov rcx, [rdi + 16] ; capacity shl rcx, 1 ; capacity * 2 cmp rcx, rbx cmovl rcx, rbx ; rcx = new_capacity mov [rsp + 8], rcx + imul rcx, [rdi + 24] ; new_capacity * item_size ; new_data = allocate(new_capacity); - mov rdi, rcx + mov rdi, rax call allocate + mov [rsp + 16], rax mov rdi, [rsp] - ; memcpy(new_data, old_data, len); - mov rbx, [rdi + 8] ; len + ; memcpy(new_data, old_data, len * vec.item_size); + mov rax, [rdi + 8] ; len + imul rax, [rdi + 24] ; len * item_size + mov rdx, rax ; len mov rsi, [rdi] ; old_data - mov rdi, rax ; new_data - mov rdx, rbx ; len + mov rdi, [rsp + 16] ; new_data call memcpy ; free(old_data) // TODO ; update vec mov rdi, [rsp] + mov rax, [rsp + 16] mov [rdi], rax ; data = new_data mov rcx, [rsp + 8] mov [rdi + 16], rcx ; capacity = new_capacity - add rsp, 16 + add rsp, 24 + pop rbx xor rax, rax ret - -