move tests to use cargo

This commit is contained in:
janis 2025-11-13 14:39:45 +01:00
parent ae2cf5f9d3
commit 7bc3c14095
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
7 changed files with 107 additions and 38 deletions

View file

@ -0,0 +1,25 @@
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = [
# LLD linker
#
# You may need to install it:
#
# - Ubuntu: `sudo apt-get install lld clang`
# - Fedora: `sudo dnf install lld clang`
# - Arch: `sudo pacman -S lld clang`
# "-Clink-arg=-fuse-ld=lld",
# Mold linker
#
# You may need to install it:
#
# - Ubuntu: `sudo apt-get install mold clang`
# - Fedora: `sudo dnf install mold clang`
# - Arch: `sudo pacman -S mold clang`
"-Clink-arg=-fuse-ld=mold",
# Nightly
# "-Zshare-generics=y",
# "-Zthreads=0",
]

View file

@ -30,41 +30,42 @@ fn main() {
println!("cargo:rustc-link-search=native={}", out_dir.display()); println!("cargo:rustc-link-search=native={}", out_dir.display());
let working_dir = manifest_dir.parent().unwrap(); let working_dir = manifest_dir.parent().unwrap();
for file in assembly_files.iter().map(|f| Path::new(f)) { for file in assembly_files.iter().map(Path::new) {
let path = working_dir.join(file); let path = working_dir.join(file);
let obj = file.with_extension("o").file_name().unwrap().to_owned(); let obj = file.with_extension("o").file_name().unwrap().to_owned();
let lib = format!("lib{}.a", file.file_stem().unwrap().to_str().unwrap()); let obj_path = out_dir.join(&obj);
std::process::Command::new("nasm") std::process::Command::new("nasm")
.current_dir(working_dir) .current_dir(working_dir)
.arg(path) .arg(path)
.arg("-wreloc-abs")
.arg("-g") .arg("-g")
.arg("-f") .arg("-f")
.arg("elf64") .arg("elf64")
.arg("-o") .arg("-o")
.arg(out_dir.join(&obj)) .arg(&obj_path)
.status() .status()
.expect("Failed to assemble assembly files"); .expect("Failed to assemble assembly files");
std::process::Command::new("ar") println!("cargo:rustc-link-arg={}", obj_path.display());
.current_dir(working_dir) // let _lib = format!("lib{}.a", file.file_stem().unwrap().to_str().unwrap());
.arg("crs") // std::process::Command::new("ar")
.arg(out_dir.join(lib)) // .current_dir(working_dir)
.arg(out_dir.join(obj)) // .arg("crs")
.status() // .arg(out_dir.join(lib))
.expect("Failed to create static library from object files"); // .arg(out_dir.join(obj))
println!( // .status()
"cargo:rustc-link-lib=static={}", // .expect("Failed to create static library from object files");
file.file_stem().unwrap().to_str().unwrap() // println!(
); // "cargo:rustc-link-lib=static={}",
// file.file_stem().unwrap().to_str().unwrap()
// );
} }
std::process::Command::new("../tools/asm2rust") std::process::Command::new("../tools/asm2rust")
.current_dir(working_dir) .current_dir(working_dir)
.args(&assembly_files) .args(assembly_files)
.args(&include_files) .args(include_files)
.arg("-o") .arg("-o")
.arg(out_dir .arg(out_dir.join("bindings.rs"))
.join("bindings.rs") .status()
) .expect("Failed to generate Rust bindings from assembly files");
.status().expect("Failed to generate Rust bindings from assembly files");
} }

View file

