diff --git a/Cargo.toml b/Cargo.toml index 7ee290b5dc918f4666d365b25d09891e041dda55..ae2f8358e589e306aeac04bb7f65752728639d16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,4 @@ edition = "2018" [dependencies] nom = "5.0.1" nom_locate = "1.0.0" +inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm8-0" } diff --git a/examples/llvm-jit.rs b/examples/llvm-jit.rs new file mode 100644 index 0000000000000000000000000000000000000000..19c9e4d315ae24df1a9a3b6a7d9845052f89f0a4 --- /dev/null +++ b/examples/llvm-jit.rs @@ -0,0 +1,64 @@ +extern crate inkwell; + +use inkwell::builder::Builder; +use inkwell::context::Context; +use inkwell::execution_engine::{ExecutionEngine, JitFunction}; +use inkwell::module::Module; +use inkwell::OptimizationLevel; + +use std::error::Error; + +/// Convenience type alias for the `sum` function. +/// +/// Calling this is innately `unsafe` because there's no guarantee it doesn't +/// do `unsafe` operations internally. +type SumFunc = unsafe extern "C" fn(u64, u64, u64) -> u64; + +fn jit_compile_sum( + context: &Context, + module: &Module, + builder: &Builder, + execution_engine: &ExecutionEngine, +) -> Option<JitFunction<SumFunc>> { + let i64_type = context.i64_type(); + let fn_type = i64_type + .fn_type(&[i64_type.into(), i64_type.into(), i64_type.into()], false); + + let function = module.add_function("sum", fn_type, None); + let basic_block = context.append_basic_block(&function, "entry"); + + builder.position_at_end(&basic_block); + + let x = function.get_nth_param(0)?.into_int_value(); + let y = function.get_nth_param(1)?.into_int_value(); + let z = function.get_nth_param(2)?.into_int_value(); + + let sum = builder.build_int_add(x, y, "sum"); + let sum = builder.build_int_add(sum, z, "sum"); + + builder.build_return(Some(&sum)); + + unsafe { execution_engine.get_function("sum").ok() } +} + +fn main() -> Result<(), Box<dyn Error>> { + let context = Context::create(); + let module = context.create_module("sum"); + let builder = context.create_builder(); + let execution_engine = + module.create_jit_execution_engine(OptimizationLevel::None)?; + + let sum = jit_compile_sum(&context, &module, &builder, &execution_engine) + .ok_or("Unable to JIT compile `sum`")?; + + let x = 1u64; + let y = 2u64; + let z = 3u64; + + unsafe { + println!("{} + {} + {} = {}", x, y, z, sum.call(x, y, z)); + assert_eq!(sum.call(x, y, z), x + y + z); + } + + Ok(()) +}