From 375d2db581a13b8bf75bb03d82d92ccc2adc86c5 Mon Sep 17 00:00:00 2001 From: Cassie Jones Date: Mon, 2 Mar 2020 19:12:14 +0100 Subject: [PATCH] Stop with #![no_std] in the runtime It was cool because it brought the final small binaries down from roughly 250K to 20K, but it was preventing me from adding features I wanted like debug tracing and better panic messages. This also adds conditional runtime tracing, which prints extra messages if the IVY_RT_TRACE environment variable is set. --- rt/src/lib.rs | 70 +++++++++++++++++++-------------------------------- 1 file changed, 26 insertions(+), 44 deletions(-) diff --git a/rt/src/lib.rs b/rt/src/lib.rs index 6dfd5bd..72bf27a 100644 --- a/rt/src/lib.rs +++ b/rt/src/lib.rs @@ -1,18 +1,16 @@ -#![no_std] -use core::{sync::atomic::{AtomicU32, Ordering}, panic::PanicInfo, fmt::Write}; +use std::sync::atomic::{Ordering, AtomicU32}; -#[panic_handler] -fn handle_panic(panic_info: &PanicInfo) -> ! { - if let Some(s) = panic_info.payload().downcast_ref::<&str>() { - abort(s); - } else { - abort("a panic occurred\n"); +const _STDOUT: i32 = 1; +const STDERR: i32 = 2; + +macro_rules! trace { + ($fmt:literal $(, $arg:expr)* $(,)?) => { + if std::env::var("IVY_RT_TRACE").is_ok() { + eprintln!($fmt, $($arg),*); + } } } -const STDOUT: i32 = 1; -const STDERR: i32 = 2; - #[repr(u8)] #[derive(PartialEq, Eq)] pub enum ObjTag { @@ -47,7 +45,6 @@ pub struct ObjLam { pub union Obj { int: i64, header: *mut ObjHeader, - box_int: *mut ObjInt, box_lam: *mut ObjLam, } @@ -62,10 +59,7 @@ mod sys { #[no_mangle] pub unsafe extern "C" fn ivy_debug(obj: Obj) -> Obj { - // let mut buffer = String::new(); - // writeln!(&mut buffer, "DBUG {:016x}", obj.int); - const BUFFER: &str = "DEBUG\n"; - sys::write(STDOUT, BUFFER.as_ptr(), BUFFER.len()); + println!("DEBUG {:016x}", obj.int); obj } @@ -83,14 +77,14 @@ pub unsafe extern "C" fn ivy_exit(code: i32) -> ! { #[no_mangle] pub unsafe extern "C" fn ivy_check_int(obj: Obj) { if !obj.is_int() { - abort("Abort: ivy_check_int called with non-integer object.\n"); + panic!("ivy_check_int called with non-integer object {:016x}.", obj.int); } } #[no_mangle] pub unsafe extern "C" fn ivy_check_lam(obj: Obj) { if !obj.is_lam() { - abort("Abort: ivy_check_lam called with non-lambda object.\n"); + panic!("ivy_check_lam called with non-lambda object {:016x}.", obj.int); } } @@ -117,7 +111,7 @@ pub unsafe extern "C" fn ivy_make_lam(func: fn(&ObjLam) -> Obj, params: u16, upv (*box_lam) .raw_fields_mut() .write_bytes(0, (params + upvars) as usize); - // println!("MAKE {:016x}", box_lam as usize); + trace!("MAKE {:016x} {:016x}", box_lam as usize, func as usize); Obj { box_lam } } @@ -145,7 +139,7 @@ pub unsafe extern "C" fn ivy_clone(obj: Obj) -> Obj { return obj; } if obj.is_int() { - abort("Abort: copying boxed integers is not implemented.\n") + unimplemented!("copying boxed integers") } let lam = &*obj.box_lam; let size = lam.size(); @@ -153,25 +147,29 @@ pub unsafe extern "C" fn ivy_clone(obj: Obj) -> Obj { core::ptr::copy(obj.box_lam as *const u8, data, size); let box_lam = data as *mut ObjLam; *(*box_lam).rc.get_mut() = 0; - // println!("COPY {:016x} {:016x}", obj.int, box_lam as usize); + trace!("COPY {:016x} {:016x}", obj.int, box_lam as usize); Obj { box_lam } } #[no_mangle] -pub unsafe extern "C" fn ivy_app(mut fun: Obj, arg: Obj) -> Obj { +pub unsafe extern "C" fn ivy_app(fun: Obj, arg: Obj) -> Obj { ivy_app_mut(ivy_clone(fun), arg) } #[no_mangle] pub unsafe extern "C" fn ivy_app_mut(fun: Obj, arg: Obj) -> Obj { - // println!("APP {:016x} {:016x}", fun.int, arg.int); + trace!("APP {:016x} {:016x}", fun.int, arg.int); if !fun.is_lam() { - abort("Abort: ivy_app called with a non-lam as the function.\n"); + panic!("ivy_app called with a non-lam as the function: {:016x}.", fun.int); } let lam = &mut *fun.box_lam; if lam.filled < lam.params { if arg.is_null() { - abort("Abort: ivy_app called with a null arg.\n"); + println!( + "Lam @ {:016x} ({:016x}) has {} of {} arguments filled.", + fun.int, lam.func as usize, lam.filled, lam.params + ); + panic!("ivy_app called with a null arg."); } arg.incref(); let idx = lam.filled as usize; @@ -179,24 +177,20 @@ pub unsafe extern "C" fn ivy_app_mut(fun: Obj, arg: Obj) -> Obj { lam.filled += 1; } else if lam.params == lam.filled { if !arg.is_null() { - abort("Abort: ivy_app called for a 0-arity application with a non-null arg.\n"); + panic!("ivy_app called for a 0-arity application with a non-null arg."); } } if lam.params == lam.filled { - // println!("RUN {:016x}", fun.int); + trace!("RUN {:016x}", fun.int); (lam.func)(lam) } else { - // println!("UPD8 {:016x}", fun.int); + trace!("UPD8 {:016x}", fun.int); fun.incref(); fun } } -fn abort(msg: &str) -> ! { - unsafe { ivy_abort(msg.as_ptr(), msg.len()) } -} - impl Obj { fn is_null(self) -> bool { unsafe { self.int == 0 } @@ -206,18 +200,6 @@ impl Obj { !self.is_null() && unsafe { self.int & 1 == 0 } } - unsafe fn refcount(self) -> u32 { - if self.is_box() { - (*self.header).rc.load(Ordering::SeqCst) - } else { - 1 - } - } - - unsafe fn unique(self) -> bool { - self.refcount() == 1 - } - unsafe fn is_int(self) -> bool { !self.is_null() && (!self.is_box() || (*self.header).tag == ObjTag::Int) } -- 2.43.2