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