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