diff --git a/src/bin/toy.rs b/src/bin/toy.rs index a12bace..5e94903 100644 --- a/src/bin/toy.rs +++ b/src/bin/toy.rs @@ -13,6 +13,8 @@ fn main() -> Result<(), String> { "iterative_fib(10) = {}", run_iterative_fib_code(&mut jit, 10)? ); + println!("counting down from 5:"); + run_countdown_code(&mut jit, 5)?; run_hello(&mut jit)?; Ok(()) } @@ -25,6 +27,10 @@ fn run_recursive_fib_code(jit: &mut jit::JIT, input: isize) -> Result Result { + unsafe { run_code(jit, COUNTDOWN_CODE, input) } +} + fn run_iterative_fib_code(jit: &mut jit::JIT, input: isize) -> Result { unsafe { run_code(jit, ITERATIVE_FIB_CODE, input) } } @@ -89,6 +95,18 @@ const RECURSIVE_FIB_CODE: &str = r#" } "#; +/// Another example: calling our builtin print functon. +const COUNTDOWN_CODE: &str = r#" + fn countdown(n) -> (r) { + r = if n == 0 { + 0 + } else { + print(n) + countdown(n - 1) + } + } +"#; + /// Another example: Iterative fibonacci. const ITERATIVE_FIB_CODE: &str = r#" fn iterative_fib(n) -> (r) { diff --git a/src/jit.rs b/src/jit.rs index 160ac36..c7bcbda 100644 --- a/src/jit.rs +++ b/src/jit.rs @@ -26,7 +26,13 @@ pub struct JIT { impl Default for JIT { fn default() -> Self { - let builder = JITBuilder::new(cranelift_module::default_libcall_names()); + let mut builder = JITBuilder::new(cranelift_module::default_libcall_names()); + + // Register our print function with the JIT so that it can be + // called from code. + let print_addr = print_internal as *const u8; + builder.symbol("print", print_addr); + let module = JITModule::new(builder); Self { builder_context: FunctionBuilderContext::new(), @@ -458,3 +464,10 @@ fn declare_variable( } var } + +// Prints a value used by the compiled code. Our JIT exposes this +// function to compiled code with the name "print". +extern "C" fn print_internal(value: isize) -> isize { + println!("{}", value); + 0 +}