diff --git a/.gitignore b/.gitignore index 5388342..9453346 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /.direnv/ lang/target +lang/libcompiler/target +/target/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..03c5ac2 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,36 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "cc" +version = "1.2.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + +[[package]] +name = "libcompiler" +version = "0.1.0" +dependencies = [ + "cc", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "typeck" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..32b830b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[workspace] +resolver = "3" + +members = [ + "lang/libcompiler", + "lang/typeck", +] \ No newline at end of file diff --git a/lang/libcompiler/Cargo.toml b/lang/libcompiler/Cargo.toml new file mode 100644 index 0000000..3f35239 --- /dev/null +++ b/lang/libcompiler/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "libcompiler" +version = "0.1.0" +edition = "2024" + +[dependencies] + +[build-dependencies] +cc = "1.0" \ No newline at end of file diff --git a/lang/libcompiler/build.rs b/lang/libcompiler/build.rs new file mode 100644 index 0000000..eeb4729 --- /dev/null +++ b/lang/libcompiler/build.rs @@ -0,0 +1,70 @@ +use std::path::Path; + +fn main() { + let out_dir = std::env::var_os("OUT_DIR").unwrap(); + let out_dir = Path::new(&out_dir); + let manifest_dir = std::env::var_os("CARGO_MANIFEST_DIR").unwrap(); + let manifest_dir = Path::new(&manifest_dir); + + let assembly_files = [ + "src/alloc.asm", + "src/ast.asm", + "src/codegen.asm", + "src/vec.asm", + "src/tokeniser.asm", + "src/lib.asm", + "src/int_to_str.asm", + "src/file.asm", + ]; + + let include_files = ["src/tokeniser.inc", "src/ast.inc"]; + + println!("cargo:rerun-if-changed=build.rs"); + for file in assembly_files.iter().chain(include_files.iter()) { + println!( + "cargo:rerun-if-changed={}/{}", + manifest_dir.parent().unwrap().display(), + file + ); + } + + println!("cargo:rustc-link-search=native={}", out_dir.display()); + let working_dir = manifest_dir.parent().unwrap(); + for file in assembly_files.iter().map(|f| Path::new(f)) { + let path = working_dir.join(file); + let obj = file.with_extension("o").file_name().unwrap().to_owned(); + let lib = format!("lib{}.a", file.file_stem().unwrap().to_str().unwrap()); + std::process::Command::new("nasm") + .current_dir(working_dir) + .arg(path) + .arg("-g") + .arg("-f") + .arg("elf64") + .arg("-o") + .arg(out_dir.join(&obj)) + .status() + .expect("Failed to assemble assembly files"); + std::process::Command::new("ar") + .current_dir(working_dir) + .arg("crs") + .arg(out_dir.join(lib)) + .arg(out_dir.join(obj)) + .status() + .expect("Failed to create static library from object files"); + println!( + "cargo:rustc-link-lib=static={}", + file.file_stem().unwrap().to_str().unwrap() + ); + } + + + std::process::Command::new("../tools/asm2rust") + .current_dir(working_dir) + .args(&assembly_files) + .args(&include_files) + .arg("-o") + .arg(out_dir + .join("bindings.rs") +) + .status().expect("Failed to generate Rust bindings from assembly files"); +} diff --git a/lang/libcompiler/src/lib.rs b/lang/libcompiler/src/lib.rs new file mode 100644 index 0000000..490dcd9 --- /dev/null +++ b/lang/libcompiler/src/lib.rs @@ -0,0 +1,590 @@ +#![feature(debug_closure_helpers)] + +pub mod ffi { + #![allow( + non_camel_case_types, + dead_code, + non_upper_case_globals, + improper_ctypes + )] + + include!(concat!(env!("OUT_DIR"), "/bindings.rs")); +} + +#[repr(C)] +#[derive(Debug, PartialEq, Eq)] +pub struct FFISlice { + pub ptr: *const u8, + pub len: usize, +} + +#[repr(transparent)] +#[derive(Debug, PartialEq, Eq)] +pub struct MaybeFFISlice { + inner: FFISlice, +} + +impl MaybeFFISlice { + pub fn is_none(&self) -> bool { + self.inner.ptr.is_null() + } + + pub fn into_option(self) -> Option { + if self.is_none() { + None + } else { + Some(self.inner) + } + } +} + +impl FFISlice { + /// # Safety + /// The caller must ensure that the slice is valid for type T. + pub unsafe fn as_slice(&self) -> &[T] { + // SAFETY: The caller ensures that the FFISlice is valid for type T. + unsafe { core::slice::from_raw_parts(self.ptr.cast(), self.len) } + } + pub fn as_bytes(&self) -> &[u8] { + // SAFETY: The FFISlice is guaranteed to be a valid byte slice. + unsafe { core::slice::from_raw_parts(self.ptr, self.len) } + } + /// # Safety + /// The caller must ensure that the slice is a valid utf8 string. + pub unsafe fn as_str(&self) -> &str { + // SAFETY: The caller ensures that the FFISlice is a valid utf8 string. + unsafe { core::str::from_utf8_unchecked(self.as_bytes()) } + } +} + +pub mod vec { + #![allow(dead_code)] + + impl Default for BlobVec { + fn default() -> Self { + Self { + data: core::ptr::null_mut(), + len: 0, + cap: 0, + elem_size: 0, + drop: None, + } + } + } + + unsafe impl Send for BlobVec {} + unsafe impl Sync for BlobVec {} + + use super::ffi::*; + + #[repr(transparent)] + #[derive(Debug)] + pub struct Vec { + pub vec: BlobVec, + _marker: core::marker::PhantomData, + } + + impl Default for Vec { + fn default() -> Self { + Self::new() + } + } + + impl Drop for Vec { + fn drop(&mut self) { + // SAFETY: The vec is valid and owned by self. + unsafe { + vec_drop(&mut self.vec); + } + } + } + + impl Vec { + pub fn new() -> Self { + Self::new_with(32) + } + + pub fn new_with(capacity: usize) -> Self { + let mut vec = BlobVec { + data: core::ptr::null_mut(), + len: 0, + cap: 0, + elem_size: 0, + drop: None, + }; + + unsafe extern "C" fn drop_fn(ptr: *mut ()) { + unsafe { + core::ptr::drop_in_place::(ptr as *mut T); + } + } + + unsafe { + vec_init_with( + &mut vec, + core::mem::size_of::(), + Some(drop_fn::), + capacity, + ); + } + + Self { + vec, + _marker: core::marker::PhantomData, + } + } + + pub fn as_slice(&self) -> &[T] { + assert_eq!(self.vec.elem_size, core::mem::size_of::()); + unsafe { core::slice::from_raw_parts(self.vec.data as *const T, self.vec.len) } + } + + pub fn as_slice_mut(&mut self) -> &mut [T] { + assert_eq!(self.vec.elem_size, core::mem::size_of::()); + unsafe { core::slice::from_raw_parts_mut(self.vec.data as *mut T, self.vec.len) } + } + + pub fn extend(&mut self, elements: Box<[T]>) { + unsafe { + let elements = + core::mem::transmute::, Box<[core::mem::ManuallyDrop]>>(elements); + vec_extend(&mut self.vec, elements.as_ptr() as *const _, elements.len()); + } + } + + pub fn push(&mut self, value: T) { + let value = core::mem::ManuallyDrop::new(value); + unsafe { + vec_push(&mut self.vec, &raw const value as *const T as *const _); + } + } + + pub fn insert(&mut self, value: T, index: usize) { + if index > self.vec.len { + return; + } + let value = core::mem::ManuallyDrop::new(value); + unsafe { + vec_insert( + &mut self.vec, + index, + &raw const value as *const T as *const _, + ); + } + } + + pub fn insert_many(&mut self, index: usize, elements: Box<[T]>) { + unsafe { + let elements = + core::mem::transmute::, Box<[core::mem::ManuallyDrop]>>(elements); + vec_insert_many( + &mut self.vec, + index, + elements.as_ptr() as *const _, + elements.len(), + ); + } + } + + pub fn pop(&mut self) -> Option { + if self.vec.len == 0 { + return None; + } + unsafe { + let ptr = vec_get(&mut self.vec, self.vec.len - 1) as *mut T; + let value = ptr.read(); + vec_pop(&mut self.vec); + Some(value) + } + } + + pub fn get(&self, index: usize) -> Option<&T> { + if index >= self.vec.len { + return None; + } + unsafe { + let ptr = vec_get(&raw const self.vec as *mut _, index) as *mut T; + Some(&*ptr) + } + } + + pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { + if index >= self.vec.len { + return None; + } + unsafe { + let ptr = vec_get(&raw mut self.vec, index) as *mut T; + Some(&mut *ptr) + } + } + + pub fn remove(&mut self, index: usize) { + if index >= self.vec.len { + return; + } + unsafe { + vec_remove(&mut self.vec, index); + } + } + + pub fn len(&self) -> usize { + self.vec.len + } + + pub fn is_empty(&self) -> bool { + self.vec.len == 0 + } + + pub fn position(&self, elem: &T, mut cmp: F) -> Option + where + F: FnMut(&T, &T) -> bool, + { + extern "C" fn cmp_trampoline bool>( + f: *const (), + a: *const (), + b: *const (), + ) -> bool { + let f = unsafe { &mut *(f as *mut F) }; + let a = unsafe { &*(a as *const T) }; + let b = unsafe { &*(b as *const T) }; + f(a, b) + } + + unsafe { + let index = vec_find( + &raw const self.vec as *mut _, + elem as *const T as *const _, + cmp_trampoline::, + &raw mut cmp as *mut (), + ); + if index == usize::MAX { + None + } else { + Some(index) + } + } + } + + pub fn binary_search_by(&self, elem: &T, mut cmp: F) -> Result + where + F: FnMut(&T, &T) -> i32, + { + extern "C" fn cmp_trampoline i32>( + f: *const (), + a: *const (), + b: *const (), + ) -> i32 { + let f = unsafe { &mut *(f as *mut F) }; + let a = unsafe { &*(a as *const T) }; + let b = unsafe { &*(b as *const T) }; + f(a, b) + } + + unsafe { + let (index, vacant) = vec_binary_search_by( + &raw const self.vec as *mut _, + elem as *const T as *const _, + cmp_trampoline::, + &raw mut cmp as *mut (), + ); + if vacant { Err(index) } else { Ok(index) } + } + } + + pub fn insert_sorted(&mut self, elem: T, mut cmp: F) -> Result + where + F: FnMut(&T, &T) -> i32, + { + extern "C" fn cmp_trampoline i32>( + f: *const (), + a: *const (), + b: *const (), + ) -> i32 { + let f = unsafe { &mut *(f as *mut F) }; + let a = unsafe { &*(a as *const T) }; + let b = unsafe { &*(b as *const T) }; + f(a, b) + } + + let mut elem = core::mem::ManuallyDrop::new(elem); + + unsafe { + let (index, _inserted) = vec_insert_sorted( + &raw const self.vec as *mut _, + &raw mut elem as *const _, + cmp_trampoline::, + &raw mut cmp as *mut (), + ); + Ok(index) + } + } + } +} + +mod display { + use super::ffi::{self, Ast, AstNode}; + + impl core::fmt::Display for AstNode { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + use crate::ffi::{ + AST_ADDRESS_OF, AST_ARG, AST_AS, AST_ASSIGNMENT, AST_BINARY_OP, AST_BLOCK, + AST_CALL, AST_DEREF, AST_FUNCTION, AST_IF, AST_NUMBER, AST_PLACE_TO_VALUE, + AST_RETURN_STATEMENT, AST_VALUE_TO_PLACE, AST_VAR_DECL, AST_VAR_REF, BinaryExpr, + }; + match self.kind { + AST_NUMBER => { + write!(f, "Number({})", self.data as usize) + } + AST_DEREF => { + write!(f, "Deref(expr: {})", self.data as usize) + } + AST_ADDRESS_OF => { + write!(f, "AddressOf(expr: {})", self.data as usize) + } + AST_CALL => { + let call = unsafe { self.data.cast::().read() }; + write!(f, "Call(callee: {}, params: {:?})", call.callee, unsafe { + std::slice::from_raw_parts(call.params.cast::(), call.params_len) + },) + } + AST_AS => { + let as_expr = unsafe { self.data.cast::().read() }; + write!(f, "As(expr: {}, target_type: {})", as_expr.expr, as_expr.ty) + } + AST_ARG => { + let arg = unsafe { self.data.cast::().read() }; + write!( + f, + "Arg(name: {:?}, arg_type: {})", + unsafe { + std::str::from_utf8(std::slice::from_raw_parts(arg.name, arg.name_len)) + }, + arg.arg_type, + ) + } + AST_VAR_REF => { + let var_ref = unsafe { self.data.cast::().read() }; + if var_ref.resolved != u64::MAX { + write!(f, "VarRef({})", var_ref.resolved) + } else { + write!(f, "VarRef(name: {:?})", unsafe { + std::str::from_utf8(std::slice::from_raw_parts( + var_ref.name, + var_ref.name_len, + )) + },) + } + } + AST_VAR_DECL => { + let var_decl = unsafe { self.data.cast::().read() }; + write!( + f, + "VarDecl(name: {:?}, var_type: {})", + unsafe { + std::str::from_utf8(std::slice::from_raw_parts( + var_decl.name, + var_decl.name_len, + )) + }, + var_decl.var_type, + ) + } + AST_ASSIGNMENT => { + write!( + f, + "Assignment(dest: {}, src: {})", + self.data as usize, self.extra + ) + } + AST_BINARY_OP => { + let BinaryExpr { + left, + operator, + right, + } = unsafe { self.data.cast::().read() }; + write!( + f, + "BinaryOp(op: {}, left: {}, right: {})", + operator, left, right + ) + } + AST_RETURN_STATEMENT => { + let return_expr_id = self.data as usize; + write!(f, "ReturnStatement(expr: {})", return_expr_id) + } + AST_FUNCTION => { + let func = unsafe { self.data.cast::().read() }; + write!( + f, + "Function(name: {:?}, args: {:?}, return_type: {}, body: {})", + unsafe { + std::str::from_utf8(std::slice::from_raw_parts( + func.name, + func.name_len, + )) + }, + unsafe { + std::slice::from_raw_parts(func.args.cast::(), func.args_len) + }, + func.return_type, + func.body + ) + } + AST_BLOCK => { + write!(f, "Block(statements: {:?})", unsafe { + std::slice::from_raw_parts(self.data.cast::(), self.extra) + }) + } + AST_IF => { + let if_node = unsafe { self.data.cast::().read() }; + write!( + f, + "If(cond: {}, then_branch: {}, else_branch: {:?})", + if_node.condition, + if_node.then, + match if_node.else_ { + u64::MAX => None, + v => Some(v), + } + ) + } + AST_PLACE_TO_VALUE => { + write!(f, "PlaceToValue(place: {})", self.data as usize) + } + AST_VALUE_TO_PLACE => { + write!(f, "ValueToPlace(value: {})", self.data as usize) + } + kind => write!(f, "UnknownNode(kind: {kind})"), + } + } + } + + impl core::fmt::Display for Ast { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + writeln!(f, "[")?; + for (i, item) in self.nodes.as_slice().iter().enumerate() { + if i > 0 { + writeln!(f, ", ")?; + } + write!(f, "\t{i}: {}", item)?; + } + write!(f, "\n]") + } + } + + impl core::fmt::Display for ffi::SymEntry { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("SymEntry") + .field_with("key", |f| { + f.debug_struct("Key") + .field_with("kind", |f| { + f.write_str(match self.key.kind { + ffi::SYM_KEY_SCOPE => "Scope", + ffi::SYM_KEY_SCOPE_NAME => "ScopeName", + ffi::SYM_KEY_PARENT_SCOPE => "ParentScope", + ffi::SYM_KEY_ARG => "Argument", + ffi::SYM_KEY_VAR => "Variable", + ffi::SYM_KEY_FUNCTION => "Function", + _ => "Unknown", + }) + }) + .field("scope", &self.key.scope_index) + .field("span", &self.key.span) + .field_with("ident", |f| { + f.write_str(unsafe { + core::str::from_utf8_unchecked(core::slice::from_raw_parts( + self.key.ident, + self.key.ident_len, + )) + }) + }) + .finish() + }) + .field_with("value", |f| { + let stct = &mut f.debug_struct("Value"); + if self.extra == 0 { + stct.field("ast_index", &self.index).finish() + } else if self.index != 0 { + stct.field_with("ident", |f| { + f.write_str(unsafe { + core::str::from_utf8_unchecked(core::slice::from_raw_parts( + self.index as *const u8, + self.extra as usize, + )) + }) + }) + .finish() + } else { + stct.field("index", &self.index) + .field("extra", &self.extra) + .finish() + } + }) + .finish() + } + } + + impl core::fmt::Display for ffi::Type { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + use ffi::{ + TYPE_BOOL, TYPE_F32, TYPE_F64, TYPE_I8, TYPE_I16, TYPE_I32, TYPE_I64, TYPE_ISIZE, + TYPE_POINTER, TYPE_STR, TYPE_U8, TYPE_U16, TYPE_U32, TYPE_U64, TYPE_USIZE, + TYPE_VOID, + }; + match self.kind { + TYPE_VOID => { + write!(f, "void") + } + TYPE_BOOL => { + write!(f, "bool") + } + TYPE_I32 => { + write!(f, "i32") + } + TYPE_U32 => { + write!(f, "u32") + } + TYPE_STR => { + write!(f, "str") + } + TYPE_POINTER => { + let pointee = unsafe { (self.data as *const ffi::Type).read() }; + write!(f, "*{pointee}",) + } + TYPE_I8 => { + write!(f, "i8") + } + TYPE_U8 => { + write!(f, "u8") + } + TYPE_I16 => { + write!(f, "i16") + } + TYPE_U16 => { + write!(f, "u16") + } + TYPE_I64 => { + write!(f, "i64") + } + TYPE_U64 => { + write!(f, "u64") + } + TYPE_F32 => { + write!(f, "f32") + } + TYPE_F64 => { + write!(f, "f64") + } + TYPE_USIZE => { + write!(f, "usize") + } + TYPE_ISIZE => { + write!(f, "isize") + } + _ => { + write!(f, "UnknownType") + } + } + } + } +} diff --git a/lang/src/ast.asm b/lang/src/ast.asm index 990c088..2900273 100644 --- a/lang/src/ast.asm +++ b/lang/src/ast.asm @@ -2139,6 +2139,7 @@ ast_resolve_var_refs_for_each: ret .panic: call panic +;; } ast_resolve_var_refs_for_each ;; rdi: Ast ;; rsi: *mut SymbolTable diff --git a/lang/src/codegen.asm b/lang/src/codegen.asm index 1e258b1..0afb1b3 100644 --- a/lang/src/codegen.asm +++ b/lang/src/codegen.asm @@ -2099,10 +2099,12 @@ codegen_expr: ;; register: u8, ;; width: u16, ;; len: u16, +;; align: u8, +;; bitset: u8, ;; value: u64, ;; } ;; end-structs -;; or: register: u4, width: u4 +;; bitset[0]: signed section .rdata ;; start-consts ; Register containing a Value diff --git a/lang/src/vec.asm b/lang/src/vec.asm index 3053a8a..e2cd6d3 100644 --- a/lang/src/vec.asm +++ b/lang/src/vec.asm @@ -35,11 +35,11 @@ global vec_tests ;; Byte vector structure ;; start-structs ;; struct BlobVec { -;; data: *mut u8, +;; data: *mut (), ;; len: usize, ;; cap: usize, ;; elem_size: usize, -;; drop: Option, +;; drop: Option, ;; } ;; end-structs ;; size: 40 bytes @@ -50,7 +50,7 @@ global vec_tests ;; rdi: pointer to Vec struct ;; rsi: item_size ;; rdx: drop function pointer -;; fn vec_init(vec: *mut Vec, item_size: usize, drop: Option) +;; define-fn: fn vec_init(vec: *mut BlobVec, item_size: usize, drop: Option) vec_init: push rbp mov rbp, rsp @@ -82,7 +82,7 @@ vec_init: ;; rsi: item_size ;; rdx: drop function pointer ;; rcx: capacity -;; fn vec_init_with(vec: *mut Vec, item_size: usize, drop: Option, capacity: usize) +;; define-fn: fn vec_init_with(vec: *mut BlobVec, item_size: usize, drop: Option, capacity: usize) vec_init_with: push rbp mov rbp, rsp @@ -116,7 +116,7 @@ vec_init_with: ;; rdi: pointer to Vec struct ;; rsi: index ;; rdx: pointer to default value -;; fn vec_get(vec: *mut Vec, index: usize, default: *mut u8) -> *mut u8 +;; define-fn: fn vec_get_or(vec: *mut BlobVec, index: usize, default: *mut ()) -> *mut () vec_get_or: push rbp mov rbp, rsp @@ -138,7 +138,7 @@ vec_get_or: ;; rdi: pointer to Vec struct ;; rsi: index -;; fn vec_get(vec: *mut Vec, index: usize) -> *mut u8 +;; define-fn: fn vec_get(vec: *mut BlobVec, index: usize) -> *mut () vec_get: push rbp mov rbp, rsp @@ -162,7 +162,7 @@ vec_get: ;; rdi: pointer to Vec struct ;; rsi: pointer to data to push ;; returns the index at which the item was pushed (the old length of the vector) -;; fn vec_push(vec: *mut Vec, data: &[u8]) -> usize +;; define-fn: fn vec_push(vec: *mut BlobVec, data: *const ()) -> usize vec_push: push rbp mov rbp, rsp @@ -196,7 +196,7 @@ vec_push: ;; rdi: pointer to Vec struct -;; fn vec_pop(vec: *mut Vec) +;; define-fn: fn vec_pop(vec: *mut BlobVec) vec_pop: push rbp mov rbp, rsp @@ -216,7 +216,7 @@ vec_pop: ret ;; rdi: pointer to Vec struct -;; fn vec_pop(vec: *mut Vec) +;; define-fn: fn vec_drop_last(vec: *mut BlobVec) vec_drop_last: push rbp mov rbp, rsp @@ -250,7 +250,7 @@ vec_drop_last: ;; rdi: pointer to Vec struct ;; rsi: index a ;; rdx: index b -;; fn vec_swap(vec: *mut Vec, a: usize, b: usize) +;; define-fn: fn vec_swap(vec: *mut BlobVec, a: usize, b: usize) vec_swap: push rbp mov rbp, rsp @@ -297,7 +297,7 @@ vec_swap: ;; rdi: pointer to Vec struct ;; rsi: index -;; fn vec_remove(vec: *mut Vec, index: usize) +;; define-fn: fn vec_remove(vec: *mut BlobVec, index: usize) vec_remove: push rbp mov rbp, rsp @@ -343,7 +343,7 @@ vec_remove: ;; essentially a reserve() function ;; rdi: pointer to Vec struct ;; rsi: desired size -;; fn vec_try_grow(vec: *mut Vec, new_size: usize) -> bool +;; define-fn: fn vec_try_grow(vec: *mut BlobVec, new_size: usize) -> bool vec_try_grow: mov rdx, bump_alloc call vec_try_grow_with @@ -353,7 +353,7 @@ vec_try_grow: ;; rdi: pointer to Vec struct ;; rsi: desired size ;; rdx: allocate function pointer -;; fn vec_try_grow(vec: *mut Vec, new_size: usize) -> bool +;; define-fn: fn vec_try_grow_with(vec: *mut BlobVec, new_size: usize, alloc: unsafe extern "C" fn(usize, usize) -> *const ()) -> bool vec_try_grow_with: push rbp mov rbp, rsp @@ -407,6 +407,7 @@ vec_try_grow_with: ret ;; rdi: pointer to Vec struct +;; define-fn: fn vec_drop(vec: *mut BlobVec) vec_drop: push rbp mov rbp, rsp @@ -449,6 +450,7 @@ vec_drop: ;; rsi: poiter to object to find ;; rdx: compare function fn(ctx: *const (), a: *const T, b: *const T) -> bool ;; rcx: compare_fn context +;; define-fn: fn vec_find(vec: *mut BlobVec, object: *const (), compare: unsafe extern "C" fn(ctx: *const (), a: *const (), b: *const ()) -> bool, ctx: *const ()) -> usize vec_find: push rbp mov rbp, rsp @@ -500,7 +502,7 @@ vec_find: ;; rdi: pointer to Vec struct ;; rsi : index ;; rdx: pointer to data to insert -;; fn vec_insert(vec: *mut Vec, index: usize, data: *const T) +;; define-fn: fn vec_insert(vec: *mut BlobVec, index: usize, data: *const ()) vec_insert: push rbp mov rbp, rsp @@ -552,7 +554,7 @@ vec_insert: ;; rsi : index ;; rdx: pointer to data to insert ;; rcx: count -;; define-fn: fn vec_insert_many(vec: *mut BlobVec, index: usize, data: *const u8, count: usize) +;; define-fn: fn vec_insert_many(vec: *mut BlobVec, index: usize, data: *const (), count: usize) vec_insert_many: push rbp mov rbp, rsp @@ -612,7 +614,7 @@ vec_insert_many: ;; rsi: pointer to key ;; rdx: compare function fn(ctx: *const (), a: *const T, b: *const T) -> i32 ;; rcx: compare_fn context -;;fn vec_binary_search_by(vec: *mut Vec, key: *const T, compare: fn(ctx: *const (), a: *const T, b: *const T) -> i32, ctx: *const ()) -> (usize, bool) +;; define-fn: fn vec_binary_search_by(vec: *mut BlobVec, key: *const (), compare: unsafe extern "C" fn(ctx: *const (), a: *const (), b: *const ()) -> i32, ctx: *const ()) -> (usize, bool) vec_binary_search_by: push rbp mov rbp, rsp @@ -684,7 +686,7 @@ vec_binary_search_by: ;; rsi: pointer to key ;; rdx: compare function fn(ctx: *const (), a: *const T, b: *const T) -> i32 ;; rcx: compare_fn context -;;fn vec_insert_sorted(vec: *mut Vec, key: *const T, compare: fn(ctx: *const (), a: *const T, b: *const T) -> i32, ctx: *const ()) -> (usize, bool) +;;define-fn: fn vec_insert_sorted(vec: *mut BlobVec, key: *const (), compare: unsafe extern "C" fn(ctx: *const (), a: *const (), b: *const ()) -> i32, ctx: *const ()) -> (usize, bool) vec_insert_sorted: push rbp mov rbp, rsp @@ -711,9 +713,9 @@ vec_insert_sorted: ret ;; rdi: *Vec -;; rsi: *const u8 +;; rsi: *const () ;; rdx: number of elements -;; define-fn: fn vec_extend(vec: *mut BlobVec, elements: *const u8, count: usize) -> () +;; define-fn: fn vec_extend(vec: *mut BlobVec, elements: *const (), count: usize) -> () vec_extend: push rbp mov rbp, rsp diff --git a/lang/tests/asm_to_rust.py b/lang/tests/asm_to_rust.py index fca691c..64682f7 100755 --- a/lang/tests/asm_to_rust.py +++ b/lang/tests/asm_to_rust.py @@ -231,7 +231,7 @@ def parse_file(path: Path) -> Dict[str, Any]: def render_rust(function_sigs: List[str], consts: List[Tuple[str, str, str]], structs: List[Tuple[str, List[str]]], rust_blocks: List[List[str]]) -> str: parts: List[str] = [] - parts.append('#![allow(non_camel_case_types, dead_code, non_upper_case_globals, improper_ctypes)]') + # parts.append('#![allow(non_camel_case_types, dead_code, non_upper_case_globals, improper_ctypes)]') parts.append('// Auto-generated Rust bindings from assembly source\n') # Functions: wrap in single extern "C" block if any diff --git a/lang/typeck/Cargo.toml b/lang/typeck/Cargo.toml new file mode 100644 index 0000000..16719f0 --- /dev/null +++ b/lang/typeck/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "typeck" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/lang/typeck/src/lib.rs b/lang/typeck/src/lib.rs new file mode 100644 index 0000000..b93cf3f --- /dev/null +++ b/lang/typeck/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/tools/asm2rust b/tools/asm2rust new file mode 120000 index 0000000..7d0d1d2 --- /dev/null +++ b/tools/asm2rust @@ -0,0 +1 @@ +../lang/tests/asm_to_rust.py \ No newline at end of file