@ -1,4 +1,7 @@
#![feature(debug_closure_helpers)] #![feature(debug_closure_helpers, box_as_ptr, allocator_api)]
#[cfg(test)]
mod tests;
pub mod ffi { pub mod ffi {
#![allow( #![allow(
@ -12,14 +15,14 @@ pub mod ffi {
} }
#[repr(C)] #[repr(C)]
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct FFISlice { pub struct FFISlice {
pub ptr: *const u8, pub ptr: *const u8,
pub len: usize, pub len: usize,
} }
#[repr(transparent)] #[repr(transparent)]
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct MaybeFFISlice { pub struct MaybeFFISlice {
inner: FFISlice, inner: FFISlice,
} }
@ -40,20 +43,27 @@ impl MaybeFFISlice {
impl FFISlice { impl FFISlice {
/// # Safety /// # Safety
/// The caller must ensure that the slice is valid for type T. /// The caller must ensure that the slice is valid for type T, and lasts for 'a.
pub unsafe fn as_slice<T: Sized>(&self) -> &[T] { pub unsafe fn as_slice_unchecked<'a, T: Sized>(self) -> &'a [T] {
// SAFETY: The caller ensures that the FFISlice is valid for type T. // SAFETY: The caller ensures that the FFISlice is valid for type T.
unsafe { core::slice::from_raw_parts(self.ptr.cast(), self.len) } unsafe { core::slice::from_raw_parts(self.ptr.cast(), self.len) }
} }
pub fn as_bytes(&self) -> &[u8] {
/// # Safety
/// The caller ensures that the slice is valid byte slice.
/// Namely, the pointer must be well-aligned and point to `len` bytes, and
/// must last for at least 'a.
pub fn as_u8s_unchecked<'a>(self) -> &'a [u8] {
// SAFETY: The FFISlice is guaranteed to be a valid byte slice. // SAFETY: The FFISlice is guaranteed to be a valid byte slice.
unsafe { core::slice::from_raw_parts(self.ptr, self.len) } unsafe { self.as_slice_unchecked() }
} }
/// # Safety /// # Safety
/// The caller must ensure that the slice is a valid utf8 string. /// The caller must ensure that the slice is a valid utf8 string.
pub unsafe fn as_str(&self) -> &str { /// Furthermore, the pointer must be well-aligned, point to `len` bytes, and
/// must last for at least 'a.
pub unsafe fn as_str_unchecked<'a>(self) -> &'a str {
// SAFETY: The caller ensures that the FFISlice is a valid utf8 string. // SAFETY: The caller ensures that the FFISlice is a valid utf8 string.
unsafe { core::str::from_utf8_unchecked(self.as_bytes()) } unsafe { core::str::from_utf8_unchecked(self.as_u8s_unchecked()) }
} }
} }
@ -610,3 +620,11 @@ mod display {
} }
pub use display::{Displayed, DisplayedSliceExt}; pub use display::{Displayed, DisplayedSliceExt};
impl Default for ffi::Ast {
fn default() -> Self {
ffi::Ast {
nodes: vec::Vec::default(),
}
}
}

View file

@ -1,6 +1,6 @@
default rel default rel
section .bss section .data
align 8 align 8
free_list: resb 40 free_list: resb 40
@ -67,7 +67,7 @@ bump_new_block:
shr rax, 1 shr rax, 1
add rax, 1 add rax, 1
add rsi, rax add rsi, rax
mov rdx, mmap_alloc lea rdx, [rel mmap_alloc]
call vec_try_grow_with call vec_try_grow_with
pop rdi pop rdi
@ -141,6 +141,8 @@ bump_alloc:
lea rdi, [rel free_list] lea rdi, [rel free_list]
mov r12, [rdi + 8] mov r12, [rdi + 8]
xor r13, r13 xor r13, r13
cmp qword [rdi + 0], 0
je .init
.alloc_loop: .alloc_loop:
cmp r13, r12 cmp r13, r12
jae .no_block jae .no_block
@ -183,6 +185,11 @@ bump_alloc:
mov r12, r13 mov r12, r13
dec r13 dec r13
jmp .alloc_loop jmp .alloc_loop
.init:
call bump_init
mov rdi, [rsp] ; size
call bump_new_block
jmp .alloc_loop
.found_space: .found_space:
mov r12, [rsp + 32] ; block entry ptr mov r12, [rsp + 32] ; block entry ptr
mov rcx, [r12] ; block_ptr mov rcx, [r12] ; block_ptr

View file

@ -6,7 +6,7 @@ global str_to_int
;; rdi: pointer to input string ;; rdi: pointer to input string
;; rsi: length of input string ;; rsi: length of input string
;; dl: radix ;; dl: radix
;; fn str_to_int(s: *const u8, len: usize, radix: u8) -> i64 ;; define-fn: str_to_int(s: *const u8, len: usize, radix: u8) -> i64
str_to_int: str_to_int:
push rbp push rbp
mov rbp, rsp mov rbp, rsp
@ -73,7 +73,7 @@ str_to_int:
;; rsi: pointer to output buffer (at least 21 bytes) ;; rsi: pointer to output buffer (at least 21 bytes)
;; rdx: length of buffer ;; rdx: length of buffer
;; cl: radix ;; cl: radix
;; fn int_to_str2(value: i64, buffer: *mut u8, len: usize, radix: u8) -> (*mut u8, usize) ;; define-fn: int_to_str2(value: i64, buffer: *mut u8, len: usize, radix: u8) -> FFISlice
int_to_str2: int_to_str2:
push rbp push rbp
mov rbp, rsp mov rbp, rsp

View file

@ -1,3 +1,5 @@
default rel
section .text section .text
extern panic extern panic
extern strlen extern strlen
@ -143,8 +145,8 @@ global NUM_LEXEMES
section .text section .text
;; rdi: length of previously matched lexeme ;; rdi: length of previously matched lexeme
;; returns the length of the ident ;; returns the length of the ident, or 0 if not an ident
;; fn is_ident(lexeme_len: usize) -> usize ;; define-fn: is_ident(lexeme_len: usize) -> usize
is_ident: is_ident:
push rbp push rbp
mov rbp, rsp mov rbp, rsp
@ -376,8 +378,15 @@ skip_whitespaces:
ret ret
;; start-structs
;; struct RawLexeme {
;; token: u8,
;; slice: FFISlice,
;; }
;;
;; end-structs
;; rdi: pointer to out-struct ;; rdi: pointer to out-struct
;; fn find_lexeme() -> (u8, *const u8, usize) ;; define-fn: find_lexeme() -> RawLexeme
find_lexeme: find_lexeme:
push rbp push rbp
mov rbp, rsp mov rbp, rsp
@ -523,7 +532,11 @@ find_lexeme:
mov [rdi + 16], rax mov [rdi + 16], rax
jmp .epilogue jmp .epilogue
;; ```rust
;; use crate::MaybeFFISlice;
;; ```
;; dil: expected token ;; dil: expected token
;; define-fn: fn expect_token(expected: u8) -> MaybeFFISlice
expect_token: expect_token:
push rbp push rbp
mov rbp, rsp mov rbp, rsp
@ -552,6 +565,7 @@ expect_token:
;; Returns the next token if it matches the expected token, else panics ;; Returns the next token if it matches the expected token, else panics
;; dil: expected token ;; dil: expected token
;; define-fn: fn unwrap_token(expected: u8) -> FFISlice
unwrap_token: unwrap_token:
push rbp push rbp
mov rbp, rsp mov rbp, rsp
@ -566,6 +580,7 @@ unwrap_token:
;; returns 0 if token not found, else returns lexeme (ptr, len) ;; returns 0 if token not found, else returns lexeme (ptr, len)
;; doesn't advance the cursor ;; doesn't advance the cursor
;; dil: expected token ;; dil: expected token
;; define-fn: fn peek_expect_token(expected: u8) -> MaybeFFISlice
peek_expect_token: peek_expect_token:
push rbp push rbp
mov rbp, rsp mov rbp, rsp
@ -579,6 +594,7 @@ peek_expect_token:
;; returns the next lexeme without advancing the cursor ;; returns the next lexeme without advancing the cursor
;; rdi: out-struct pointer ;; rdi: out-struct pointer
;; define-fn: fn peek_lexeme() -> RawLexeme
peek_lexeme: peek_lexeme:
push rbp push rbp
mov rbp, rsp mov rbp, rsp
@ -593,6 +609,7 @@ peek_lexeme:
ret ret
;; Skips one token ahead, without returning it. ;; Skips one token ahead, without returning it.
;; define-fn: fn skip_token()
skip_token: skip_token:
push rbp push rbp
mov rbp, rsp mov rbp, rsp
@ -603,6 +620,7 @@ skip_token:
add rsp, 24 add rsp, 24
pop rbp pop rbp
;; define-fn: fn tokeniser_get_cursor() -> usize
tokeniser_get_cursor: tokeniser_get_cursor:
mov rax, [rel cursor] mov rax, [rel cursor]
ret ret

View file

@ -345,7 +345,7 @@ vec_remove:
;; rsi: desired size ;; rsi: desired size
;; define-fn: fn vec_try_grow(vec: *mut BlobVec, new_size: usize) -> bool ;; define-fn: fn vec_try_grow(vec: *mut BlobVec, new_size: usize) -> bool
vec_try_grow: vec_try_grow:
mov rdx, bump_alloc lea rdx, [rel bump_alloc]
call vec_try_grow_with call vec_try_grow_with
ret ret