Skip to content

Instantly share code, notes, and snippets.

@JCBurnside
Last active February 21, 2024 02:35
Show Gist options
  • Save JCBurnside/e93d6b95d1caa3746b7fe72073094cc2 to your computer and use it in GitHub Desktop.
Save JCBurnside/e93d6b95d1caa3746b7fe72073094cc2 to your computer and use it in GitHub Desktop.
A small sample using LLJIT
use llvm_sys::orc2;
use std::{ffi::{CStr, CString}, mem::MaybeUninit, ops::Deref};
struct LLJIT(orc2::lljit::LLVMOrcLLJITRef);
impl Drop for LLJIT {
fn drop(&mut self) {
unsafe { orc2::lljit::LLVMOrcDisposeLLJIT(self.0) };
}
}
impl Deref for LLJIT {
type Target = orc2::lljit::LLVMOrcLLJITRef;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl LLJIT {
fn add_module(&self, m : llvm_sys::prelude::LLVMModuleRef) {
unsafe {
let thread_safe_ctx = orc2::LLVMOrcCreateNewThreadSafeContext();
let thread_safe = orc2::LLVMOrcCreateNewThreadSafeModule(m, thread_safe_ctx);
let dylib = orc2::lljit::LLVMOrcLLJITGetMainJITDylib(**self);
orc2::lljit::LLVMOrcLLJITAddLLVMIRModule(**self, dylib, thread_safe);
}
}
}
#[repr(transparent)]
struct LLJITBuilder(orc2::lljit::LLVMOrcLLJITBuilderRef);
impl Drop for LLJITBuilder {
fn drop(&mut self) {
if !self.0.is_null() {
unsafe { orc2::lljit::LLVMOrcDisposeLLJITBuilder(self.0) };
}
}
}
impl Deref for LLJITBuilder {
type Target = orc2::lljit::LLVMOrcLLJITBuilderRef;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl LLJITBuilder {
fn new() -> Self {
Self(unsafe { orc2::lljit::LLVMOrcCreateLLJITBuilder() })
}
fn create(mut self) -> LLJIT {
let mut lljit = MaybeUninit::uninit();
let err = unsafe { orc2::lljit::LLVMOrcCreateLLJIT(lljit.as_mut_ptr(), *self) };
self.0 = std::ptr::null_mut();
if !err.is_null() {
let err_msg = unsafe { error::LLVMGetErrorMessage(err) };
let err_msg = unsafe { CStr::from_ptr(err_msg) };
panic!("{err_msg:?}");
}
let ptr = unsafe { lljit.assume_init() };
if ptr.is_null() {
panic!("lljit wasn't initialized?")
}
LLJIT(ptr)
}
}
fn main() {
unsafe {
llvm_sys::target::LLVM_InitializeNativeTarget();
llvm_sys::target::LLVM_InitializeNativeAsmPrinter();
let ctx = llvm_sys::core::LLVMContextCreate();
let module = llvm_sys::core::LLVMModuleCreateWithNameInContext(std::ptr::null(), ctx);
let ty = llvm_sys::core::LLVMVoidType();
let ty = llvm_sys::core::LLVMFunctionType(ty, std::ptr::null_mut(), 0, 0);
let name = CString::new("foo").unwrap();
let fun = llvm_sys::core::LLVMAddFunction(module, name.as_ptr(), ty);
let bb = llvm_sys::core::LLVMAppendBasicBlock(fun, std::ptr::null());
let builder = llvm_sys::core::LLVMCreateBuilder();
llvm_sys::core::LLVMPositionBuilderAtEnd(builder, bb);
llvm_sys::core::LLVMBuildRet(builder,std::ptr::null_mut());
let llbuilder = LLJITBuilder::new();
let lljit = llbuilder.create();
lljit.add_module(module);
let mut executor_addr = MaybeUninit::uninit();
orc2::lljit::LLVMOrcLLJITLookup(*lljit, executor_addr.as_mut_ptr(), name.as_ptr());
let fun = std::mem::transmute::<u64,unsafe extern "C" fn()>(executor_addr.assume_init());
fun()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment