Skip to main content

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