Last active
February 21, 2024 02:35
-
-
Save JCBurnside/e93d6b95d1caa3746b7fe72073094cc2 to your computer and use it in GitHub Desktop.
A small sample using LLJIT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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