From 92b262d599f83d629e9f75bd492c58aab34a3672 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Adri=C3=A1n=20Arroyo=20Calle?= Date: Sat, 25 Feb 2023 22:27:28 +0100 Subject: [PATCH] Macroization of the code --- src/ffi.rs | 211 ++++++++++++++++++---------------- src/machine/machine_errors.rs | 19 +++ src/machine/system_calls.rs | 7 +- 3 files changed, 136 insertions(+), 101 deletions(-) diff --git a/src/ffi.rs b/src/ffi.rs index e8f2bc4b..8b0b5db9 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -120,61 +120,32 @@ impl ForeignFunctionTable { Ok(()) } - fn build_pointer_args(mut args: &mut Vec, type_args: &Vec<*mut ffi_type>, structs_table: &mut HashMap) -> Result { + fn build_pointer_args(args: &mut Vec, type_args: &Vec<*mut ffi_type>, structs_table: &mut HashMap) -> Result { let mut pointers = Vec::with_capacity(args.len()); let mut memory = Vec::new(); for i in 0..args.len() { let field_type = type_args[i]; unsafe { + macro_rules! push_int { + ($type:ty) => { + { + let n: $type = <$type>::try_from(args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; + let mut box_value = Box::new(n) as Box; + pointers.push(&mut *box_value as *mut _ as *mut c_void); + memory.push(box_value); + } + } + } + match (*field_type).type_ as u32 { - libffi::raw::FFI_TYPE_UINT8 => { - let n: u8 = u8::try_from(args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; - let mut box_value = Box::new(n) as Box; - pointers.push(&mut *box_value as *mut _ as *mut c_void); - memory.push(box_value); - }, - libffi::raw::FFI_TYPE_SINT8 => { - let n: i8 = i8::try_from(args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; - let mut box_value = Box::new(n) as Box; - pointers.push(&mut *box_value as *mut _ as *mut c_void); - memory.push(box_value); - }, - libffi::raw::FFI_TYPE_UINT16 => { - let n: u16 = u16::try_from(args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; - let mut box_value = Box::new(n) as Box; - pointers.push(&mut *box_value as *mut _ as *mut c_void); - memory.push(box_value); - }, - libffi::raw::FFI_TYPE_SINT16 => { - let n: i16 = i16::try_from(args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; - let mut box_value = Box::new(n) as Box; - pointers.push(&mut *box_value as *mut _ as *mut c_void); - memory.push(box_value); - }, - libffi::raw::FFI_TYPE_UINT32 => { - let n: u32 = u32::try_from(args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; - let mut box_value = Box::new(n) as Box; - pointers.push(&mut *box_value as *mut _ as *mut c_void); - memory.push(box_value); - }, - libffi::raw::FFI_TYPE_SINT32 => { - let n: i32 = i32::try_from(args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; - let mut box_value = Box::new(n) as Box; - pointers.push(&mut *box_value as *mut _ as *mut c_void); - memory.push(box_value); - }, - libffi::raw::FFI_TYPE_UINT64 => { - let n: u64 = u64::try_from(args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; - let mut box_value = Box::new(n) as Box; - pointers.push(&mut *box_value as *mut _ as *mut c_void); - memory.push(box_value); - }, - libffi::raw::FFI_TYPE_SINT64 => { - let n: i64 = args[i].as_int()?; - let mut box_value = Box::new(n) as Box; - pointers.push(&mut *box_value as *mut _ as *mut c_void); - memory.push(box_value); - }, + libffi::raw::FFI_TYPE_UINT8 => push_int!(u8), + libffi::raw::FFI_TYPE_SINT8 => push_int!(i8), + libffi::raw::FFI_TYPE_UINT16 => push_int!(u16), + libffi::raw::FFI_TYPE_SINT16 => push_int!(i16), + libffi::raw::FFI_TYPE_UINT32 => push_int!(u32), + libffi::raw::FFI_TYPE_SINT32 => push_int!(i32), + libffi::raw::FFI_TYPE_UINT64 => push_int!(u64), + libffi::raw::FFI_TYPE_SINT64 => push_int!(i64), libffi::raw::FFI_TYPE_FLOAT => { let n: f32 = args[i].as_float()? as f32; let mut box_value = Box::new(n) as Box; @@ -193,34 +164,46 @@ impl ForeignFunctionTable { }, libffi::raw::FFI_TYPE_STRUCT => { match args[i] { - Value::Struct(ref name, ref struct_args) => { + Value::Struct(ref name, ref mut struct_args) => { if let Some(ref mut struct_type) = structs_table.get_mut(name) { let layout = Layout::from_size_align(struct_type.ffi_type.size, struct_type.ffi_type.alignment.into()).unwrap(); let ptr = alloc(layout) as *mut c_void; let mut field_ptr = ptr; + for i in 0..(struct_type.fields.len()-1) { + macro_rules! try_write_int { + ($type:ty) => { + { + let n: $type = <$type>::try_from(struct_args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; + std::ptr::write(field_ptr as *mut $type, n); + field_ptr = field_ptr.add(std::mem::size_of::<$type>()); + } + } + } + + macro_rules! write { + ($type:ty, $value:expr) => { + { + let data: $type = $value; + std::ptr::write(field_ptr as *mut $type, data); + field_ptr = field_ptr.add(std::mem::size_of::<$type>()); + } + } + } + let field = struct_type.fields[i]; match (*field).type_ as u32 { - libffi::raw::FFI_TYPE_UINT8 => { - let n: u8 = u8::try_from(struct_args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; - std::ptr::write(field_ptr as *mut u8, n); - field_ptr = field_ptr.add(std::mem::size_of::()); - }, - libffi::raw::FFI_TYPE_UINT32 => { - let n: u32 = u32::try_from(struct_args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; - std::ptr::write(field_ptr as *mut u32, n); - field_ptr = field_ptr.add(std::mem::size_of::()); - }, - libffi::raw::FFI_TYPE_SINT32 => { - let n: u32 = u32::try_from(struct_args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?; - std::ptr::write(field_ptr as *mut u32, n); - field_ptr = field_ptr.add(std::mem::size_of::()); - }, - libffi::raw::FFI_TYPE_FLOAT => { - let n: f32 = struct_args[i].as_float()? as f32; - std::ptr::write(field_ptr as *mut f32, n); - field_ptr = field_ptr.add(std::mem::size_of::()); - }, + libffi::raw::FFI_TYPE_UINT8 => try_write_int!(u8), + libffi::raw::FFI_TYPE_SINT8 => try_write_int!(i8), + libffi::raw::FFI_TYPE_UINT16 => try_write_int!(u16), + libffi::raw::FFI_TYPE_SINT16 => try_write_int!(i16), + libffi::raw::FFI_TYPE_UINT32 => try_write_int!(u32), + libffi::raw::FFI_TYPE_SINT32 => try_write_int!(i32), + libffi::raw::FFI_TYPE_UINT64 => try_write_int!(u64), + libffi::raw::FFI_TYPE_SINT64 => try_write_int!(i64), + libffi::raw::FFI_TYPE_POINTER => write!(*mut c_void, struct_args[i].as_ptr()?), + libffi::raw::FFI_TYPE_FLOAT => write!(f32, struct_args[i].as_float()? as f32), + libffi::raw::FFI_TYPE_DOUBLE => write!(f64, struct_args[i].as_float()?), _ => { unreachable!() } @@ -247,42 +230,66 @@ impl ForeignFunctionTable { pub fn exec(&mut self, name: &str, mut args: Vec) -> Result { let function_impl = self.table.get_mut(name).ok_or(FFIError::FunctionNotFound)?; - let mut pointer_args = Self::build_pointer_args(&mut args, &function_impl.args, &mut self.structs).unwrap(); + let mut pointer_args = Self::build_pointer_args(&mut args, &function_impl.args, &mut self.structs)?; + return unsafe { + macro_rules! call_and_return { + ($type:ty) => { + { + let mut n: Box = Box::new(0); + libffi::raw::ffi_call( + &mut function_impl.cif, + Some(*function_impl.code_ptr.as_safe_fun()), + &mut *n as *mut _ as *mut c_void, + pointer_args.pointers.as_mut_ptr() as *mut *mut c_void + ); + Ok(Value::Int(i64::from(*n))) + } + } + } + match (*function_impl.cif.rtype).type_ as u32 { - libffi::raw::FFI_TYPE_VOID => { - let mut _n: Box = Box::new(0); + libffi::raw::FFI_TYPE_VOID => call_and_return!(i32), + libffi::raw::FFI_TYPE_UINT8 => call_and_return!(u8), + libffi::raw::FFI_TYPE_SINT8 => call_and_return!(i8), + libffi::raw::FFI_TYPE_UINT16 => call_and_return!(u16), + libffi::raw::FFI_TYPE_SINT16 => call_and_return!(i16), + libffi::raw::FFI_TYPE_UINT32 => call_and_return!(u32), + libffi::raw::FFI_TYPE_SINT32 => call_and_return!(i32), + libffi::raw::FFI_TYPE_UINT64 => { + let mut n: Box = Box::new(0); libffi::raw::ffi_call( &mut function_impl.cif, Some(*function_impl.code_ptr.as_safe_fun()), - &mut *_n as *mut _ as *mut c_void, + &mut *n as *mut _ as *mut c_void, pointer_args.pointers.as_mut_ptr() as *mut *mut c_void ); - Ok(Value::Int(0)) + Ok(Value::Int(i64::try_from(*n).map_err(|_| FFIError::ValueDontFit)?)) }, - libffi::raw::FFI_TYPE_SINT8 => { - let mut n: Box = Box::new(0); + libffi::raw::FFI_TYPE_SINT64 => call_and_return!(i64), + libffi::raw::FFI_TYPE_FLOAT => { + let mut n: Box = Box::new(0.0); libffi::raw::ffi_call( &mut function_impl.cif, Some(*function_impl.code_ptr.as_safe_fun()), &mut *n as *mut _ as *mut c_void, pointer_args.pointers.as_mut_ptr() as *mut *mut c_void ); - Ok(Value::Int(i64::from(*n))) - }, - libffi::raw::FFI_TYPE_SINT32 => { - let mut n: Box = Box::new(0); + Ok(Value::Float((*n).into())) + }, + libffi::raw::FFI_TYPE_DOUBLE => { + let mut n: Box = Box::new(0.0); libffi::raw::ffi_call( &mut function_impl.cif, Some(*function_impl.code_ptr.as_safe_fun()), &mut *n as *mut _ as *mut c_void, pointer_args.pointers.as_mut_ptr() as *mut *mut c_void ); - Ok(Value::Int(i64::from(*n))) + Ok(Value::Float(*n)) }, libffi::raw::FFI_TYPE_STRUCT => { let mut returns = Vec::new(); - let mut struct_type = self.structs.get_mut(&function_impl.return_struct_name.clone().ok_or(FFIError::StructNotFound)?).ok_or(FFIError::StructNotFound)?; + let struct_type = self.structs.get_mut(&function_impl.return_struct_name.clone().ok_or(FFIError::StructNotFound)?).ok_or(FFIError::StructNotFound)?; let layout = Layout::from_size_align(struct_type.ffi_type.size, struct_type.ffi_type.alignment.into()).unwrap(); let ptr = alloc(layout) as *mut c_void; libffi::raw::ffi_call( @@ -292,25 +299,33 @@ impl ForeignFunctionTable { pointer_args.pointers.as_mut_ptr() as *mut *mut c_void ); - let mut field_ptr = ptr; + let mut field_ptr = ptr; + + macro_rules! read_and_push_int { + ($type:ty) => { + { + let n = std::ptr::read(field_ptr as *mut $type); + returns.push(Value::Int(i64::from(n))); + field_ptr = field_ptr.add(std::mem::size_of::<$type>()); + } + } + } + for i in 0..(struct_type.fields.len()-1) { let field = struct_type.fields[i]; match (*field).type_ as u32 { - libffi::raw::FFI_TYPE_UINT8 => { - let n = std::ptr::read(field_ptr as *mut u8); - returns.push(Value::Int(i64::from(n))); - field_ptr = field_ptr.add(std::mem::size_of::()); - }, - libffi::raw::FFI_TYPE_SINT32 => { - let n = std::ptr::read(field_ptr as *mut i32); - returns.push(Value::Int(i64::from(n))); - field_ptr = field_ptr.add(std::mem::size_of::()); - }, - libffi::raw::FFI_TYPE_UINT32 => { - let n = std::ptr::read(field_ptr as *mut u32); - returns.push(Value::Int(i64::from(n))); - field_ptr = field_ptr.add(std::mem::size_of::()); + libffi::raw::FFI_TYPE_UINT8 => read_and_push_int!(u8), + libffi::raw::FFI_TYPE_SINT8 => read_and_push_int!(i8), + libffi::raw::FFI_TYPE_UINT16 => read_and_push_int!(u16), + libffi::raw::FFI_TYPE_SINT16 => read_and_push_int!(i16), + libffi::raw::FFI_TYPE_UINT32 => read_and_push_int!(u32), + libffi::raw::FFI_TYPE_SINT32 => read_and_push_int!(i32), + libffi::raw::FFI_TYPE_UINT64 => { + let n = std::ptr::read(field_ptr as *mut u64); + returns.push(Value::Int(i64::try_from(n).map_err(|_| FFIError::ValueDontFit)?)); + field_ptr = field_ptr.add(std::mem::size_of::()); }, + libffi::raw::FFI_TYPE_SINT64 => read_and_push_int!(i64), _ => { unreachable!() } diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index ca2af22e..194d3ccc 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -1,6 +1,7 @@ use crate::atom_table::*; use crate::parser::ast::*; +use crate::ffi::FFIError; use crate::forms::*; use crate::machine::heap::*; use crate::machine::loader::CompilationTarget; @@ -515,6 +516,24 @@ impl MachineState { } } + pub(super) fn ffi_error(&mut self, err: FFIError) -> MachineError { + let error_atom = match err { + FFIError::ValueCast => atom!("value_cast"), + FFIError::ValueDontFit => atom!("value_dont_fit"), + FFIError::InvalidFFIType => atom!("invalid_ffi_type"), + FFIError::InvalidStructName => atom!("invalid_struct_name"), + FFIError::FunctionNotFound => atom!("function_not_found"), + FFIError::StructNotFound => atom!("struct_not_found"), + }; + let stub = functor!(atom!("ffi_error"),[atom(error_atom)]); + + MachineError { + stub, + location: None, + from: ErrorProvenance::Constructed, + } + } + pub(super) fn error_form(&mut self, err: MachineError, src: FunctorStub) -> MachineStub { let h = self.heap.len(); let location = err.location; diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index c68a532e..e8536035 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -4288,9 +4288,10 @@ impl Machine { return Ok(()); }, Err(e) => { - // throw error - self.machine_st.fail = true; - return Ok(()); + let stub = functor_stub(atom!("current_input"), 1); + let err = self.machine_st.ffi_error(e); + + return Err(self.machine_st.error_form(err, stub)); } } } -- 2.54.0