asdf
This commit is contained in:
parent
e9f634bca5
commit
9a235e625a
|
|
@ -1,21 +1,45 @@
|
|||
# Makefile: Compile and link main.asm using nasm and mold, intermediate files in target/
|
||||
|
||||
TARGET_DIR := target
|
||||
SRC := src/main.asm src/lib.asm src/int_to_str.asm
|
||||
OBJ := $(addprefix $(TARGET_DIR)/, $(notdir $(SRC:.asm=.o)))
|
||||
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_OBJ := $(patsubst src/%.asm,$(TARGET_DIR)/%.o,$(BIN_SRC))
|
||||
BIN := $(TARGET_DIR)/main
|
||||
|
||||
TEST_SRCS := $(wildcard tests/*.rs)
|
||||
TEST_BINS := $(patsubst tests/%.rs,$(TARGET_DIR)/tests/%,$(TEST_SRCS))
|
||||
OBJ_LINK_ARGS := $(foreach o,$(OBJ),-C link-arg=$(o))
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
test-bins: $(TEST_BINS)
|
||||
|
||||
test: test-bins
|
||||
@echo "Running all tests.."
|
||||
@for b in $(TEST_BINS); do \
|
||||
echo "==> Running $$b"; \
|
||||
"$$b" || exit $$?; \
|
||||
done
|
||||
|
||||
# pattern rule: compile each .rs into a binary with the same base name
|
||||
$(TARGET_DIR)/tests/%: tests/%.rs | $(OBJ) $(TARGET_DIR)/tests
|
||||
@echo "[$(RUSTC)] $< -> $@"
|
||||
rustc -Clink-arg=-fuse-ld=mold $(OBJ_LINK_ARGS) -g -o $@ $<
|
||||
|
||||
$(TARGET_DIR):
|
||||
mkdir -p $(TARGET_DIR)
|
||||
mkdir -p $(TARGET_DIR)/tests
|
||||
|
||||
$(TARGET_DIR)/tests: $(TARGET_DIR)
|
||||
mkdir -p $(TARGET_DIR)/tests
|
||||
|
||||
$(TARGET_DIR)/%.o: src/%.asm | $(TARGET_DIR)
|
||||
nasm -f elf64 -g $< -o $@
|
||||
|
||||
$(BIN): $(OBJ)
|
||||
$(BIN): $(OBJ) $(BIN_OBJ)
|
||||
mold -run ld -o $(BIN) $(OBJ)
|
||||
|
||||
run: $(BIN)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
default rel
|
||||
|
||||
section .rdata
|
||||
panic_msg db "panic occured!", 10
|
||||
panic_msg_len equ $ - panic_msg
|
||||
oom_msg db "panic: oom!", 10
|
||||
oom_msg_len equ $ - oom_msg
|
||||
file_error_msg db "Could not open file: "
|
||||
file_error_msg_len equ $ - file_error_msg
|
||||
error_msg db "Error: "
|
||||
error_msg_len equ $ - error_msg
|
||||
|
||||
|
|
@ -23,6 +23,7 @@ global exit
|
|||
global error_to_str
|
||||
global eprint_error
|
||||
global alloc_pages
|
||||
global allocate
|
||||
|
||||
global is_alpha
|
||||
global is_numeric
|
||||
|
|
@ -35,8 +36,8 @@ global is_id_start
|
|||
|
||||
;; Abort the program with a default panic message
|
||||
panic:
|
||||
mov rdi, panic_msg
|
||||
mov rsi, panic_msg_len
|
||||
lea rdi, [panic_msg]
|
||||
lea rsi, [panic_msg_len]
|
||||
call eprint_str
|
||||
; exit with error code 1
|
||||
mov rax, 60 ; syscall: exit
|
||||
|
|
@ -45,8 +46,8 @@ panic:
|
|||
|
||||
;; Abort the program with a default panic message
|
||||
oom:
|
||||
mov rdi, oom_msg
|
||||
mov rsi, oom_msg_len
|
||||
lea rdi, [oom_msg]
|
||||
lea rsi, [oom_msg_len]
|
||||
call eprint_str
|
||||
; exit with error code 1
|
||||
mov rax, 60 ; syscall: exit
|
||||
|
|
@ -64,9 +65,9 @@ exit:
|
|||
;; rsi: length of string
|
||||
eprint_str:
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 2 ; fd: stderr
|
||||
mov rdx, rsi ; len: length
|
||||
mov rsi, rdi ; buf: str
|
||||
mov rdi, 2 ; fd: stderr
|
||||
syscall
|
||||
ret
|
||||
|
||||
|
|
@ -95,7 +96,7 @@ streq:
|
|||
jne .false
|
||||
; for i in 0..a.len() {
|
||||
xor r8, r8
|
||||
.loop
|
||||
.loop:
|
||||
cmp r8, rsi
|
||||
jge .true
|
||||
; if a[i] != b[i] {
|
||||
|
|
@ -136,10 +137,10 @@ strcmp:
|
|||
.loop:
|
||||
cmp r8, rax
|
||||
jge .length_check
|
||||
mov r9l, [rdi + r8]
|
||||
mov r10l, [rdx + r8]
|
||||
mov r9b, [rdi + r8]
|
||||
mov r10b, [rdx + r8]
|
||||
; if a[i] < b[i] {
|
||||
cmp r9l, r10l
|
||||
cmp r9b, r10b
|
||||
; return Ordering::Less;
|
||||
jb .less
|
||||
; } else if a[i] > b[i] {
|
||||
|
|
@ -299,8 +300,8 @@ eprint_error:
|
|||
; let err_code = err_code;
|
||||
push rdi
|
||||
; eprint_str(ERROR_STR, ERROR_STR.len());
|
||||
mov rdi, error_msg
|
||||
mov rsi, error_msg_len
|
||||
lea rdi, [error_msg]
|
||||
lea rsi, [error_msg_len]
|
||||
call eprint_str
|
||||
; let (err, len) = error_to_str(err_code);
|
||||
pop rdi
|
||||
|
|
|
|||
|
|
@ -12,21 +12,35 @@ extern exit
|
|||
extern error_to_str
|
||||
extern eprint_error
|
||||
extern alloc_pages
|
||||
extern allocate
|
||||
|
||||
extern is_alpha
|
||||
extern is_numeric
|
||||
extern is_id_continue
|
||||
extern is_id_start
|
||||
|
||||
extern vec_tests
|
||||
|
||||
section .data
|
||||
hello_msg db "Hello, World!", 10
|
||||
hello_msg_len equ $ - hello_msg
|
||||
file_error_msg db "Could not open file: "
|
||||
file_error_msg_len equ $ - file_error_msg
|
||||
test_success db "All tests passed!", 10
|
||||
test_success_len equ $ - test_success
|
||||
|
||||
section .text
|
||||
global _start
|
||||
_start:
|
||||
mov rdi, test_success
|
||||
mov rsi, test_success_len
|
||||
call eprint_str
|
||||
|
||||
mov rdi, 0
|
||||
call exit
|
||||
|
||||
|
||||
compiler_entry:
|
||||
; get filename from argv[1]
|
||||
; argv is at rsp + 8
|
||||
; check if argc > 1
|
||||
|
|
@ -158,9 +172,7 @@ tokeniser_init:
|
|||
|
||||
; allocate buffer
|
||||
mov rcx, r15
|
||||
add rcx, 4095
|
||||
shr rcx, 12 ; divide by 4096
|
||||
call alloc_pages
|
||||
call allocate
|
||||
mov [buffer], rax
|
||||
mov [buffer_len], r15
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ global vec_remove
|
|||
global vec_get
|
||||
global vec_drop
|
||||
|
||||
global vec_tests
|
||||
|
||||
|
||||
;; Byte vector structure
|
||||
;; struct Vec {
|
||||
|
|
@ -50,7 +52,8 @@ vec_init:
|
|||
mov qword [r15 + 24], rsi ; item_size
|
||||
; (*vec).capacity = INIT_CAPACITY / item_size;
|
||||
mov rax, INIT_CAPACITY
|
||||
idiv rax, rsi
|
||||
xor rdx, rdx
|
||||
div rsi
|
||||
mov qword [r15 + 16], rax
|
||||
pop rdx
|
||||
mov qword [r15 + 32], rdx ; drop
|
||||
|
|
@ -66,7 +69,7 @@ vec_get:
|
|||
jge .panic
|
||||
; return &mut vec.data[index * vec.item_size];
|
||||
mov rax, [rdi + 24] ; item_size
|
||||
imul rax, rsi ; index * item_size
|
||||
mul rsi ; index * item_size
|
||||
mov rsi, [rdi] ; data
|
||||
add rax, rsi ; data + index * item_size
|
||||
ret
|
||||
|
|
@ -90,7 +93,6 @@ vec_push:
|
|||
mov [rsp + 8], rsi ; save data ptr
|
||||
mov [rsp + 16], rdx ; save data size
|
||||
; vec_try_grow(vec, size);
|
||||
mov rsi, [rdi + 24] ; item_size
|
||||
call vec_try_grow
|
||||
; memcpy(&vec.data[vec.len], data, size);
|
||||
mov rax, [rsp] ; vec
|
||||
|
|
@ -101,7 +103,7 @@ vec_push:
|
|||
call memcpy
|
||||
; vec.len += 1;
|
||||
mov rax, [rsp] ; vec
|
||||
add [rax + 8], 1
|
||||
add qword [rax + 8], 1
|
||||
add rsp, 24
|
||||
ret
|
||||
.panic:
|
||||
|
|
@ -124,9 +126,9 @@ vec_pop:
|
|||
test r8, r8
|
||||
je .ret
|
||||
; drop(&mut vec.data[vec.len..vec.len + vec.item_size]);
|
||||
imul rax, [rdi + 24] ; len * item_size
|
||||
mul qword [rdi + 24] ; len * item_size
|
||||
mov rsi, [rdi] ; data
|
||||
add rsi, rax ; data + len * item_size
|
||||
add rax, rsi ; data + len * item_size
|
||||
mov rdi, rsi
|
||||
call r8
|
||||
.ret:
|
||||
|
|
@ -156,11 +158,12 @@ vec_swap:
|
|||
jge .panic
|
||||
|
||||
; a = a * item_size;
|
||||
mov rbx, [rdi + 24] ; item_size
|
||||
imul rdx, rbx ; b * item_size
|
||||
mov rax, [rdi + 24] ; item_size
|
||||
mul rbx ; b * item_size
|
||||
mov [rsp + 16], rax
|
||||
; b = b * item_size;
|
||||
imul rsi, rbx ; a * item_size
|
||||
mov rax, rsi
|
||||
mul rbx ; a * item_size
|
||||
mov [rsp + 8], rax
|
||||
|
||||
; // SAFETY: a and b must not overlap
|
||||
|
|
@ -168,7 +171,7 @@ vec_swap:
|
|||
mov rcx, [rdi + 24] ; item_size
|
||||
lea rdi, [rdi] ; vec.data
|
||||
mov rsi, rdi
|
||||
add rdi [rsp + 16] ; data + a
|
||||
add rdi, [rsp + 16] ; data + a
|
||||
add rsi, [rsp + 24] ; data + b
|
||||
call memswap
|
||||
add rsp, 24
|
||||
|
|
@ -205,22 +208,23 @@ vec_remove:
|
|||
test r8, r8
|
||||
je .ret
|
||||
; drop(&mut vec.data[vec.len..vec.len + vec.item_size]);
|
||||
imul rax, [rdi + 24] ; len * item_size
|
||||
mul qword [rdi + 24] ; len * item_size
|
||||
lea rdi, [rdi] ; data
|
||||
add rdi, rax ; data + len * item_size
|
||||
call r8
|
||||
; }
|
||||
.ret:
|
||||
ret
|
||||
.panic:
|
||||
call panic
|
||||
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
|
||||
|
|
@ -238,7 +242,8 @@ vec_try_grow:
|
|||
cmp rcx, rbx
|
||||
cmovl rcx, rbx ; rcx = new_capacity
|
||||
mov [rsp + 8], rcx
|
||||
imul rcx, [rdi + 24] ; new_capacity * item_size
|
||||
mov rax, rcx
|
||||
mul qword [rdi + 24] ; new_capacity * item_size
|
||||
; new_data = allocate(new_capacity);
|
||||
mov rdi, rax
|
||||
call allocate
|
||||
|
|
@ -246,7 +251,7 @@ vec_try_grow:
|
|||
mov rdi, [rsp]
|
||||
; memcpy(new_data, old_data, len * vec.item_size);
|
||||
mov rax, [rdi + 8] ; len
|
||||
imul rax, [rdi + 24] ; len * item_size
|
||||
mul qword [rdi + 24] ; len * item_size
|
||||
mov rdx, rax ; len
|
||||
mov rsi, [rdi] ; old_data
|
||||
mov rdi, [rsp + 16] ; new_data
|
||||
|
|
@ -281,7 +286,8 @@ vec_drop:
|
|||
jge .ret
|
||||
mov rdi, [rsp]
|
||||
; drop(&mut vec.data[i * vec.item_size..(i + 1) * vec.item_size]);
|
||||
imul r13, [rdi + 24] ; i * item_size
|
||||
mov rax, r13
|
||||
mul qword [rdi + 24] ; i * item_size
|
||||
mov rdi, [rdi] ; data
|
||||
add rdi, rax
|
||||
call r12
|
||||
|
|
|
|||
62
lang/tests/vec.rs
Normal file
62
lang/tests/vec.rs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
#[repr(C)]
|
||||
pub struct BlobVec {
|
||||
pub data: *mut u8,
|
||||
pub len: usize,
|
||||
pub cap: usize,
|
||||
pub elem_size: usize,
|
||||
pub drop: Option<extern "C" fn(*mut u8)>,
|
||||
}
|
||||
|
||||
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_pop(vec: *mut BlobVec);
|
||||
unsafe fn vec_get(vec: *mut BlobVec, index: usize) -> *mut u8;
|
||||
unsafe fn vec_remove(vec: *mut BlobVec, index: usize);
|
||||
unsafe fn vec_drop(vec: *mut BlobVec);
|
||||
|
||||
unsafe fn exit(code: i32) -> !;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
static mut DROPS: usize = 1;
|
||||
let mut vec = BlobVec {
|
||||
data: core::ptr::null_mut(),
|
||||
len: 0,
|
||||
cap: 0,
|
||||
elem_size: 1,
|
||||
drop: None,
|
||||
};
|
||||
|
||||
extern "C" fn drop(ptr: *mut u8) {
|
||||
unsafe {
|
||||
DROPS *= ptr.cast::<u32>().read() as usize;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
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);
|
||||
assert_eq!(vec.len, 1);
|
||||
let retrieved = *(vec_get(&mut vec, 0) as *mut u32);
|
||||
assert_eq!(retrieved, 2);
|
||||
assert_eq!(DROPS, 1);
|
||||
vec_pop(&mut vec);
|
||||
assert_eq!(vec.len, 0);
|
||||
assert_eq!(DROPS, 2);
|
||||
value = 3;
|
||||
vec_push(&mut vec, &value as *const u32 as *const u8);
|
||||
value = 5;
|
||||
vec_push(&mut vec, &value as *const u32 as *const u8);
|
||||
assert_eq!(vec.len, 2);
|
||||
vec_pop(&mut vec);
|
||||
vec_pop(&mut vec);
|
||||
assert_eq!(DROPS, 2 * 3 * 5);
|
||||
eprintln!("Push/pop test passed\n");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue