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::{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().unwrap_basic().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        let c_string = to_c_str(fn_name);
336        let address = unsafe { LLVMGetFunctionAddress(self.execution_engine_inner(), c_string.as_ptr()) };
337
338        // REVIEW: Can also return 0 if no targets are initialized.
339        // One option might be to set a (thread local?) global to true if any at all of the targets have been
340        // initialized (maybe we could figure out which config in particular is the trigger)
341        // and if not return an "NoTargetsInitialized" error, instead of not found.
342        if address == 0 {
343            return Err(FunctionLookupError::FunctionNotFound);
344        }
345
346        Ok(address as usize)
347    }
348
349    // REVIEW: Not sure if an EE's target data can change.. if so we might want to update the value
350    // when making this call
351    pub fn get_target_data(&self) -> &TargetData {
352        self.target_data
353            .as_ref()
354            .expect("TargetData should always exist until Drop")
355    }
356
357    // REVIEW: Can also find nothing if no targeting is initialized. Maybe best to
358    // do have a global flag for anything initialized. Catch is that it must be initialized
359    // before EE is created
360    // REVIEW: Should FunctionValue lifetime be tied to self not 'ctx?
361    pub fn get_function_value(&self, fn_name: &str) -> Result<FunctionValue<'ctx>, FunctionLookupError> {
362        if !self.jit_mode {
363            return Err(FunctionLookupError::JITNotEnabled);
364        }
365
366        let c_string = to_c_str(fn_name);
367        let mut function = MaybeUninit::uninit();
368
369        let code = unsafe { LLVMFindFunction(self.execution_engine_inner(), c_string.as_ptr(), function.as_mut_ptr()) };
370
371        if code == 0 {
372            return unsafe { FunctionValue::new(function.assume_init()).ok_or(FunctionLookupError::FunctionNotFound) };
373        };
374
375        Err(FunctionLookupError::FunctionNotFound)
376    }
377
378    // TODOC: Marked as unsafe because input function could very well do something unsafe. It's up to the caller
379    // to ensure that doesn't happen by defining their function correctly.
380    pub unsafe fn run_function(
381        &self,
382        function: FunctionValue<'ctx>,
383        args: &[&GenericValue<'ctx>],
384    ) -> GenericValue<'ctx> {
385        let mut args: Vec<LLVMGenericValueRef> = args.iter().map(|val| val.generic_value).collect();
386
387        let value = LLVMRunFunction(
388            self.execution_engine_inner(),
389            function.as_value_ref(),
390            args.len() as u32,
391            args.as_mut_ptr(),
392        ); // REVIEW: usize to u32 ok??
393
394        GenericValue::new(value)
395    }
396
397    // TODOC: Marked as unsafe because input function could very well do something unsafe. It's up to the caller
398    // to ensure that doesn't happen by defining their function correctly.
399    // SubType: Only for JIT EEs?
400    pub unsafe fn run_function_as_main(&self, function: FunctionValue<'ctx>, args: &[&str]) -> c_int {
401        let cstring_args: Vec<_> = args.iter().map(|&arg| to_c_str(arg)).collect();
402        let raw_args: Vec<*const _> = cstring_args.iter().map(|arg| arg.as_ptr()).collect();
403
404        let environment_variables = []; // TODO: Support envp. Likely needs to be null terminated
405
406        LLVMRunFunctionAsMain(
407            self.execution_engine_inner(),
408            function.as_value_ref(),
409            raw_args.len() as u32,
410            raw_args.as_ptr(),
411            environment_variables.as_ptr(),
412        ) // REVIEW: usize to u32 cast ok??
413    }
414
415    pub fn free_fn_machine_code(&self, function: FunctionValue<'ctx>) {
416        unsafe { LLVMFreeMachineCodeForFunction(self.execution_engine_inner(), function.as_value_ref()) }
417    }
418
419    // REVIEW: Is this actually safe?
420    pub fn run_static_constructors(&self) {
421        unsafe { LLVMRunStaticConstructors(self.execution_engine_inner()) }
422    }
423
424    // REVIEW: Is this actually safe? Can you double destruct/free?
425    pub fn run_static_destructors(&self) {
426        unsafe { LLVMRunStaticDestructors(self.execution_engine_inner()) }
427    }
428}
429
430// Modules owned by the EE will be discarded by the EE so we don't
431// want owned modules to drop.
432impl Drop for ExecutionEngine<'_> {
433    fn drop(&mut self) {
434        forget(
435            self.target_data
436                .take()
437                .expect("TargetData should always exist until Drop"),
438        );
439
440        // We must ensure the EE gets dropped before its context does,
441        // which is important in the case where the EE has the last
442        // remaining reference to it context
443        drop(self.execution_engine.take().expect(EE_INNER_PANIC));
444    }
445}
446
447impl Clone for ExecutionEngine<'_> {
448    fn clone(&self) -> Self {
449        let execution_engine_rc = self.execution_engine_rc().clone();
450
451        unsafe { ExecutionEngine::new(execution_engine_rc, self.jit_mode) }
452    }
453}
454
455/// A smart pointer which wraps the `Drop` logic for `LLVMExecutionEngineRef`.
456#[derive(Debug, Clone, PartialEq, Eq)]
457struct ExecEngineInner<'ctx>(Rc<LLVMExecutionEngineRef>, PhantomData<&'ctx Context>);
458
459impl Drop for ExecEngineInner<'_> {
460    fn drop(&mut self) {
461        if Rc::strong_count(&self.0) == 1 {
462            unsafe {
463                LLVMDisposeExecutionEngine(*self.0);
464            }
465        }
466    }
467}
468
469impl Deref for ExecEngineInner<'_> {
470    type Target = LLVMExecutionEngineRef;
471
472    fn deref(&self) -> &Self::Target {
473        &self.0
474    }
475}
476
477/// A wrapper around a function pointer which ensures the function being pointed
478/// to doesn't accidentally outlive its execution engine.
479#[derive(Clone)]
480pub struct JitFunction<'ctx, F> {
481    _execution_engine: ExecEngineInner<'ctx>,
482    inner: F,
483}
484
485impl<F: Copy> JitFunction<'_, F> {
486    /// Returns the raw function pointer, consuming self in the process.
487    /// This function is unsafe because the function pointer may dangle
488    /// if the ExecutionEngine it came from is dropped. The caller is
489    /// thus responsible for ensuring the ExecutionEngine remains valid.
490    pub unsafe fn into_raw(self) -> F {
491        self.inner
492    }
493
494    /// Returns the raw function pointer.
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 as_raw(&self) -> F {
499        self.inner
500    }
501}
502
503impl<F> Debug for JitFunction<'_, F> {
504    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
505        f.debug_tuple("JitFunction").field(&"<unnamed>").finish()
506    }
507}
508
509/// Marker trait representing an unsafe function pointer (`unsafe extern "C" fn(A, B, ...) -> Output`).
510pub trait UnsafeFunctionPointer: private::SealedUnsafeFunctionPointer {}
511
512mod private {
513    /// A sealed trait which ensures nobody outside this crate can implement
514    /// `UnsafeFunctionPointer`.
515    ///
516    /// See https://rust-lang-nursery.github.io/api-guidelines/future-proofing.html
517    pub trait SealedUnsafeFunctionPointer: Copy {}
518}
519
520impl<F: private::SealedUnsafeFunctionPointer> UnsafeFunctionPointer for F {}
521
522macro_rules! impl_unsafe_fn {
523    (@recurse $first:ident $( , $rest:ident )*) => {
524        impl_unsafe_fn!($( $rest ),*);
525    };
526
527    (@recurse) => {};
528
529    ($( $param:ident ),*) => {
530        impl<Output, $( $param ),*> private::SealedUnsafeFunctionPointer for unsafe extern "C" fn($( $param ),*) -> Output {}
531
532        impl<Output, $( $param ),*> JitFunction<'_, unsafe extern "C" fn($( $param ),*) -> Output> {
533            /// This method allows you to call the underlying function while making
534            /// sure that the backing storage is not dropped too early and
535            /// preserves the `unsafe` marker for any calls.
536            #[allow(non_snake_case)]
537            #[inline(always)]
538            pub unsafe fn call(&self, $( $param: $param ),*) -> Output {
539                (self.inner)($( $param ),*)
540            }
541        }
542
543        impl_unsafe_fn!(@recurse $( $param ),*);
544    };
545}
546
547impl_unsafe_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M);
548
549#[cfg(feature = "experimental")]
550pub mod experimental {
551    use llvm_sys::error::{LLVMConsumeError, LLVMErrorRef, LLVMErrorTypeId, LLVMGetErrorMessage, LLVMGetErrorTypeId};
552    use llvm_sys::orc::{
553        LLVMOrcAddEagerlyCompiledIR, LLVMOrcAddLazilyCompiledIR, LLVMOrcCreateInstance, LLVMOrcDisposeInstance,
554        LLVMOrcDisposeMangledSymbol, LLVMOrcGetErrorMsg, LLVMOrcGetMangledSymbol, LLVMOrcJITStackRef,
555    };
556
557    use crate::module::Module;
558    use crate::support::to_c_str;
559    use crate::targets::TargetMachine;
560
561    use std::ffi::{CStr, CString};
562    use std::mem::MaybeUninit;
563    use std::ops::Deref;
564
565    #[derive(Debug)]
566    pub struct MangledSymbol(*mut libc::c_char);
567
568    impl Deref for MangledSymbol {
569        type Target = CStr;
570
571        fn deref(&self) -> &CStr {
572            unsafe { CStr::from_ptr(self.0) }
573        }
574    }
575
576    impl Drop for MangledSymbol {
577        fn drop(&mut self) {
578            unsafe { LLVMOrcDisposeMangledSymbol(self.0) }
579        }
580    }
581
582    #[derive(Debug)]
583    pub struct LLVMError(LLVMErrorRef);
584
585    impl LLVMError {
586        // Null type id == success
587        pub fn get_type_id(&self) -> LLVMErrorTypeId {
588            // FIXME: Don't expose LLVMErrorTypeId
589            unsafe { LLVMGetErrorTypeId(self.0) }
590        }
591    }
592
593    impl Deref for LLVMError {
594        type Target = CStr;
595
596        fn deref(&self) -> &CStr {
597            unsafe {
598                CStr::from_ptr(LLVMGetErrorMessage(self.0)) // FIXME: LLVMGetErrorMessage consumes the error, needs LLVMDisposeErrorMessage after
599            }
600        }
601    }
602
603    impl Drop for LLVMError {
604        fn drop(&mut self) {
605            unsafe { LLVMConsumeError(self.0) }
606        }
607    }
608
609    // TODO
610    #[derive(Debug)]
611    pub struct Orc(LLVMOrcJITStackRef);
612
613    impl Orc {
614        pub fn create(target_machine: TargetMachine) -> Self {
615            let stack_ref = unsafe { LLVMOrcCreateInstance(target_machine.target_machine) };
616
617            Orc(stack_ref)
618        }
619
620        pub fn add_compiled_ir<'ctx>(&self, module: &Module<'ctx>, lazily: bool) -> Result<(), ()> {
621            // let handle = MaybeUninit::uninit();
622            // let _err =  if lazily {
623            //     unsafe { LLVMOrcAddLazilyCompiledIR(self.0, handle.as_mut_ptr(), module.module.get(), sym_resolve, sym_resolve_ctx) }
624            // } else {
625            //     unsafe { LLVMOrcAddEagerlyCompiledIR(self.0, handle.as_mut_ptr(), module.module.get(), sym_resolve, sym_resolve_ctx) }
626            // };
627
628            Ok(())
629        }
630
631        /// Obtains an error message owned by the ORC JIT stack.
632        pub fn get_error(&self) -> &CStr {
633            let err_str = unsafe { LLVMOrcGetErrorMsg(self.0) };
634
635            if err_str.is_null() {
636                panic!("Needs to be optional")
637            }
638
639            unsafe { CStr::from_ptr(err_str) }
640        }
641
642        pub fn get_mangled_symbol(&self, symbol: &str) -> MangledSymbol {
643            let mut mangled_symbol = MaybeUninit::uninit();
644            let c_symbol = to_c_str(symbol);
645
646            unsafe { LLVMOrcGetMangledSymbol(self.0, mangled_symbol.as_mut_ptr(), c_symbol.as_ptr()) };
647
648            MangledSymbol(unsafe { mangled_symbol.assume_init() })
649        }
650    }
651
652    impl Drop for Orc {
653        fn drop(&mut self) {
654            // REVIEW: This returns an LLVMErrorRef, not sure what we can do with it...
655            // print to stderr maybe?
656            LLVMError(unsafe { LLVMOrcDisposeInstance(self.0) });
657        }
658    }
659
660    #[test]
661    fn test_mangled_str() {
662        use crate::targets::{CodeModel, InitializationConfig, RelocMode, Target};
663        use crate::OptimizationLevel;
664
665        Target::initialize_native(&InitializationConfig::default()).unwrap();
666
667        let target_triple = TargetMachine::get_default_triple();
668        let target = Target::from_triple(&target_triple).unwrap();
669        let target_machine = target
670            .create_target_machine(
671                &target_triple,
672                &"",
673                &"",
674                OptimizationLevel::None,
675                RelocMode::Default,
676                CodeModel::Default,
677            )
678            .unwrap();
679        let orc = Orc::create(target_machine);
680
681        assert_eq!(orc.get_error().to_str().unwrap(), "");
682
683        let mangled_symbol = orc.get_mangled_symbol("MyStructName");
684
685        assert_eq!(orc.get_error().to_str().unwrap(), "");
686
687        // REVIEW: This doesn't seem very mangled...
688        assert_eq!(mangled_symbol.to_str().unwrap(), "MyStructName");
689    }
690}