Skip to main content

inkwell/
execution_engine.rs

1use libc::c_int;
2use llvm_sys::execution_engine::{
3    LLVMAddGlobalMapping, LLVMAddModule, LLVMDisposeExecutionEngine, LLVMExecutionEngineRef, LLVMFindFunction,
4    LLVMFreeMachineCodeForFunction, LLVMGenericValueRef, LLVMGetExecutionEngineTargetData, LLVMGetFunctionAddress,
5    LLVMLinkInInterpreter, LLVMLinkInMCJIT, LLVMRemoveModule, LLVMRunFunction, LLVMRunFunctionAsMain,
6    LLVMRunStaticConstructors, LLVMRunStaticDestructors,
7};
8
9use crate::context::Context;
10use crate::module::Module;
11use crate::support::{LLVMString, to_c_str};
12use crate::targets::TargetData;
13use crate::values::{AnyValue, AsValueRef, FunctionValue, GenericValue};
14
15use std::error::Error;
16use std::fmt::{self, Debug, Display, Formatter};
17use std::marker::PhantomData;
18use std::mem::{MaybeUninit, forget, size_of, transmute_copy};
19use std::ops::Deref;
20use std::ptr::NonNull;
21use std::rc::Rc;
22
23static EE_INNER_PANIC: &str = "ExecutionEngineInner should exist until Drop";
24
25#[derive(Debug, PartialEq, Eq)]
26pub enum FunctionLookupError {
27    JITNotEnabled,
28    FunctionNotFound, // 404!
29}
30
31impl Error for FunctionLookupError {}
32
33impl FunctionLookupError {
34    fn as_str(&self) -> &str {
35        match self {
36            FunctionLookupError::JITNotEnabled => "ExecutionEngine does not have JIT functionality enabled",
37            FunctionLookupError::FunctionNotFound => "Function not found in ExecutionEngine",
38        }
39    }
40}
41
42impl Display for FunctionLookupError {
43    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
44        write!(f, "FunctionLookupError({})", self.as_str())
45    }
46}
47
48#[derive(Debug, PartialEq, Eq)]
49pub enum RemoveModuleError {
50    ModuleNotOwned,
51    IncorrectModuleOwner,
52    LLVMError(LLVMString),
53}
54
55impl Error for RemoveModuleError {
56    // This method is deprecated on nighty so it's probably not
57    // something we should worry about
58    fn description(&self) -> &str {
59        self.as_str()
60    }
61
62    fn cause(&self) -> Option<&dyn Error> {
63        None
64    }
65}
66
67impl RemoveModuleError {
68    fn as_str(&self) -> &str {
69        match self {
70            RemoveModuleError::ModuleNotOwned => "Module is not owned by an Execution Engine",
71            RemoveModuleError::IncorrectModuleOwner => "Module is not owned by this Execution Engine",
72            RemoveModuleError::LLVMError(string) => string.to_str().unwrap_or("LLVMError with invalid unicode"),
73        }
74    }
75}
76
77impl Display for RemoveModuleError {
78    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
79        write!(f, "RemoveModuleError({})", self.as_str())
80    }
81}
82
83/// A reference-counted wrapper around LLVM's execution engine.
84///
85/// # Note
86///
87/// Cloning this object is essentially just a case of copying a couple pointers
88/// and incrementing one or two atomics, so this should be quite cheap to create
89/// copies. The underlying LLVM object will be automatically deallocated when
90/// there are no more references to it.
91#[derive(PartialEq, Eq, Debug)]
92pub struct ExecutionEngine<'ctx> {
93    execution_engine: Option<ExecEngineInner<'ctx>>,
94    target_data: Option<TargetData>,
95    jit_mode: bool,
96}
97
98impl<'ctx> ExecutionEngine<'ctx> {
99    pub unsafe fn new(execution_engine: Rc<LLVMExecutionEngineRef>, jit_mode: bool) -> Self {
100        unsafe {
101            assert!(!execution_engine.is_null());
102
103            // REVIEW: Will we have to do this for LLVMGetExecutionEngineTargetMachine too?
104            let target_data = LLVMGetExecutionEngineTargetData(*execution_engine);
105
106            ExecutionEngine {
107                execution_engine: Some(ExecEngineInner(execution_engine, PhantomData)),
108                target_data: Some(TargetData::new(target_data)),
109                jit_mode,
110            }
111        }
112    }
113
114    /// Acquires the underlying raw pointer belonging to this `ExecutionEngine` type.
115    pub fn as_mut_ptr(&self) -> LLVMExecutionEngineRef {
116        self.execution_engine_inner()
117    }
118
119    pub(crate) fn execution_engine_rc(&self) -> &Rc<LLVMExecutionEngineRef> {
120        &self.execution_engine.as_ref().expect(EE_INNER_PANIC).0
121    }
122
123    #[inline]
124    pub(crate) fn execution_engine_inner(&self) -> LLVMExecutionEngineRef {
125        **self.execution_engine_rc()
126    }
127
128    // This function is noop, but required for proper MCJIT initialization and
129    // registration. Without it, LTO is free to eliminate it
130    pub(crate) fn link_in_mc_jit() {
131        unsafe { LLVMLinkInMCJIT() }
132    }
133
134    // This function is noop, but required for proper MCJIT initialization and
135    // registration. Without it, LTO is free to eliminate it
136    pub(crate) fn link_in_interpreter() {
137        unsafe {
138            LLVMLinkInInterpreter();
139        }
140    }
141
142    /// Maps the specified value to an address.
143    ///
144    /// # Example
145    /// ```no_run
146    /// use inkwell::targets::{InitializationConfig, Target};
147    /// use inkwell::context::Context;
148    /// use inkwell::OptimizationLevel;
149    ///
150    /// Target::initialize_native(&InitializationConfig::default()).unwrap();
151    ///
152    /// extern fn sumf(a: f64, b: f64) -> f64 {
153    ///     a + b
154    /// }
155    ///
156    /// let context = Context::create();
157    /// let module = context.create_module("test");
158    /// let builder = context.create_builder();
159    ///
160    /// let ft = context.f64_type();
161    /// let fnt = ft.fn_type(&[], false);
162    ///
163    /// let f = module.add_function("test_fn", fnt, None);
164    /// let b = context.append_basic_block(f, "entry");
165    ///
166    /// builder.position_at_end(b);
167    ///
168    /// let extf = module.add_function("sumf", ft.fn_type(&[ft.into(), ft.into()], false), None);
169    ///
170    /// let argf = ft.const_float(64.);
171    /// let call_site_value = builder.build_call(extf, &[argf.into(), argf.into()], "retv").unwrap();
172    /// let retv = call_site_value.try_as_basic_value().unwrap_basic().into_float_value();
173    ///
174    /// builder.build_return(Some(&retv)).unwrap();
175    ///
176    /// let mut ee = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
177    /// ee.add_global_mapping(&extf, sumf as usize);
178    ///
179    /// let result = unsafe { ee.run_function(f, &[]) }.as_float(&ft);
180    ///
181    /// assert_eq!(result, 128.);
182    /// ```
183    pub fn add_global_mapping(&self, value: &dyn AnyValue<'ctx>, addr: usize) {
184        unsafe { LLVMAddGlobalMapping(self.execution_engine_inner(), value.as_value_ref(), addr as *mut _) }
185    }
186
187    /// Adds a module to an `ExecutionEngine`.
188    ///
189    /// The method will be `Ok(())` if the module does not belong to an `ExecutionEngine` already and `Err(())` otherwise.
190    ///
191    /// ```rust,no_run
192    /// use inkwell::targets::{InitializationConfig, Target};
193    /// use inkwell::context::Context;
194    /// use inkwell::OptimizationLevel;
195    ///
196    /// Target::initialize_native(&InitializationConfig::default()).unwrap();
197    ///
198    /// let context = Context::create();
199    /// let module = context.create_module("test");
200    /// let mut ee = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
201    ///
202    /// assert!(ee.add_module(&module).is_err());
203    /// ```
204    pub fn add_module(&self, module: &Module<'ctx>) -> Result<(), ()> {
205        unsafe { LLVMAddModule(self.execution_engine_inner(), module.as_mut_ptr()) }
206
207        if module.owned_by_ee.borrow().is_some() {
208            return Err(());
209        }
210
211        *module.owned_by_ee.borrow_mut() = Some(self.clone());
212
213        Ok(())
214    }
215
216    pub fn remove_module(&self, module: &Module<'ctx>) -> Result<(), RemoveModuleError> {
217        match *module.owned_by_ee.borrow() {
218            Some(ref ee) if ee.execution_engine_inner() != self.execution_engine_inner() => {
219                return Err(RemoveModuleError::IncorrectModuleOwner);
220            },
221            None => return Err(RemoveModuleError::ModuleNotOwned),
222            _ => (),
223        }
224
225        let mut new_module = MaybeUninit::uninit();
226        let mut err_string: *mut ::libc::c_char = ::core::ptr::null_mut();
227
228        let code = unsafe {
229            LLVMRemoveModule(
230                self.execution_engine_inner(),
231                module.as_mut_ptr(),
232                new_module.as_mut_ptr(),
233                &mut err_string,
234            )
235        };
236
237        if code == 1 {
238            unsafe {
239                return Err(RemoveModuleError::LLVMError(LLVMString::new(err_string)));
240            }
241        }
242
243        let new_module = unsafe { new_module.assume_init() };
244
245        module.module.set(unsafe { NonNull::new_unchecked(new_module) });
246        *module.owned_by_ee.borrow_mut() = None;
247
248        Ok(())
249    }
250
251    /// Try to load a function from the execution engine.
252    ///
253    /// If a target hasn't already been initialized, spurious "function not
254    /// found" errors may be encountered.
255    ///
256    /// The [`UnsafeFunctionPointer`] trait is designed so only `unsafe extern
257    /// "C"` functions can be retrieved via the `get_function()` method. If you
258    /// get funny type errors then it's probably because you have specified the
259    /// wrong calling convention or forgotten to specify the retrieved function
260    /// as `unsafe`.
261    ///
262    /// # Examples
263    ///
264    ///
265    /// ```rust,no_run
266    /// # use inkwell::targets::{InitializationConfig, Target};
267    /// # use inkwell::context::Context;
268    /// # use inkwell::OptimizationLevel;
269    /// # Target::initialize_native(&InitializationConfig::default()).unwrap();
270    /// let context = Context::create();
271    /// let module = context.create_module("test");
272    /// let builder = context.create_builder();
273    ///
274    /// // Set up the function signature
275    /// let double = context.f64_type();
276    /// let sig = double.fn_type(&[], false);
277    ///
278    /// // Add the function to our module
279    /// let f = module.add_function("test_fn", sig, None);
280    /// let b = context.append_basic_block(f, "entry");
281    /// builder.position_at_end(b);
282    ///
283    /// // Insert a return statement
284    /// let ret = double.const_float(64.0);
285    /// builder.build_return(Some(&ret)).unwrap();
286    ///
287    /// // create the JIT engine
288    /// let mut ee = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
289    ///
290    /// // fetch our JIT'd function and execute it
291    /// unsafe {
292    ///     let test_fn = ee.get_function::<unsafe extern "C" fn() -> f64>("test_fn").unwrap();
293    ///     let return_value = test_fn.call();
294    ///     assert_eq!(return_value, 64.0);
295    /// }
296    /// ```
297    ///
298    /// # Safety
299    ///
300    /// It is the caller's responsibility to ensure they call the function with
301    /// the correct signature and calling convention.
302    ///
303    /// The `JitFunction` wrapper ensures a function won't accidentally outlive the
304    /// execution engine it came from, but adding functions after calling this
305    /// method *may* invalidate the function pointer.
306    ///
307    /// [`UnsafeFunctionPointer`]: trait.UnsafeFunctionPointer.html
308    pub unsafe fn get_function<F>(&self, fn_name: &str) -> Result<JitFunction<'ctx, F>, FunctionLookupError>
309    where
310        F: UnsafeFunctionPointer,
311    {
312        unsafe {
313            if !self.jit_mode {
314                return Err(FunctionLookupError::JITNotEnabled);
315            }
316
317            let address = self.get_function_address(fn_name)?;
318
319            assert_eq!(
320                size_of::<F>(),
321                size_of::<usize>(),
322                "The type `F` must have the same size as a function pointer"
323            );
324
325            let execution_engine = self.execution_engine.as_ref().expect(EE_INNER_PANIC);
326
327            Ok(JitFunction {
328                _execution_engine: execution_engine.clone(),
329                inner: transmute_copy(&address),
330            })
331        }
332    }
333
334    /// Attempts to look up a function's address by its name. May return Err if the function cannot be
335    /// found or some other unknown error has occurred.
336    ///
337    /// It is recommended to use `get_function` instead of this method when intending to call the function
338    /// pointer so that you don't have to do error-prone transmutes yourself.
339    pub fn get_function_address(&self, fn_name: &str) -> Result<usize, FunctionLookupError> {
340        let c_string = to_c_str(fn_name);
341        let address = unsafe { LLVMGetFunctionAddress(self.execution_engine_inner(), c_string.as_ptr()) };
342
343        // REVIEW: Can also return 0 if no targets are initialized.
344        // One option might be to set a (thread local?) global to true if any at all of the targets have been
345        // initialized (maybe we could figure out which config in particular is the trigger)
346        // and if not return an "NoTargetsInitialized" error, instead of not found.
347        if address == 0 {
348            return Err(FunctionLookupError::FunctionNotFound);
349        }
350
351        Ok(address as usize)
352    }
353
354    // REVIEW: Not sure if an EE's target data can change.. if so we might want to update the value
355    // when making this call
356    pub fn get_target_data(&self) -> &TargetData {
357        self.target_data
358            .as_ref()
359            .expect("TargetData should always exist until Drop")
360    }
361
362    // REVIEW: Can also find nothing if no targeting is initialized. Maybe best to
363    // do have a global flag for anything initialized. Catch is that it must be initialized
364    // before EE is created
365    // REVIEW: Should FunctionValue lifetime be tied to self not 'ctx?
366    pub fn get_function_value(&self, fn_name: &str) -> Result<FunctionValue<'ctx>, FunctionLookupError> {
367        if !self.jit_mode {
368            return Err(FunctionLookupError::JITNotEnabled);
369        }
370
371        let c_string = to_c_str(fn_name);
372        let mut function = MaybeUninit::uninit();
373
374        let code = unsafe { LLVMFindFunction(self.execution_engine_inner(), c_string.as_ptr(), function.as_mut_ptr()) };
375
376        if code == 0 {
377            return unsafe { FunctionValue::new(function.assume_init()).ok_or(FunctionLookupError::FunctionNotFound) };
378        };
379
380        Err(FunctionLookupError::FunctionNotFound)
381    }
382
383    // TODOC: Marked as unsafe because input function could very well do something unsafe. It's up to the caller
384    // to ensure that doesn't happen by defining their function correctly.
385    pub unsafe fn run_function(
386        &self,
387        function: FunctionValue<'ctx>,
388        args: &[&GenericValue<'ctx>],
389    ) -> GenericValue<'ctx> {
390        unsafe {
391            let mut args: Vec<LLVMGenericValueRef> = args.iter().map(|val| val.generic_value.as_ptr()).collect();
392
393            let value = LLVMRunFunction(
394                self.execution_engine_inner(),
395                function.as_value_ref(),
396                args.len() as u32,
397                args.as_mut_ptr(),
398            ); // REVIEW: usize to u32 ok??
399
400            GenericValue::new(value)
401        }
402    }
403
404    // TODOC: Marked as unsafe because input function could very well do something unsafe. It's up to the caller
405    // to ensure that doesn't happen by defining their function correctly.
406    // SubType: Only for JIT EEs?
407    pub unsafe fn run_function_as_main(&self, function: FunctionValue<'ctx>, args: &[&str]) -> c_int {
408        unsafe {
409            let cstring_args: Vec<_> = args.iter().map(|&arg| to_c_str(arg)).collect();
410            let raw_args: Vec<*const _> = cstring_args.iter().map(|arg| arg.as_ptr()).collect();
411
412            let environment_variables = []; // TODO: Support envp. Likely needs to be null terminated
413
414            LLVMRunFunctionAsMain(
415                self.execution_engine_inner(),
416                function.as_value_ref(),
417                raw_args.len() as u32,
418                raw_args.as_ptr(),
419                environment_variables.as_ptr(),
420            ) // REVIEW: usize to u32 cast ok??
421        }
422    }
423
424    pub fn free_fn_machine_code(&self, function: FunctionValue<'ctx>) {
425        unsafe { LLVMFreeMachineCodeForFunction(self.execution_engine_inner(), function.as_value_ref()) }
426    }
427
428    // REVIEW: Is this actually safe?
429    pub fn run_static_constructors(&self) {
430        unsafe { LLVMRunStaticConstructors(self.execution_engine_inner()) }
431    }
432
433    // REVIEW: Is this actually safe? Can you double destruct/free?
434    pub fn run_static_destructors(&self) {
435        unsafe { LLVMRunStaticDestructors(self.execution_engine_inner()) }
436    }
437}
438
439// Modules owned by the EE will be discarded by the EE so we don't
440// want owned modules to drop.
441impl Drop for ExecutionEngine<'_> {
442    fn drop(&mut self) {
443        forget(
444            self.target_data
445                .take()
446                .expect("TargetData should always exist until Drop"),
447        );
448
449        // We must ensure the EE gets dropped before its context does,
450        // which is important in the case where the EE has the last
451        // remaining reference to it context
452        drop(self.execution_engine.take().expect(EE_INNER_PANIC));
453    }
454}
455
456impl Clone for ExecutionEngine<'_> {
457    fn clone(&self) -> Self {
458        let execution_engine_rc = self.execution_engine_rc().clone();
459
460        unsafe { ExecutionEngine::new(execution_engine_rc, self.jit_mode) }
461    }
462}
463
464/// A smart pointer which wraps the `Drop` logic for `LLVMExecutionEngineRef`.
465#[repr(transparent)]
466#[derive(Debug, Clone, PartialEq, Eq)]
467struct ExecEngineInner<'ctx>(Rc<LLVMExecutionEngineRef>, PhantomData<&'ctx Context>);
468
469impl Drop for ExecEngineInner<'_> {
470    fn drop(&mut self) {
471        if Rc::strong_count(&self.0) == 1 {
472            unsafe {
473                LLVMDisposeExecutionEngine(*self.0);
474            }
475        }
476    }
477}
478
479impl Deref for ExecEngineInner<'_> {
480    type Target = LLVMExecutionEngineRef;
481
482    fn deref(&self) -> &Self::Target {
483        &self.0
484    }
485}
486
487/// A wrapper around a function pointer which ensures the function being pointed
488/// to doesn't accidentally outlive its execution engine.
489#[derive(Clone)]
490pub struct JitFunction<'ctx, F> {
491    _execution_engine: ExecEngineInner<'ctx>,
492    inner: F,
493}
494
495impl<F: Copy> JitFunction<'_, F> {
496    /// Returns the raw function pointer, consuming self in the process.
497    /// This function is unsafe because the function pointer may dangle
498    /// if the ExecutionEngine it came from is dropped. The caller is
499    /// thus responsible for ensuring the ExecutionEngine remains valid.
500    pub unsafe fn into_raw(self) -> F {
501        self.inner
502    }
503
504    /// Returns the raw function pointer.
505    /// This function is unsafe because the function pointer may dangle
506    /// if the ExecutionEngine it came from is dropped. The caller is
507    /// thus responsible for ensuring the ExecutionEngine remains valid.
508    pub unsafe fn as_raw(&self) -> F {
509        self.inner
510    }
511}
512
513impl<F> Debug for JitFunction<'_, F> {
514    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
515        f.debug_tuple("JitFunction").field(&"<unnamed>").finish()
516    }
517}
518
519/// Marker trait representing an unsafe function pointer (`unsafe extern "C" fn(A, B, ...) -> Output`).
520pub trait UnsafeFunctionPointer: private::SealedUnsafeFunctionPointer {}
521
522mod private {
523    /// A sealed trait which ensures nobody outside this crate can implement
524    /// `UnsafeFunctionPointer`.
525    ///
526    /// See https://rust-lang-nursery.github.io/api-guidelines/future-proofing.html
527    pub trait SealedUnsafeFunctionPointer: Copy {}
528}
529
530impl<F: private::SealedUnsafeFunctionPointer> UnsafeFunctionPointer for F {}
531
532macro_rules! impl_unsafe_fn {
533    (@recurse $first:ident $( , $rest:ident )*) => {
534        impl_unsafe_fn!($( $rest ),*);
535    };
536
537    (@recurse) => {};
538
539    ($( $param:ident ),*) => {
540        impl<Output, $( $param ),*> private::SealedUnsafeFunctionPointer for unsafe extern "C" fn($( $param ),*) -> Output {}
541
542        impl<Output, $( $param ),*> JitFunction<'_, unsafe extern "C" fn($( $param ),*) -> Output> {
543            /// This method allows you to call the underlying function while making
544            /// sure that the backing storage is not dropped too early and
545            /// preserves the `unsafe` marker for any calls.
546            #[allow(non_snake_case)]
547            #[inline(always)]
548            pub unsafe fn call(&self, $( $param: $param ),*) -> Output { unsafe {
549                (self.inner)($( $param ),*)
550            }}
551        }
552
553        impl_unsafe_fn!(@recurse $( $param ),*);
554    };
555}
556
557impl_unsafe_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M);
558
559#[cfg(feature = "experimental")]
560pub mod experimental {
561    use llvm_sys::error::{LLVMConsumeError, LLVMErrorRef, LLVMErrorTypeId, LLVMGetErrorMessage, LLVMGetErrorTypeId};
562    use llvm_sys::orc::{
563        LLVMOrcAddEagerlyCompiledIR, LLVMOrcAddLazilyCompiledIR, LLVMOrcCreateInstance, LLVMOrcDisposeInstance,
564        LLVMOrcDisposeMangledSymbol, LLVMOrcGetErrorMsg, LLVMOrcGetMangledSymbol, LLVMOrcJITStackRef,
565    };
566
567    use crate::module::Module;
568    use crate::support::to_c_str;
569    use crate::targets::TargetMachine;
570
571    use std::ffi::{CStr, CString};
572    use std::mem::MaybeUninit;
573    use std::ops::Deref;
574
575    #[derive(Debug)]
576    pub struct MangledSymbol(*mut libc::c_char);
577
578    impl Deref for MangledSymbol {
579        type Target = CStr;
580
581        fn deref(&self) -> &CStr {
582            unsafe { CStr::from_ptr(self.0) }
583        }
584    }
585
586    impl Drop for MangledSymbol {
587        fn drop(&mut self) {
588            unsafe { LLVMOrcDisposeMangledSymbol(self.0) }
589        }
590    }
591
592    #[derive(Debug)]
593    pub struct LLVMError(LLVMErrorRef);
594
595    impl LLVMError {
596        // Null type id == success
597        pub fn get_type_id(&self) -> LLVMErrorTypeId {
598            // FIXME: Don't expose LLVMErrorTypeId
599            unsafe { LLVMGetErrorTypeId(self.0) }
600        }
601    }
602
603    impl Deref for LLVMError {
604        type Target = CStr;
605
606        fn deref(&self) -> &CStr {
607            unsafe {
608                CStr::from_ptr(LLVMGetErrorMessage(self.0)) // FIXME: LLVMGetErrorMessage consumes the error, needs LLVMDisposeErrorMessage after
609            }
610        }
611    }
612
613    impl Drop for LLVMError {
614        fn drop(&mut self) {
615            unsafe { LLVMConsumeError(self.0) }
616        }
617    }
618
619    // TODO
620    #[derive(Debug)]
621    pub struct Orc(LLVMOrcJITStackRef);
622
623    impl Orc {
624        pub fn create(target_machine: TargetMachine) -> Self {
625            let stack_ref = unsafe { LLVMOrcCreateInstance(target_machine.target_machine.as_ptr()) };
626
627            Orc(stack_ref)
628        }
629
630        pub fn add_compiled_ir<'ctx>(&self, module: &Module<'ctx>, lazily: bool) -> Result<(), ()> {
631            // let handle = MaybeUninit::uninit();
632            // let _err =  if lazily {
633            //     unsafe { LLVMOrcAddLazilyCompiledIR(self.0, handle.as_mut_ptr(), module.module.get(), sym_resolve, sym_resolve_ctx) }
634            // } else {
635            //     unsafe { LLVMOrcAddEagerlyCompiledIR(self.0, handle.as_mut_ptr(), module.module.get(), sym_resolve, sym_resolve_ctx) }
636            // };
637
638            Ok(())
639        }
640
641        /// Obtains an error message owned by the ORC JIT stack.
642        pub fn get_error(&self) -> &CStr {
643            let err_str = unsafe { LLVMOrcGetErrorMsg(self.0) };
644
645            if err_str.is_null() {
646                panic!("Needs to be optional")
647            }
648
649            unsafe { CStr::from_ptr(err_str) }
650        }
651
652        pub fn get_mangled_symbol(&self, symbol: &str) -> MangledSymbol {
653            let mut mangled_symbol = MaybeUninit::uninit();
654            let c_symbol = to_c_str(symbol);
655
656            unsafe { LLVMOrcGetMangledSymbol(self.0, mangled_symbol.as_mut_ptr(), c_symbol.as_ptr()) };
657
658            MangledSymbol(unsafe { mangled_symbol.assume_init() })
659        }
660    }
661
662    impl Drop for Orc {
663        fn drop(&mut self) {
664            // REVIEW: This returns an LLVMErrorRef, not sure what we can do with it...
665            // print to stderr maybe?
666            LLVMError(unsafe { LLVMOrcDisposeInstance(self.0) });
667        }
668    }
669
670    #[test]
671    fn test_mangled_str() {
672        use crate::OptimizationLevel;
673        use crate::targets::{CodeModel, InitializationConfig, RelocMode, Target};
674
675        Target::initialize_native(&InitializationConfig::default()).unwrap();
676
677        let target_triple = TargetMachine::get_default_triple();
678        let target = Target::from_triple(&target_triple).unwrap();
679        let target_machine = target
680            .create_target_machine(
681                &target_triple,
682                &"",
683                &"",
684                OptimizationLevel::None,
685                RelocMode::Default,
686                CodeModel::Default,
687            )
688            .unwrap();
689        let orc = Orc::create(target_machine);
690
691        assert_eq!(orc.get_error().to_str().unwrap(), "");
692
693        let mangled_symbol = orc.get_mangled_symbol("MyStructName");
694
695        assert_eq!(orc.get_error().to_str().unwrap(), "");
696
697        // REVIEW: This doesn't seem very mangled...
698        assert_eq!(mangled_symbol.to_str().unwrap(), "MyStructName");
699    }
700}