revmc_llvm/
orc.rs

1//! Safe wrappers for LLVM ORC and LLJIT, which are not yet implemented in [`inkwell`].
2//!
3//! Header files implemented:
4//! - `LLJIT.h`
5//! - `LLJITUtils.h` (experimental, not available in `llvm-sys`)
6//! - `Orc.h`
7//! - `OrcEE.h` (experimental)
8//!
9//! Note that lifetimes are implicit here, I just didn't bother to add them.
10
11#![allow(missing_debug_implementations)]
12#![allow(clippy::new_without_default)]
13#![allow(clippy::missing_safety_doc)]
14#![allow(clippy::too_many_arguments)]
15
16use crate::llvm_string;
17use inkwell::{
18    llvm_sys::{
19        core::{LLVMContextCreate, LLVMModuleCreateWithNameInContext},
20        error::*,
21        orc2::{lljit::*, *},
22        prelude::*,
23    },
24    module::Module,
25    support::LLVMString,
26    targets::TargetMachine,
27};
28use std::{
29    ffi::{c_char, c_void, CStr, CString},
30    fmt,
31    marker::PhantomData,
32    mem::{self, MaybeUninit},
33    panic::AssertUnwindSafe,
34    ptr::{self, NonNull},
35};
36
37/// A thread-safe LLVM context.
38///
39/// Must use a lock to access the context in multi-threaded scenarios.
40///
41/// See [the ORCv2 docs](https://releases.llvm.org/17.0.1/docs/ORCv2.html).
42pub struct ThreadSafeContext {
43    ctx: LLVMOrcThreadSafeContextRef,
44}
45
46impl ThreadSafeContext {
47    /// Creates a new thread-safe context.
48    pub fn new() -> Self {
49        unsafe { Self::from_inner(LLVMOrcCreateNewThreadSafeContext()) }
50    }
51
52    /// Wraps a raw pointer.
53    pub unsafe fn from_inner(ctx: LLVMOrcThreadSafeContextRef) -> Self {
54        Self { ctx }
55    }
56
57    /// Unwraps the raw pointer.
58    pub fn as_inner(&self) -> LLVMOrcThreadSafeContextRef {
59        self.ctx
60    }
61
62    /// Create a ThreadSafeModule wrapper around the given LLVM module.
63    pub fn create_module<'ctx>(&'ctx self, module: Module<'ctx>) -> ThreadSafeModule {
64        ThreadSafeModule::create_in_context(module, self)
65    }
66}
67
68unsafe impl Send for ThreadSafeContext {}
69
70impl Drop for ThreadSafeContext {
71    fn drop(&mut self) {
72        unsafe { LLVMOrcDisposeThreadSafeContext(self.ctx) };
73    }
74}
75
76/// A thread-safe module.
77///
78/// See [the ORCv2 docs](https://releases.llvm.org/17.0.1/docs/ORCv2.html).
79// NOTE: A lifetime is not needed according to `LLVMOrcCreateNewThreadSafeContext`
80// > Ownership of the underlying ThreadSafeContext data is shared: Clients can and should dispose of
81// > their ThreadSafeContext as soon as they no longer need to refer to it directly. Other
82// > references (e.g. from ThreadSafeModules) will keep the data alive as long as it is needed.
83pub struct ThreadSafeModule {
84    ptr: LLVMOrcThreadSafeModuleRef,
85}
86
87extern "C" {
88    fn LLVMOrcCreateNewThreadSafeContextFromLLVMContext(
89        Ctx: LLVMContextRef,
90    ) -> LLVMOrcThreadSafeContextRef;
91}
92
93impl ThreadSafeModule {
94    /// Creates a new module with the given name in a new context.
95    ///
96    /// Use [`Self::with_module`] to access and modify the module.
97    pub fn create(name: &str) -> Self {
98        let name_cstr = CString::new(name).unwrap();
99        unsafe {
100            let ctx = LLVMContextCreate();
101            let module = LLVMModuleCreateWithNameInContext(name_cstr.as_ptr(), ctx);
102            let tsc = LLVMOrcCreateNewThreadSafeContextFromLLVMContext(ctx);
103            let ptr = LLVMOrcCreateNewThreadSafeModule(module, tsc);
104            LLVMOrcDisposeThreadSafeContext(tsc);
105            Self { ptr }
106        }
107    }
108
109    /// Create a ThreadSafeModule wrapper around the given LLVM module.
110    pub fn create_in_context<'ctx>(module: Module<'ctx>, ctx: &'ctx ThreadSafeContext) -> Self {
111        let module = mem::ManuallyDrop::new(module);
112        let ptr = unsafe { LLVMOrcCreateNewThreadSafeModule(module.as_mut_ptr(), ctx.as_inner()) };
113        Self { ptr }
114    }
115
116    /// Wraps a raw pointer.
117    pub unsafe fn from_inner(ptr: LLVMOrcThreadSafeModuleRef) -> Self {
118        Self { ptr }
119    }
120
121    /// Unwraps the raw pointer.
122    pub fn as_inner(&self) -> LLVMOrcThreadSafeModuleRef {
123        self.ptr
124    }
125
126    /// Runs the given closure with the module.
127    ///
128    /// This implicitly locks the associated context.
129    pub fn with_module<'tsm>(
130        &'tsm self,
131        mut f: impl FnMut(&Module<'tsm>) -> Result<(), String>,
132    ) -> Result<(), LLVMString> {
133        extern "C" fn shim(ctx: *mut c_void, m: LLVMModuleRef) -> LLVMErrorRef {
134            let f = ctx.cast::<&mut dyn FnMut(&Module<'_>) -> Result<(), String>>();
135            let m = mem::ManuallyDrop::new(unsafe { Module::new(m) });
136            let res = std::panic::catch_unwind(AssertUnwindSafe(|| unsafe { (*f)(&m) }));
137            cvt_cb_res(res)
138        }
139
140        let mut f = &mut f as &mut dyn FnMut(&Module<'tsm>) -> Result<(), String>;
141        let ctx = &mut f as *mut _ as *mut c_void;
142        cvt(unsafe { LLVMOrcThreadSafeModuleWithModuleDo(self.as_inner(), shim, ctx) })
143    }
144}
145
146unsafe impl Send for ThreadSafeModule {}
147
148impl Drop for ThreadSafeModule {
149    fn drop(&mut self) {
150        unsafe { LLVMOrcDisposeThreadSafeModule(self.ptr) };
151    }
152}
153
154/// A symbol string pool reference.
155#[repr(C)]
156pub struct SymbolStringPoolRef {
157    ptr: LLVMOrcSymbolStringPoolRef,
158}
159
160impl SymbolStringPoolRef {
161    /// Wraps a raw pointer.
162    pub unsafe fn from_inner(ptr: LLVMOrcSymbolStringPoolRef) -> Self {
163        Self { ptr }
164    }
165
166    /// Unwraps the raw pointer.
167    pub fn as_inner(&self) -> LLVMOrcSymbolStringPoolRef {
168        self.ptr
169    }
170
171    /// Clear all unreferenced symbol string pool entries.
172    ///
173    /// This can be called at any time to release unused entries in the
174    /// ExecutionSession's string pool. Since it locks the pool (preventing
175    /// interning of any new strings) it is recommended that it only be called
176    /// infrequently, ideally when the caller has reason to believe that some
177    /// entries will have become unreferenced, e.g. after removing a module or
178    /// closing a JITDylib.
179    pub fn clear_dead_entries(&self) {
180        unsafe { LLVMOrcSymbolStringPoolClearDeadEntries(self.as_inner()) };
181    }
182}
183
184/// A reference-counted unique string interned in a `SymbolStringPool`.
185#[derive(PartialEq, Eq, Hash)]
186#[repr(C)]
187pub struct SymbolStringPoolEntry {
188    ptr: NonNull<LLVMOrcOpaqueSymbolStringPoolEntry>,
189}
190
191impl Clone for SymbolStringPoolEntry {
192    fn clone(&self) -> Self {
193        unsafe { LLVMOrcRetainSymbolStringPoolEntry(self.as_inner()) };
194        Self { ..*self }
195    }
196}
197
198impl fmt::Debug for SymbolStringPoolEntry {
199    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200        self.as_cstr().fmt(f)
201    }
202}
203
204impl std::ops::Deref for SymbolStringPoolEntry {
205    type Target = CStr;
206
207    fn deref(&self) -> &Self::Target {
208        self.as_cstr()
209    }
210}
211
212impl SymbolStringPoolEntry {
213    /// Wraps a raw pointer.
214    pub unsafe fn from_inner(ptr: LLVMOrcSymbolStringPoolEntryRef) -> Option<Self> {
215        NonNull::new(ptr).map(|ptr| Self { ptr })
216    }
217
218    /// Wraps a raw pointer. Must not be null.
219    pub unsafe fn from_inner_unchecked(ptr: LLVMOrcSymbolStringPoolEntryRef) -> Self {
220        Self { ptr: NonNull::new_unchecked(ptr) }
221    }
222
223    /// Unwraps the raw pointer.
224    pub fn as_inner(&self) -> LLVMOrcSymbolStringPoolEntryRef {
225        self.ptr.as_ptr()
226    }
227
228    /// Convert to a C string.
229    pub fn as_cstr(&self) -> &CStr {
230        unsafe { CStr::from_ptr(LLVMOrcSymbolStringPoolEntryStr(self.as_inner())) }
231    }
232}
233
234impl Drop for SymbolStringPoolEntry {
235    fn drop(&mut self) {
236        unsafe { LLVMOrcReleaseSymbolStringPoolEntry(self.as_inner()) }
237    }
238}
239
240/// An evaluated symbol.
241#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
242#[repr(C)]
243pub struct EvaluatedSymbol {
244    /// The address of the symbol.
245    pub address: u64,
246    /// The flags of the symbol.
247    pub flags: SymbolFlags,
248}
249
250impl EvaluatedSymbol {
251    /// Create a new EvaluatedSymbol from the given address and flags.
252    pub fn new(address: u64, flags: SymbolFlags) -> Self {
253        Self { address, flags }
254    }
255
256    /// Create a new EvaluatedSymbol from the given flags.
257    pub fn from_flags(flags: SymbolFlags) -> Self {
258        Self { address: 0, flags }
259    }
260
261    /// Create a new EvaluatedSymbol from the given address.
262    pub fn from_address(address: usize) -> Self {
263        Self { address: address as u64, flags: SymbolFlags::none() }
264    }
265}
266
267/// Symbol flags.
268#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
269#[repr(C)]
270pub struct SymbolFlags {
271    /// The generic flags.
272    pub generic: u8,
273    /// The target flags.
274    pub target: u8,
275}
276
277impl SymbolFlags {
278    /// Create a new, empty SymbolFlags.
279    pub fn none() -> Self {
280        Self { generic: LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsNone as u8, target: 0 }
281    }
282
283    /// Set the `Exported` flag.
284    pub fn set_exported(&mut self) {
285        self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsExported as u8;
286    }
287
288    /// Set the `Exported` flag.
289    pub fn with_exported(mut self) -> Self {
290        self.set_exported();
291        self
292    }
293
294    /// Returns `true` if the `Exported` flag is set.
295    pub fn is_exported(&self) -> bool {
296        (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsExported as u8) != 0
297    }
298
299    /// Set the `Weak` flag.
300    pub fn set_weak(&mut self) {
301        self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsWeak as u8;
302    }
303
304    /// Set the `Weak` flag.
305    pub fn weak(mut self) -> Self {
306        self.set_weak();
307        self
308    }
309
310    /// Returns `true` if the `Weak` flag is set.
311    pub fn is_weak(&self) -> bool {
312        (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsWeak as u8) != 0
313    }
314
315    /// Set the `Callable` flag.
316    pub fn set_callable(&mut self) {
317        self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsCallable as u8;
318    }
319
320    /// Set the `Callable` flag.
321    pub fn callable(mut self) -> Self {
322        self.set_callable();
323        self
324    }
325
326    /// Returns `true` if the `Callable` flag is set.
327    pub fn is_callable(&self) -> bool {
328        (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsCallable as u8) != 0
329    }
330
331    /// Set the `MaterializationSideEffectsOnly` flag.
332    pub fn set_materialization_side_effects_only(&mut self) {
333        self.generic |=
334            LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly
335                as u8;
336    }
337
338    /// Set the `MaterializationSideEffectsOnly` flag.
339    pub fn materialization_side_effects_only(mut self) -> Self {
340        self.set_materialization_side_effects_only();
341        self
342    }
343
344    /// Returns `true` if the `MaterializationSideEffectsOnly` flag is set.
345    pub fn is_materialization_side_effects_only(&self) -> bool {
346        (self.generic
347            & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly
348                as u8)
349            != 0
350    }
351
352    /// Add a generic flag.
353    pub fn set_generic(&mut self, flag: LLVMJITSymbolGenericFlags) {
354        self.generic |= flag as u8;
355    }
356
357    /// Add a generic flag.
358    pub fn with_generic(mut self, flag: LLVMJITSymbolGenericFlags) -> Self {
359        self.set_generic(flag);
360        self
361    }
362
363    /// Add a target flag.
364    pub fn set_target(&mut self, flag: LLVMJITSymbolTargetFlags) {
365        self.target |= flag;
366    }
367
368    /// Add a target flag.
369    pub fn with_target(mut self, flag: LLVMJITSymbolTargetFlags) -> Self {
370        self.set_target(flag);
371        self
372    }
373}
374
375/// A pair of a symbol name and flags.
376#[derive(Clone, Debug, PartialEq, Eq, Hash)]
377#[repr(C)]
378pub struct SymbolFlagsMapPair {
379    /// The symbol name.
380    pub name: SymbolStringPoolEntry,
381    /// The symbol flags.
382    pub flags: SymbolFlags,
383}
384
385impl SymbolFlagsMapPair {
386    /// Create a new pair.
387    pub fn new(name: SymbolStringPoolEntry, flags: SymbolFlags) -> Self {
388        Self { name, flags }
389    }
390}
391
392/// A pair of a symbol name and an evaluated symbol.
393#[derive(Clone, Debug, PartialEq, Eq, Hash)]
394#[repr(C)]
395pub struct SymbolMapPair {
396    /// The symbol name.
397    pub name: SymbolStringPoolEntry,
398    /// The evaluated symbol.
399    pub evaluated_symbol: EvaluatedSymbol,
400}
401
402impl SymbolMapPair {
403    /// Create a new pair.
404    pub fn new(name: SymbolStringPoolEntry, evaluated_symbol: EvaluatedSymbol) -> Self {
405        Self { name, evaluated_symbol }
406    }
407}
408
409/// An owned list of symbol flags map pairs.
410///
411/// Returned by [`MaterializationResponsibilityRef::get_symbols`].
412pub struct SymbolFlagsMapPairs<'a>(&'a [SymbolFlagsMapPair]);
413
414impl<'a> SymbolFlagsMapPairs<'a> {
415    /// Returns the slice of pairs.
416    pub fn as_slice(&self) -> &'a [SymbolFlagsMapPair] {
417        self.0
418    }
419}
420
421impl std::ops::Deref for SymbolFlagsMapPairs<'_> {
422    type Target = [SymbolFlagsMapPair];
423
424    fn deref(&self) -> &Self::Target {
425        self.0
426    }
427}
428
429impl Drop for SymbolFlagsMapPairs<'_> {
430    fn drop(&mut self) {
431        unsafe { LLVMOrcDisposeCSymbolFlagsMap(self.0.as_ptr().cast_mut().cast()) };
432    }
433}
434
435/// A materialization unit.
436pub struct MaterializationUnit {
437    mu: LLVMOrcMaterializationUnitRef,
438}
439
440impl MaterializationUnit {
441    /// Create a custom MaterializationUnit.
442    pub fn new_custom(
443        name: &CStr,
444        syms: Vec<SymbolFlagsMapPair>,
445        init_sym: Option<SymbolStringPoolEntry>,
446        mu: Box<dyn CustomMaterializationUnit>,
447    ) -> Self {
448        extern "C" fn materialize(ctx: *mut c_void, mr: LLVMOrcMaterializationResponsibilityRef) {
449            // Ownership of the Ctx and MR arguments passes to the callback which must adhere to the
450            // LLVMOrcMaterializationResponsibilityRef contract (see comment for that type).
451            //
452            // If this callback is called then the LLVMOrcMaterializationUnitDestroy callback will
453            // NOT be called.
454            let ctx = unsafe { Box::from_raw(ctx.cast::<Box<dyn CustomMaterializationUnit>>()) };
455            let mr = unsafe { MaterializationResponsibility::from_inner(mr) };
456            let res = std::panic::catch_unwind(AssertUnwindSafe(move || ctx.materialize(mr)));
457            if let Err(e) = res {
458                error!(msg=?panic_payload(&e), "materialize callback panicked");
459            }
460        }
461
462        extern "C" fn discard(
463            ctx: *mut c_void,
464            jd: LLVMOrcJITDylibRef,
465            symbol: LLVMOrcSymbolStringPoolEntryRef,
466        ) {
467            // Ownership of JD and Symbol remain with the caller:
468            // these arguments should not be disposed of or released.
469            let ctx = unsafe { &mut **ctx.cast::<Box<dyn CustomMaterializationUnit>>() };
470            let jd = unsafe { JITDylibRef::from_inner_unchecked(jd) };
471            let symbol = mem::ManuallyDrop::new(unsafe {
472                SymbolStringPoolEntry::from_inner_unchecked(symbol)
473            });
474            let res = std::panic::catch_unwind(AssertUnwindSafe(|| ctx.discard(jd, &symbol)));
475            if let Err(e) = res {
476                error!(msg=?panic_payload(&e), "discard callback panicked");
477            }
478        }
479
480        extern "C" fn destroy(ctx: *mut c_void) {
481            // If a custom MaterializationUnit is destroyed before its Materialize function is
482            // called then this function will be called to provide an opportunity for the underlying
483            // program representation to be destroyed.
484            let ctx = unsafe { Box::from_raw(ctx.cast::<Box<dyn CustomMaterializationUnit>>()) };
485            let res = std::panic::catch_unwind(AssertUnwindSafe(|| drop(ctx)));
486            if let Err(e) = res {
487                error!(msg=?panic_payload(&e), "destroy callback panicked");
488            }
489        }
490
491        let ctx = Box::into_raw(Box::new(mu)).cast();
492        let init_sym = if let Some(init_sym) = init_sym {
493            mem::ManuallyDrop::new(init_sym).as_inner()
494        } else {
495            ptr::null_mut()
496        };
497        let syms = ManuallyDropElements::new(syms);
498        unsafe {
499            Self::new_custom_raw(
500                name,
501                ctx,
502                syms.as_ptr().cast_mut().cast(),
503                syms.len(),
504                init_sym,
505                materialize,
506                discard,
507                destroy,
508            )
509        }
510    }
511
512    /// Create a custom MaterializationUnit.
513    ///
514    /// See [`Self::new_custom`].
515    pub unsafe fn new_custom_raw(
516        name: &CStr,
517        ctx: *mut c_void,
518        syms: LLVMOrcCSymbolFlagsMapPairs,
519        num_syms: usize,
520        init_sym: LLVMOrcSymbolStringPoolEntryRef,
521        materialize: LLVMOrcMaterializationUnitMaterializeFunction,
522        discard: LLVMOrcMaterializationUnitDiscardFunction,
523        destroy: LLVMOrcMaterializationUnitDestroyFunction,
524    ) -> Self {
525        Self::from_inner(LLVMOrcCreateCustomMaterializationUnit(
526            name.as_ptr(),
527            ctx,
528            syms,
529            num_syms,
530            init_sym,
531            materialize,
532            discard,
533            destroy,
534        ))
535    }
536
537    /// Create a MaterializationUnit to define the given symbols as pointing to the corresponding
538    /// raw addresses.
539    pub fn absolute_symbols(syms: Vec<SymbolMapPair>) -> Self {
540        let syms = ManuallyDropElements::new(syms);
541        unsafe { Self::absolute_symbols_raw(syms.as_ptr().cast_mut().cast(), syms.len()) }
542    }
543
544    /// Create a MaterializationUnit to define the given symbols as pointing to the corresponding
545    /// raw addresses.
546    ///
547    /// See [`Self::absolute_symbols`].
548    pub unsafe fn absolute_symbols_raw(syms: LLVMOrcCSymbolMapPairs, len: usize) -> Self {
549        unsafe { Self::from_inner(LLVMOrcAbsoluteSymbols(syms, len)) }
550    }
551
552    // TODO: fn lazy_reexports
553
554    /// Wraps a raw pointer.
555    pub unsafe fn from_inner(mu: LLVMOrcMaterializationUnitRef) -> Self {
556        Self { mu }
557    }
558
559    /// Unwraps the raw pointer.
560    pub fn as_inner(&self) -> LLVMOrcMaterializationUnitRef {
561        self.mu
562    }
563}
564
565impl Drop for MaterializationUnit {
566    fn drop(&mut self) {
567        unsafe { LLVMOrcDisposeMaterializationUnit(self.as_inner()) };
568    }
569}
570
571/// A custom materialization unit.
572///
573/// Use with [`MaterializationUnit::new_custom`].
574pub trait CustomMaterializationUnit {
575    /// Materialize callback.
576    fn materialize(self: Box<Self>, mr: MaterializationResponsibility);
577
578    /// Discard callback.
579    fn discard(&mut self, jd: JITDylibRef, symbol: &SymbolStringPoolEntry);
580
581    // fn destroy is Drop
582}
583
584/// An owned materialization responsibility.
585pub struct MaterializationResponsibility {
586    mr: LLVMOrcMaterializationResponsibilityRef,
587}
588
589impl MaterializationResponsibility {
590    /// Wraps a raw pointer.
591    pub unsafe fn from_inner(mr: LLVMOrcMaterializationResponsibilityRef) -> Self {
592        Self { mr }
593    }
594
595    /// Unwraps the raw pointer.
596    pub fn as_inner(&self) -> LLVMOrcMaterializationResponsibilityRef {
597        self.mr
598    }
599
600    /// Returns a reference to the MaterializationResponsibility.
601    #[inline]
602    pub fn as_ref(&self) -> MaterializationResponsibilityRef<'_> {
603        unsafe { MaterializationResponsibilityRef::from_inner(self.as_inner()) }
604    }
605}
606
607impl Drop for MaterializationResponsibility {
608    fn drop(&mut self) {
609        unsafe { LLVMOrcDisposeMaterializationResponsibility(self.as_inner()) };
610    }
611}
612
613/// A reference to a materialization responsibility.
614pub struct MaterializationResponsibilityRef<'mr> {
615    mr: LLVMOrcMaterializationResponsibilityRef,
616    _marker: PhantomData<&'mr ()>,
617}
618
619impl<'mr> MaterializationResponsibilityRef<'mr> {
620    /// Wraps a raw pointer.
621    pub unsafe fn from_inner(mr: LLVMOrcMaterializationResponsibilityRef) -> Self {
622        Self { mr, _marker: PhantomData }
623    }
624
625    /// Unwraps the raw pointer.
626    pub fn as_inner(&self) -> LLVMOrcMaterializationResponsibilityRef {
627        self.mr
628    }
629
630    /// Returns the target JITDylib that these symbols are being materialized into.
631    pub fn get_target_dylib(&self) -> JITDylibRef {
632        unsafe {
633            JITDylibRef::from_inner_unchecked(LLVMOrcMaterializationResponsibilityGetTargetDylib(
634                self.as_inner(),
635            ))
636        }
637    }
638
639    /// Returns the ExecutionSession for this MaterializationResponsibility.
640    pub fn get_execution_session(&self) -> ExecutionSessionRef<'mr> {
641        unsafe {
642            ExecutionSessionRef::from_inner(
643                LLVMOrcMaterializationResponsibilityGetExecutionSession(self.as_inner()),
644            )
645        }
646    }
647
648    /// Returns the symbol flags map for this responsibility instance.
649    pub fn get_symbols(&self) -> SymbolFlagsMapPairs<'mr> {
650        /*
651         * The length of the array is returned in NumPairs and the caller is responsible
652         * for the returned memory and needs to call LLVMOrcDisposeCSymbolFlagsMap.
653         *
654         * To use the returned symbols beyond the lifetime of the
655         * MaterializationResponsibility requires the caller to retain the symbols
656         * explicitly.
657         */
658        let mut len = MaybeUninit::uninit();
659        let data = unsafe {
660            LLVMOrcMaterializationResponsibilityGetSymbols(self.as_inner(), len.as_mut_ptr())
661        };
662        SymbolFlagsMapPairs(unsafe { std::slice::from_raw_parts(data.cast(), len.assume_init()) })
663    }
664
665    /// Returns the initialization pseudo-symbol, if any.
666    ///
667    /// This symbol will also be present in the SymbolFlagsMap for this
668    /// MaterializationResponsibility object.
669    pub fn get_initializer_symbol(&self) -> Option<SymbolStringPoolEntry> {
670        let ptr =
671            unsafe { LLVMOrcMaterializationResponsibilityGetInitializerSymbol(self.as_inner()) };
672        unsafe { SymbolStringPoolEntry::from_inner(ptr) }
673    }
674
675    /// Returns the names of any symbols covered by this MaterializationResponsibility object that
676    /// have queries pending.
677    ///
678    /// This information can be used to return responsibility for unrequested symbols back to the
679    /// JITDylib via the delegate method.
680    pub fn get_requested_symbols(&self) -> &[SymbolStringPoolEntry] {
681        let mut len = MaybeUninit::uninit();
682        let ptr = unsafe {
683            LLVMOrcMaterializationResponsibilityGetRequestedSymbols(
684                self.as_inner(),
685                len.as_mut_ptr(),
686            )
687        };
688        unsafe { std::slice::from_raw_parts(ptr.cast(), len.assume_init()) }
689    }
690
691    /// Notifies the target JITDylib that the given symbols have been resolved.
692    pub fn notify_resolved(&self, syms: &[SymbolFlagsMapPair]) -> Result<(), LLVMString> {
693        cvt(unsafe {
694            LLVMOrcMaterializationResponsibilityNotifyResolved(
695                self.as_inner(),
696                syms.as_ptr().cast_mut().cast(),
697                syms.len(),
698            )
699        })
700    }
701
702    /// Notifies the target JITDylib (and any pending queries on that JITDylib)
703    /// that all symbols covered by this MaterializationResponsibility instance
704    /// have been emitted.
705    ///
706    /// `symbol_dep_groups` specifies the symbol dependency groups for this materialization unit.
707    /// Pass an empty slice if there are no dependencies.
708    pub fn notify_emitted(
709        &self,
710        symbol_dep_groups: &mut [LLVMOrcCSymbolDependenceGroup],
711    ) -> Result<(), LLVMString> {
712        cvt(unsafe {
713            LLVMOrcMaterializationResponsibilityNotifyEmitted(
714                self.as_inner(),
715                symbol_dep_groups.as_mut_ptr(),
716                symbol_dep_groups.len(),
717            )
718        })
719    }
720
721    /// Notify all not-yet-emitted covered by this MaterializationResponsibility instance that an
722    /// error has occurred.
723    ///
724    /// This will remove all symbols covered by this MaterializationResponsibility from the target
725    /// JITDylib, and send an error to any queries waiting on these symbols.
726    pub fn fail_materialization(&self) {
727        unsafe { LLVMOrcMaterializationResponsibilityFailMaterialization(self.as_inner()) };
728    }
729
730    /// Transfers responsibility to the given MaterializationUnit for all symbols defined by that
731    /// MaterializationUnit.
732    ///
733    /// This allows materializers to break up work based on run-time information (e.g.
734    /// by introspecting which symbols have actually been looked up and
735    /// materializing only those).
736    pub fn replace(&self, mu: MaterializationUnit) -> Result<(), LLVMString> {
737        let mu = mem::ManuallyDrop::new(mu);
738        cvt(unsafe { LLVMOrcMaterializationResponsibilityReplace(self.as_inner(), mu.as_inner()) })
739    }
740
741    /// Delegates responsibility for the given symbols to the returned
742    /// materialization responsibility. Useful for breaking up work between
743    /// threads, or different kinds of materialization processes.
744    ///
745    /// The caller retains responsibility of the the passed
746    /// MaterializationResponsibility.
747    pub fn delegate(&self, syms: &[SymbolStringPoolEntry]) -> Result<Self, LLVMString> {
748        let mut res = MaybeUninit::uninit();
749        cvt(unsafe {
750            LLVMOrcMaterializationResponsibilityDelegate(
751                self.as_inner(),
752                syms.as_ptr().cast_mut().cast(),
753                syms.len(),
754                res.as_mut_ptr(),
755            )
756        })?;
757        Ok(unsafe { Self::from_inner(res.assume_init()) })
758    }
759}
760
761/// A resource tracker.
762///
763/// ResourceTrackers allow you to remove code.
764pub struct ResourceTracker {
765    rt: LLVMOrcResourceTrackerRef,
766}
767
768impl ResourceTracker {
769    /// Wraps a raw pointer.
770    pub unsafe fn from_inner(rt: LLVMOrcResourceTrackerRef) -> Self {
771        Self { rt }
772    }
773
774    /// Unwraps the raw pointer.
775    pub fn as_inner(&self) -> LLVMOrcResourceTrackerRef {
776        self.rt
777    }
778
779    /// Remove all resources associated with this tracker.
780    pub fn remove(&self) -> Result<(), LLVMString> {
781        cvt(unsafe { LLVMOrcResourceTrackerRemove(self.as_inner()) })
782    }
783
784    /// Transfers tracking of all resources associated with this resource tracker to the given
785    /// resource tracker.
786    pub fn transfer_to(&self, rt: &Self) {
787        unsafe { LLVMOrcResourceTrackerTransferTo(self.as_inner(), rt.as_inner()) };
788    }
789}
790
791impl Drop for ResourceTracker {
792    fn drop(&mut self) {
793        unsafe { LLVMOrcReleaseResourceTracker(self.as_inner()) };
794    }
795}
796
797/// A JIT execution session reference.
798///
799/// Returned by [`LLJIT::get_execution_session`] and
800/// [`MaterializationResponsibilityRef::get_execution_session`].
801///
802/// ExecutionSession represents the JIT'd program and provides context for the JIT: It contains the
803/// JITDylibs, error reporting mechanisms, and dispatches the materializers.
804///
805/// See [the ORCv2 docs](https://releases.llvm.org/17.0.1/docs/ORCv2.html).
806pub struct ExecutionSessionRef<'ee> {
807    es: LLVMOrcExecutionSessionRef,
808    _marker: PhantomData<&'ee ()>,
809}
810
811impl ExecutionSessionRef<'_> {
812    /// Wraps a raw pointer.
813    pub unsafe fn from_inner(es: LLVMOrcExecutionSessionRef) -> Self {
814        Self { es, _marker: PhantomData }
815    }
816
817    /// Unwraps the raw pointer.
818    pub fn as_inner(&self) -> LLVMOrcExecutionSessionRef {
819        self.es
820    }
821
822    /// Intern a string in the ExecutionSession's SymbolStringPool and return a reference to it.
823    pub fn intern(&self, name: &CStr) -> SymbolStringPoolEntry {
824        unsafe {
825            SymbolStringPoolEntry::from_inner_unchecked(LLVMOrcExecutionSessionIntern(
826                self.as_inner(),
827                name.as_ptr(),
828            ))
829        }
830    }
831
832    /// Returns the JITDylib with the given name, if any.
833    pub fn get_dylib_by_name(&self, name: &CStr) -> Option<JITDylibRef> {
834        unsafe {
835            let dylib = LLVMOrcExecutionSessionGetJITDylibByName(self.as_inner(), name.as_ptr());
836            JITDylibRef::from_inner(dylib)
837        }
838    }
839
840    /// Create a "bare" JITDylib.
841    ///
842    /// The client is responsible for ensuring that the JITDylib's name is unique.
843    ///
844    /// This call does not install any library code or symbols into the newly created JITDylib. The
845    /// client is responsible for all configuration.
846    pub fn create_bare_jit_dylib(&self, name: &CStr) -> JITDylibRef {
847        debug_assert!(self.get_dylib_by_name(name).is_none());
848        unsafe {
849            JITDylibRef::from_inner_unchecked(LLVMOrcExecutionSessionCreateBareJITDylib(
850                self.as_inner(),
851                name.as_ptr(),
852            ))
853        }
854    }
855
856    /// Create a JITDylib.
857    ///
858    /// The client is responsible for ensuring that the JITDylib's name is unique.
859    ///
860    /// If a Platform is attached to the ExecutionSession then Platform::setupJITDylib will be
861    /// called to install standard platform symbols (e.g. standard library interposes). If no
862    /// Platform is installed then this call is equivalent to [Self::create_bare_jit_dylib] and will
863    /// always return success.
864    pub fn create_jit_dylib(&self, name: &CStr) -> Result<JITDylibRef, LLVMString> {
865        debug_assert!(self.get_dylib_by_name(name).is_none());
866        let mut res = MaybeUninit::uninit();
867        cvt(unsafe {
868            LLVMOrcExecutionSessionCreateJITDylib(self.as_inner(), res.as_mut_ptr(), name.as_ptr())
869        })?;
870        Ok(unsafe { JITDylibRef::from_inner_unchecked(res.assume_init()) })
871    }
872
873    /// Sets the default error reporter to the ExecutionSession.
874    ///
875    /// Uses [`tracing::error!`] to log the error message.
876    pub fn set_default_error_reporter(&self) {
877        self.set_error_reporter(|msg| error!(msg = %msg.to_string_lossy(), "LLVM error"))
878    }
879
880    /// Attach a custom error reporter function to the ExecutionSession.
881    pub fn set_error_reporter(&self, f: fn(&CStr)) {
882        extern "C" fn shim(ctx: *mut c_void, err: LLVMErrorRef) {
883            let f = ctx as *mut fn(&CStr);
884            let Err(e) = cvt(err) else { return };
885            let res = std::panic::catch_unwind(AssertUnwindSafe(|| unsafe { (*f)(&e) }));
886            if let Err(e) = res {
887                error!(msg=?panic_payload(&e), "error reporter closure panicked");
888            }
889        }
890
891        let ctx = f as *mut c_void;
892        unsafe { LLVMOrcExecutionSessionSetErrorReporter(self.as_inner(), shim, ctx) };
893    }
894}
895
896/// A JIT dynamic library reference.
897///
898/// JITDylibs provide the symbol tables.
899pub struct JITDylibRef {
900    dylib: NonNull<LLVMOrcOpaqueJITDylib>,
901}
902
903impl JITDylibRef {
904    /// Wraps a raw pointer.
905    pub unsafe fn from_inner(dylib: LLVMOrcJITDylibRef) -> Option<Self> {
906        NonNull::new(dylib).map(|dylib| Self { dylib })
907    }
908
909    /// Wraps a raw pointer. Must not be null.
910    pub unsafe fn from_inner_unchecked(dylib: LLVMOrcJITDylibRef) -> Self {
911        Self { dylib: NonNull::new_unchecked(dylib) }
912    }
913
914    /// Unwraps the raw pointer.
915    pub fn as_inner(&self) -> LLVMOrcJITDylibRef {
916        self.dylib.as_ptr()
917    }
918
919    /// Return a reference to a newly created resource tracker associated with JD.
920    pub fn create_resource_tracker(&self) -> ResourceTracker {
921        unsafe {
922            ResourceTracker::from_inner(LLVMOrcJITDylibCreateResourceTracker(self.as_inner()))
923        }
924    }
925
926    /// Return a reference to the default resource tracker for the given JITDylib.
927    pub fn get_default_resource_tracker(&self) -> ResourceTracker {
928        unsafe {
929            ResourceTracker::from_inner(LLVMOrcJITDylibGetDefaultResourceTracker(self.as_inner()))
930        }
931    }
932
933    /// Add the given MaterializationUnit to the given JITDylib.
934    pub fn define(&self, mu: MaterializationUnit) -> Result<(), (LLVMString, MaterializationUnit)> {
935        // If this operation succeeds then JITDylib JD will take ownership of MU.
936        // If the operation fails then ownership remains with the caller who should call
937        // LLVMOrcDisposeMaterializationUnit to destroy it.
938        cvt(unsafe { LLVMOrcJITDylibDefine(self.as_inner(), mu.as_inner()) }).map_err(|e| (e, mu))
939    }
940
941    /// Calls remove on all trackers associated with this JITDylib.
942    pub fn clear(&self) -> Result<(), LLVMString> {
943        cvt(unsafe { LLVMOrcJITDylibClear(self.as_inner()) })
944    }
945
946    /// Add a DefinitionGenerator to the given JITDylib.
947    pub fn add_generator(&self, dg: DefinitionGenerator) {
948        // The JITDylib will take ownership of the given generator:
949        // the client is no longer responsible for managing its memory.
950        let dg = mem::ManuallyDrop::new(dg);
951        unsafe { LLVMOrcJITDylibAddGenerator(self.as_inner(), dg.as_inner()) };
952    }
953}
954
955/// Definition generator.
956pub struct DefinitionGenerator {
957    dg: LLVMOrcDefinitionGeneratorRef,
958}
959
960impl DefinitionGenerator {
961    /// Creates a new custom DefinitionGenerator.
962    pub fn new_custom(generator: Box<dyn CustomDefinitionGenerator>) -> Self {
963        extern "C" fn try_to_generate(
964            generator_obj: LLVMOrcDefinitionGeneratorRef,
965            ctx: *mut c_void,
966            lookup_state: *mut LLVMOrcLookupStateRef,
967            kind: LLVMOrcLookupKind,
968            jd: LLVMOrcJITDylibRef,
969            jd_lookup_flags: LLVMOrcJITDylibLookupFlags,
970            lookup_set: LLVMOrcCLookupSet,
971            lookup_set_size: usize,
972        ) -> LLVMErrorRef {
973            let generator = unsafe { &mut **ctx.cast::<Box<dyn CustomDefinitionGenerator>>() };
974            let lookup_state = unsafe { &mut *lookup_state };
975            let jd = unsafe { JITDylibRef::from_inner_unchecked(jd) };
976            let lookup_set = unsafe { std::slice::from_raw_parts(lookup_set, lookup_set_size) };
977            let res = std::panic::catch_unwind(AssertUnwindSafe(|| {
978                generator.try_to_generate(
979                    generator_obj,
980                    lookup_state,
981                    kind,
982                    jd,
983                    jd_lookup_flags,
984                    lookup_set,
985                )
986            }));
987            cvt_cb_res(res)
988        }
989
990        extern "C" fn dispose(ctx: *mut c_void) {
991            let generator =
992                unsafe { Box::from_raw(ctx.cast::<Box<dyn CustomDefinitionGenerator>>()) };
993            let res = std::panic::catch_unwind(AssertUnwindSafe(|| drop(generator)));
994            if let Err(e) = res {
995                error!(msg=?panic_payload(&e), "dispose callback panicked");
996            }
997        }
998
999        let ctx = Box::into_raw(Box::new(generator)).cast();
1000        unsafe { Self::new_custom_raw(try_to_generate, ctx, dispose) }
1001    }
1002
1003    /// Creates a new custom DefinitionGenerator.
1004    ///
1005    /// See [`Self::new_custom`].
1006    pub unsafe fn new_custom_raw(
1007        f: LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction,
1008        ctx: *mut c_void,
1009        dispose: LLVMOrcDisposeCAPIDefinitionGeneratorFunction,
1010    ) -> Self {
1011        Self::from_inner(LLVMOrcCreateCustomCAPIDefinitionGenerator(f, ctx, dispose))
1012    }
1013
1014    /// Wraps a raw pointer.
1015    pub unsafe fn from_inner(dg: LLVMOrcDefinitionGeneratorRef) -> Self {
1016        Self { dg }
1017    }
1018
1019    /// Unwraps the raw pointer.
1020    pub fn as_inner(&self) -> LLVMOrcDefinitionGeneratorRef {
1021        self.dg
1022    }
1023}
1024
1025impl Drop for DefinitionGenerator {
1026    fn drop(&mut self) {
1027        unsafe { LLVMOrcDisposeDefinitionGenerator(self.as_inner()) };
1028    }
1029}
1030
1031/// A custom definition generator.
1032pub trait CustomDefinitionGenerator {
1033    /// A custom generator function.
1034    ///
1035    /// This can be used to create a custom generator object using
1036    /// LLVMOrcCreateCustomCAPIDefinitionGenerator. The resulting object can be attached to a
1037    /// JITDylib, via LLVMOrcJITDylibAddGenerator, to receive callbacks when lookups fail to match
1038    /// existing definitions.
1039    ///
1040    /// GeneratorObj will contain the address of the custom generator object.
1041    ///
1042    /// Ctx will contain the context object passed to LLVMOrcCreateCustomCAPIDefinitionGenerator.
1043    ///
1044    /// LookupState will contain a pointer to an LLVMOrcLookupStateRef object. This can optionally
1045    /// be modified to make the definition generation process asynchronous: If the LookupStateRef
1046    /// value is copied, and the original LLVMOrcLookupStateRef set to null, the lookup will be
1047    /// suspended. Once the asynchronous definition process has been completed clients must call
1048    /// LLVMOrcLookupStateContinueLookup to continue the lookup (this should be done
1049    /// unconditionally, even if errors have occurred in the mean time, to free the lookup state
1050    /// memory and notify the query object of the failures). If LookupState is captured this
1051    /// function must return LLVMErrorSuccess.
1052    ///
1053    /// The Kind argument can be inspected to determine the lookup kind (e.g.
1054    /// as-if-during-static-link, or as-if-during-dlsym).
1055    ///
1056    /// The JD argument specifies which JITDylib the definitions should be generated into.
1057    ///
1058    /// The JDLookupFlags argument can be inspected to determine whether the original lookup
1059    /// included non-exported symbols.
1060    ///
1061    /// Finally, the LookupSet argument contains the set of symbols that could not be found in JD
1062    /// already (the set of generation candidates).
1063    fn try_to_generate(
1064        &mut self,
1065        generator_obj: LLVMOrcDefinitionGeneratorRef,
1066        lookup_state: &mut LLVMOrcLookupStateRef,
1067        kind: LLVMOrcLookupKind,
1068        jd: JITDylibRef,
1069        jd_lookup_flags: LLVMOrcJITDylibLookupFlags,
1070        lookup_set: &[LLVMOrcCLookupSetElement],
1071    ) -> Result<(), String>;
1072}
1073
1074impl<T> CustomDefinitionGenerator for T
1075where
1076    T: FnMut(
1077        LLVMOrcDefinitionGeneratorRef,
1078        &mut LLVMOrcLookupStateRef,
1079        LLVMOrcLookupKind,
1080        JITDylibRef,
1081        LLVMOrcJITDylibLookupFlags,
1082        &[LLVMOrcCLookupSetElement],
1083    ) -> Result<(), String>,
1084{
1085    #[inline]
1086    fn try_to_generate(
1087        &mut self,
1088        generator_obj: LLVMOrcDefinitionGeneratorRef,
1089        lookup_state: &mut LLVMOrcLookupStateRef,
1090        kind: LLVMOrcLookupKind,
1091        jd: JITDylibRef,
1092        jd_lookup_flags: LLVMOrcJITDylibLookupFlags,
1093        lookup_set: &[LLVMOrcCLookupSetElement],
1094    ) -> Result<(), String> {
1095        self(generator_obj, lookup_state, kind, jd, jd_lookup_flags, lookup_set)
1096    }
1097}
1098
1099/// [`LLVMOrcJITTargetMachineBuilderRef`], used in [`LLJITBuilder`].
1100pub struct JITTargetMachineBuilder {
1101    builder: LLVMOrcJITTargetMachineBuilderRef,
1102}
1103
1104impl JITTargetMachineBuilder {
1105    /// Create a JITTargetMachineBuilder from the given TargetMachine template.
1106    pub fn new(tm: TargetMachine) -> Self {
1107        let tm = mem::ManuallyDrop::new(tm);
1108        unsafe {
1109            Self::from_inner(LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm.as_mut_ptr()))
1110        }
1111    }
1112
1113    /// Create a JITTargetMachineBuilder by detecting the host.
1114    pub fn detect_host() -> Result<Self, LLVMString> {
1115        let mut res = MaybeUninit::uninit();
1116        cvt(unsafe { LLVMOrcJITTargetMachineBuilderDetectHost(res.as_mut_ptr()) })?;
1117        Ok(Self { builder: unsafe { res.assume_init() } })
1118    }
1119
1120    /// Wraps a raw pointer.
1121    pub unsafe fn from_inner(builder: LLVMOrcJITTargetMachineBuilderRef) -> Self {
1122        Self { builder }
1123    }
1124
1125    /// Unwraps the raw pointer.
1126    pub fn as_inner(&self) -> LLVMOrcJITTargetMachineBuilderRef {
1127        self.builder
1128    }
1129
1130    /// Returns the target triple for the given JITTargetMachineBuilder as a string.
1131    pub fn get_target_triple(&self) -> LLVMString {
1132        unsafe { llvm_string(LLVMOrcJITTargetMachineBuilderGetTargetTriple(self.as_inner())) }
1133    }
1134
1135    /// Sets the target triple for the given JITTargetMachineBuilder to the given string.
1136    pub fn set_target_triple(&self, triple: &CStr) {
1137        unsafe { LLVMOrcJITTargetMachineBuilderSetTargetTriple(self.as_inner(), triple.as_ptr()) }
1138    }
1139}
1140
1141impl Drop for JITTargetMachineBuilder {
1142    fn drop(&mut self) {
1143        unsafe { LLVMOrcDisposeJITTargetMachineBuilder(self.builder) }
1144    }
1145}
1146
1147/// Lazily-initialized [`LLJIT`] builder.
1148#[must_use]
1149pub struct LLJITBuilder {
1150    builder: lljit::LLVMOrcLLJITBuilderRef,
1151}
1152
1153impl LLJITBuilder {
1154    /// Creates a new default LLJIT builder.
1155    pub fn new() -> Self {
1156        Self { builder: ptr::null_mut() }
1157    }
1158
1159    /// Wraps a raw pointer.
1160    pub unsafe fn from_inner(builder: LLVMOrcLLJITBuilderRef) -> Self {
1161        Self { builder }
1162    }
1163
1164    /// Unwraps the raw pointer.
1165    pub fn as_inner(&self) -> LLVMOrcLLJITBuilderRef {
1166        self.builder
1167    }
1168
1169    fn as_inner_init(&mut self) -> LLVMOrcLLJITBuilderRef {
1170        if self.builder.is_null() {
1171            self.builder = unsafe { LLVMOrcCreateLLJITBuilder() };
1172        }
1173        self.builder
1174    }
1175
1176    /// Set the target machine builder by creating it from the given template.
1177    pub fn set_target_machine(self, tm: TargetMachine) -> Self {
1178        self.set_target_machine_builder(JITTargetMachineBuilder::new(tm))
1179    }
1180
1181    /// Set the target machine builder by detecting the host.
1182    pub fn set_target_machine_from_host(self) -> Result<Self, LLVMString> {
1183        JITTargetMachineBuilder::detect_host().map(|jtmb| self.set_target_machine_builder(jtmb))
1184    }
1185
1186    /// Set the target machine builder.
1187    pub fn set_target_machine_builder(mut self, jtmb: JITTargetMachineBuilder) -> Self {
1188        let jtmb = mem::ManuallyDrop::new(jtmb);
1189        unsafe {
1190            LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(self.as_inner_init(), jtmb.as_inner())
1191        };
1192        self
1193    }
1194
1195    /*
1196    pub fn set_object_linking_layer_creator(self, mut f: &mut dyn FnMut(*const (), &CStr)) -> Self {
1197        extern "C" fn shim(
1198            ctx: *mut c_void,
1199            es: LLVMOrcExecutionSessionRef,
1200            triple: *const c_char,
1201        ) -> LLVMOrcObjectLayerRef {
1202            let f = ctx.cast::<&mut dyn FnMut(*const (), &CStr)>();
1203            let name = unsafe { CStr::from_ptr(triple) };
1204            unsafe { (*f)(es.cast(), name) };
1205            ptr::null_mut()
1206        }
1207
1208        let ctx = &mut f as *mut _ as *mut c_void;
1209        unsafe { LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator(self.as_inner_init(), shim, ctx) };
1210        self
1211    }
1212    */
1213
1214    /// Builds the JIT.
1215    pub fn build(self) -> Result<LLJIT, LLVMString> {
1216        // This operation takes ownership of the Builder argument: clients should not
1217        // dispose of the builder after calling this function (even if the function
1218        // returns an error).
1219        let builder = mem::ManuallyDrop::new(self);
1220        let mut res = MaybeUninit::uninit();
1221        cvt(unsafe { LLVMOrcCreateLLJIT(res.as_mut_ptr(), builder.as_inner()) })?;
1222        Ok(unsafe { LLJIT::from_inner(res.assume_init()) })
1223    }
1224}
1225
1226impl Drop for LLJITBuilder {
1227    fn drop(&mut self) {
1228        unsafe { LLVMOrcDisposeLLJITBuilder(self.builder) };
1229    }
1230}
1231
1232/// An ORC JIT.
1233///
1234/// Manages the memory of all JIT'd code and all modules that are transferred to it.
1235///
1236/// See [the ORCv2 docs](https://releases.llvm.org/17.0.1/docs/ORCv2.html).
1237pub struct LLJIT {
1238    jit: LLVMOrcLLJITRef,
1239}
1240
1241impl LLJIT {
1242    /// Creates a new LLJIT builder.
1243    pub fn builder() -> LLJITBuilder {
1244        LLJITBuilder::new()
1245    }
1246
1247    /// Creates a new ORC JIT with a target machine for the host.
1248    pub fn new() -> Result<Self, LLVMString> {
1249        LLJITBuilder::new().set_target_machine_from_host()?.build()
1250    }
1251
1252    /// Creates a new default ORC JIT.
1253    pub fn new_empty() -> Result<Self, LLVMString> {
1254        LLJITBuilder::new().build()
1255    }
1256
1257    /// Wraps a raw pointer.
1258    pub unsafe fn from_inner(jit: LLVMOrcLLJITRef) -> Self {
1259        Self { jit }
1260    }
1261
1262    /// Unwraps the raw pointer.
1263    pub fn as_inner(&self) -> LLVMOrcLLJITRef {
1264        self.jit
1265    }
1266
1267    /// Return the target triple for this LLJIT instance.
1268    pub fn get_triple_string(&self) -> &CStr {
1269        // This string is owned by the LLJIT instance and does not need to be freed by the caller.
1270        unsafe { CStr::from_ptr(LLVMOrcLLJITGetTripleString(self.jit)) }
1271    }
1272
1273    /// Return the data layout for this LLJIT instance.
1274    pub fn get_data_layout_string(&self) -> &CStr {
1275        // This string is owned by the LLJIT instance and does not need to be freed by the caller.
1276        unsafe { CStr::from_ptr(LLVMOrcLLJITGetDataLayoutStr(self.jit)) }
1277    }
1278
1279    /// Returns the global prefix character according to the LLJIT's DataLayout.
1280    pub fn get_global_prefix(&self) -> c_char {
1281        unsafe { LLVMOrcLLJITGetGlobalPrefix(self.jit) }
1282    }
1283
1284    /// Add an IR module to the main JITDylib.
1285    pub fn add_module(&self, tsm: ThreadSafeModule) -> Result<(), LLVMString> {
1286        let jd = self.get_main_jit_dylib();
1287        self.add_module_with_dylib(tsm, jd)
1288    }
1289
1290    /// Add an IR module to the given JITDylib.
1291    pub fn add_module_with_dylib(
1292        &self,
1293        tsm: ThreadSafeModule,
1294        jd: JITDylibRef,
1295    ) -> Result<(), LLVMString> {
1296        let tsm = mem::ManuallyDrop::new(tsm);
1297        cvt(unsafe { LLVMOrcLLJITAddLLVMIRModule(self.as_inner(), jd.as_inner(), tsm.as_inner()) })
1298    }
1299
1300    /// Add an IR module to the given ResourceTracker's JITDylib.
1301    pub fn add_module_with_rt(
1302        &self,
1303        tsm: ThreadSafeModule,
1304        jd: ResourceTracker,
1305    ) -> Result<(), LLVMString> {
1306        let tsm = mem::ManuallyDrop::new(tsm);
1307        cvt(unsafe {
1308            LLVMOrcLLJITAddLLVMIRModuleWithRT(self.as_inner(), jd.as_inner(), tsm.as_inner())
1309        })
1310    }
1311
1312    /// Gets the execution session.
1313    pub fn get_execution_session(&self) -> ExecutionSessionRef<'_> {
1314        unsafe { ExecutionSessionRef::from_inner(LLVMOrcLLJITGetExecutionSession(self.as_inner())) }
1315    }
1316
1317    /// Return a reference to the Main JITDylib.
1318    pub fn get_main_jit_dylib(&self) -> JITDylibRef {
1319        unsafe { JITDylibRef::from_inner_unchecked(LLVMOrcLLJITGetMainJITDylib(self.as_inner())) }
1320    }
1321
1322    /// Mangles the given string according to the LLJIT instance's DataLayout, then interns the
1323    /// result in the SymbolStringPool and returns a reference to the pool entry.
1324    pub fn mangle_and_intern(&self, unmangled_name: &CStr) -> SymbolStringPoolEntry {
1325        unsafe {
1326            SymbolStringPoolEntry::from_inner_unchecked(LLVMOrcLLJITMangleAndIntern(
1327                self.as_inner(),
1328                unmangled_name.as_ptr(),
1329            ))
1330        }
1331    }
1332
1333    /// Look up the given symbol in the main JITDylib of the given LLJIT instance.
1334    pub fn lookup(&self, name: &CStr) -> Result<usize, LLVMString> {
1335        self.lookup_unmangled(&self.mangle_and_intern(name))
1336    }
1337
1338    /// Look up the given symbol in the main JITDylib of the given LLJIT instance.
1339    ///
1340    /// The name should be mangled.
1341    pub fn lookup_unmangled(&self, unmangled_name: &CStr) -> Result<usize, LLVMString> {
1342        let mut res = MaybeUninit::uninit();
1343        cvt(unsafe {
1344            LLVMOrcLLJITLookup(self.as_inner(), res.as_mut_ptr(), unmangled_name.as_ptr())
1345        })?;
1346        Ok(unsafe { res.assume_init() }.try_into().unwrap())
1347    }
1348
1349    /// Returns a non-owning reference to the LLJIT instance's IR transform layer.
1350    pub fn get_ir_transform_layer(&self) -> IRTransformLayerRef {
1351        unsafe { IRTransformLayerRef::from_inner(LLVMOrcLLJITGetIRTransformLayer(self.as_inner())) }
1352    }
1353
1354    // get_*_layer...
1355
1356    // Experimental interface for `libLLVMOrcDebugging.a`.
1357    /*
1358    /// Install the plugin that submits debug objects to the executor.
1359    /// Executors must expose the llvm_orc_registerJITLoaderGDBWrapper symbol.
1360    pub fn enable_debug_support(&self) -> Result<(), LLVMString> {
1361        cvt(unsafe { LLVMOrcLLJITEnableDebugSupport(self.as_inner()) })
1362    }
1363    */
1364}
1365
1366impl Drop for LLJIT {
1367    fn drop(&mut self) {
1368        if let Err(e) = cvt(unsafe { LLVMOrcDisposeLLJIT(self.jit) }) {
1369            error!("Failed to dispose JIT: {e}");
1370        }
1371    }
1372}
1373
1374/*
1375pub struct ObjectLayerRef {
1376    ptr: LLVMOrcObjectLayerRef,
1377}
1378
1379impl ObjectLayerRef {
1380    /// Wraps a raw pointer.
1381    pub unsafe fn from_inner(ptr: LLVMOrcObjectLayerRef) -> Self {
1382        Self { ptr }
1383    }
1384
1385    /// Unwraps the raw pointer.
1386    pub fn as_inner(&self) -> LLVMOrcObjectLayerRef {
1387        self.ptr
1388    }
1389}
1390
1391pub struct ObjectTransformLayerRef {
1392    ptr: LLVMOrcObjectTransformLayerRef,
1393}
1394
1395impl ObjectTransformLayerRef {
1396    /// Wraps a raw pointer.
1397    pub unsafe fn from_inner(ptr: LLVMOrcObjectTransformLayerRef) -> Self {
1398        Self { ptr }
1399    }
1400
1401    /// Unwraps the raw pointer.
1402    pub fn as_inner(&self) -> LLVMOrcObjectTransformLayerRef {
1403        self.ptr
1404    }
1405}
1406*/
1407
1408/// A reference to an IR transform layer.
1409pub struct IRTransformLayerRef {
1410    ptr: LLVMOrcIRTransformLayerRef,
1411}
1412
1413impl IRTransformLayerRef {
1414    /// Wraps a raw pointer.
1415    pub unsafe fn from_inner(ptr: LLVMOrcIRTransformLayerRef) -> Self {
1416        Self { ptr }
1417    }
1418
1419    /// Unwraps the raw pointer.
1420    pub fn as_inner(&self) -> LLVMOrcIRTransformLayerRef {
1421        self.ptr
1422    }
1423
1424    /// Emit should materialize the given IR.
1425    pub fn emit(&self, mr: MaterializationResponsibility, tsm: ThreadSafeModule) {
1426        let mr = mem::ManuallyDrop::new(mr);
1427        let tsm = mem::ManuallyDrop::new(tsm);
1428        unsafe { LLVMOrcIRTransformLayerEmit(self.as_inner(), mr.as_inner(), tsm.as_inner()) };
1429    }
1430
1431    /// Set the transform function of this transform layer.
1432    pub fn set_transform(&self, f: fn(&ThreadSafeModule) -> Result<(), String>) {
1433        extern "C" fn shim(
1434            ctx: *mut c_void,
1435            m: *mut LLVMOrcThreadSafeModuleRef,
1436            _mr: LLVMOrcMaterializationResponsibilityRef,
1437        ) -> LLVMErrorRef {
1438            let f = ctx as *mut fn(&ThreadSafeModule) -> Result<(), String>;
1439            let m = mem::ManuallyDrop::new(unsafe { ThreadSafeModule::from_inner(*m) });
1440            let res = std::panic::catch_unwind(AssertUnwindSafe(|| unsafe { (*f)(&m) }));
1441            cvt_cb_res(res)
1442        }
1443
1444        let ctx = f as *mut c_void;
1445        unsafe { LLVMOrcIRTransformLayerSetTransform(self.as_inner(), shim, ctx) };
1446    }
1447}
1448
1449/// Converts an `LLVMErrorRef` to a `Result`.
1450fn cvt(ptr: LLVMErrorRef) -> Result<(), LLVMString> {
1451    if ptr.is_null() {
1452        Ok(())
1453    } else {
1454        Err(unsafe { llvm_string(LLVMGetErrorMessage(ptr)) })
1455    }
1456}
1457
1458fn cvt_cb_res(res: Result<Result<(), String>, Box<dyn std::any::Any + Send>>) -> LLVMErrorRef {
1459    let msg = match res {
1460        Ok(Ok(())) => return ptr::null_mut(), // LLVMErrorSuccess
1461        Ok(Err(e)) => e,
1462        Err(e) => format!("callback panicked, payload: {:?}", panic_payload(&e)),
1463    };
1464    unsafe { LLVMCreateStringError(CString::new(msg).unwrap_or_default().as_ptr()) }
1465}
1466
1467fn panic_payload(any: &dyn std::any::Any) -> Option<&str> {
1468    if let Some(s) = any.downcast_ref::<&str>() {
1469        Some(*s)
1470    } else if let Some(s) = any.downcast_ref::<String>() {
1471        Some(s.as_str())
1472    } else {
1473        None
1474    }
1475}
1476
1477/// Deallocates the vector without running the elements' destructors.
1478// Comment from LLVMOrcAbsoluteSymbols:
1479/*
1480 * This function takes ownership of the elements of the Syms array. The Name
1481 * fields of the array elements are taken to have been retained for this
1482 * function. This allows the following pattern...
1483 *
1484 *   size_t NumPairs;
1485 *   LLVMOrcCSymbolMapPairs Sym;
1486 *   -- Build Syms array --
1487 *   LLVMOrcMaterializationUnitRef MU =
1488 *       LLVMOrcAbsoluteSymbols(Syms, NumPairs);
1489 *
1490 * ... without requiring cleanup of the elements of the Sym array afterwards.
1491 *
1492 * The client is still responsible for deleting the Sym array itself.
1493 *
1494 * If a client wishes to reuse elements of the Sym array after this call they
1495 * must explicitly retain each of the elements for themselves.
1496 */
1497struct ManuallyDropElements<T> {
1498    vec: Vec<T>,
1499}
1500
1501impl<T> ManuallyDropElements<T> {
1502    #[inline(always)]
1503    fn new(vec: Vec<T>) -> Self {
1504        Self { vec }
1505    }
1506}
1507
1508impl<T> std::ops::Deref for ManuallyDropElements<T> {
1509    type Target = Vec<T>;
1510
1511    #[inline(always)]
1512    fn deref(&self) -> &Vec<T> {
1513        &self.vec
1514    }
1515}
1516
1517impl<T> std::ops::DerefMut for ManuallyDropElements<T> {
1518    #[inline(always)]
1519    fn deref_mut(&mut self) -> &mut Vec<T> {
1520        &mut self.vec
1521    }
1522}
1523
1524impl<T> Drop for ManuallyDropElements<T> {
1525    #[inline(always)]
1526    fn drop(&mut self) {
1527        unsafe { self.vec.set_len(0) };
1528    }
1529}
1530
1531#[cfg(test)]
1532mod tests {
1533    use super::*;
1534    use inkwell::{passes::PassBuilderOptions, targets::Target};
1535
1536    #[test]
1537    #[ignore = "ci fails idk"]
1538    fn e2e() {
1539        let tsm = ThreadSafeModule::create("test");
1540        let fn_name = "my_fn";
1541        tsm.with_module(|m| {
1542            let cx = m.get_context();
1543            let bcx = cx.create_builder();
1544            let ty = cx.i64_type().fn_type(&[], false);
1545
1546            let f = m.add_function(fn_name, ty, Some(inkwell::module::Linkage::External));
1547            let bb = cx.append_basic_block(f, "entry");
1548            bcx.position_at_end(bb);
1549            bcx.build_int_compare(
1550                inkwell::IntPredicate::EQ,
1551                cx.i64_type().const_zero(),
1552                cx.i64_type().const_all_ones(),
1553                "a",
1554            )
1555            .unwrap();
1556            bcx.build_return(Some(&cx.i64_type().const_int(69, false))).unwrap();
1557
1558            eprintln!("--before--");
1559            eprintln!("{}", m.print_to_string().to_string_lossy());
1560
1561            m.verify().map_err(|e| e.to_string())?;
1562
1563            Target::initialize_native(&Default::default()).unwrap();
1564            let triple = TargetMachine::get_default_triple();
1565            let cpu = TargetMachine::get_host_cpu_name();
1566            let features = TargetMachine::get_host_cpu_features();
1567            let target = Target::from_triple(&triple).map_err(|e| e.to_string())?;
1568            let machine = target
1569                .create_target_machine(
1570                    &triple,
1571                    &cpu.to_string_lossy(),
1572                    &features.to_string_lossy(),
1573                    Default::default(),
1574                    inkwell::targets::RelocMode::Default,
1575                    inkwell::targets::CodeModel::Default,
1576                )
1577                .ok_or_else(|| String::from("failed to create target machine"))?;
1578
1579            m.run_passes("default<O3>", &machine, PassBuilderOptions::create()).unwrap();
1580
1581            eprintln!("--after--");
1582            eprintln!("{}", m.print_to_string().to_string_lossy());
1583
1584            Ok(())
1585        })
1586        .unwrap();
1587
1588        let jit = LLJIT::new_empty().unwrap();
1589        jit.add_module(tsm).unwrap();
1590        let address =
1591            jit.lookup_unmangled(&jit.mangle_and_intern(&CString::new(fn_name).unwrap())).unwrap();
1592        eprintln!("address: {address:#x}");
1593        let f = unsafe { std::mem::transmute::<usize, extern "C" fn() -> u64>(address) };
1594        let r = f();
1595        assert_eq!(r, 69);
1596    }
1597}