use cargo
This commit is contained in:
parent
fe350da24d
commit
32b8e84891
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,2 +1,4 @@
|
|||
/.direnv/
|
||||
lang/target
|
||||
lang/libcompiler/target
|
||||
/target/
|
||||
|
|
|
|||
36
Cargo.lock
generated
Normal file
36
Cargo.lock
generated
Normal file
|
|
@ -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"
|
||||
7
Cargo.toml
Normal file
7
Cargo.toml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
[workspace]
|
||||
resolver = "3"
|
||||
|
||||
members = [
|
||||
"lang/libcompiler",
|
||||
"lang/typeck",
|
||||
]
|
||||
9
lang/libcompiler/Cargo.toml
Normal file
9
lang/libcompiler/Cargo.toml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "libcompiler"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0"
|
||||
70
lang/libcompiler/build.rs
Normal file
70
lang/libcompiler/build.rs
Normal file
|
|
@ -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");
|
||||
}
|
||||
590
lang/libcompiler/src/lib.rs
Normal file
590
lang/libcompiler/src/lib.rs
Normal file
|
|
@ -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<FFISlice> {
|
||||
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<T: Sized>(&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<T> {
|
||||
pub vec: BlobVec,
|
||||
_marker: core::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Default for Vec<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for Vec<T> {
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: The vec is valid and owned by self.
|
||||
unsafe {
|
||||
vec_drop(&mut self.vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Vec<T> {
|
||||
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<T>(ptr: *mut ()) {
|
||||
unsafe {
|
||||
core::ptr::drop_in_place::<T>(ptr as *mut T);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
vec_init_with(
|
||||
&mut vec,
|
||||
core::mem::size_of::<T>(),
|
||||
Some(drop_fn::<T>),
|
||||
capacity,
|
||||
);
|
||||
}
|
||||
|
||||
Self {
|
||||
vec,
|
||||
_marker: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
assert_eq!(self.vec.elem_size, core::mem::size_of::<T>());
|
||||
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::<T>());
|
||||
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<[T]>, Box<[core::mem::ManuallyDrop<T>]>>(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<[T]>, Box<[core::mem::ManuallyDrop<T>]>>(elements);
|
||||
vec_insert_many(
|
||||
&mut self.vec,
|
||||
index,
|
||||
elements.as_ptr() as *const _,
|
||||
elements.len(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Option<T> {
|
||||
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<F>(&self, elem: &T, mut cmp: F) -> Option<usize>
|
||||
where
|
||||
F: FnMut(&T, &T) -> bool,
|
||||
{
|
||||
extern "C" fn cmp_trampoline<T, F: FnMut(&T, &T) -> 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::<T, F>,
|
||||
&raw mut cmp as *mut (),
|
||||
);
|
||||
if index == usize::MAX {
|
||||
None
|
||||
} else {
|
||||
Some(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn binary_search_by<F>(&self, elem: &T, mut cmp: F) -> Result<usize, usize>
|
||||
where
|
||||
F: FnMut(&T, &T) -> i32,
|
||||
{
|
||||
extern "C" fn cmp_trampoline<T, F: FnMut(&T, &T) -> 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::<T, F>,
|
||||
&raw mut cmp as *mut (),
|
||||
);
|
||||
if vacant { Err(index) } else { Ok(index) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_sorted<F>(&mut self, elem: T, mut cmp: F) -> Result<usize, usize>
|
||||
where
|
||||
F: FnMut(&T, &T) -> i32,
|
||||
{
|
||||
extern "C" fn cmp_trampoline<T, F: FnMut(&T, &T) -> 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::<T, F>,
|
||||
&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::<crate::ffi::AstCallExpr>().read() };
|
||||
write!(f, "Call(callee: {}, params: {:?})", call.callee, unsafe {
|
||||
std::slice::from_raw_parts(call.params.cast::<u64>(), call.params_len)
|
||||
},)
|
||||
}
|
||||
AST_AS => {
|
||||
let as_expr = unsafe { self.data.cast::<crate::ffi::AstAsExpr>().read() };
|
||||
write!(f, "As(expr: {}, target_type: {})", as_expr.expr, as_expr.ty)
|
||||
}
|
||||
AST_ARG => {
|
||||
let arg = unsafe { self.data.cast::<crate::ffi::AstArgument>().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::<crate::ffi::AstVarRef>().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::<crate::ffi::AstVarDecl>().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::<crate::ffi::BinaryExpr>().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::<crate::ffi::AstFunction>().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::<u64>(), func.args_len)
|
||||
},
|
||||
func.return_type,
|
||||
func.body
|
||||
)
|
||||
}
|
||||
AST_BLOCK => {
|
||||
write!(f, "Block(statements: {:?})", unsafe {
|
||||
std::slice::from_raw_parts(self.data.cast::<u64>(), self.extra)
|
||||
})
|
||||
}
|
||||
AST_IF => {
|
||||
let if_node = unsafe { self.data.cast::<crate::ffi::AstIfExpr>().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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<extern "C" fn(*mut u8)>,
|
||||
;; drop: Option<unsafe extern "C" fn(*mut ())>,
|
||||
;; }
|
||||
;; 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<fn(*mut u8)>)
|
||||
;; define-fn: fn vec_init(vec: *mut BlobVec, item_size: usize, drop: Option<unsafe extern "C" fn(*mut ())>)
|
||||
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<fn(*mut u8)>, capacity: usize)
|
||||
;; define-fn: fn vec_init_with(vec: *mut BlobVec, item_size: usize, drop: Option<unsafe extern "C" fn(*mut ())>, 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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
6
lang/typeck/Cargo.toml
Normal file
6
lang/typeck/Cargo.toml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "typeck"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
14
lang/typeck/src/lib.rs
Normal file
14
lang/typeck/src/lib.rs
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
1
tools/asm2rust
Symbolic link
1
tools/asm2rust
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../lang/tests/asm_to_rust.py
|
||||
Loading…
Reference in a new issue