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,
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 fmt::Debug for ThreadSafeContext {
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        f.debug_struct("ThreadSafeContext").finish_non_exhaustive()
56    }
57}
58
59impl ThreadSafeContext {
60    /// Creates a new thread-safe context.
61    pub fn new() -> Self {
62        unsafe { Self::from_inner(LLVMOrcCreateNewThreadSafeContext()) }
63    }
64
65    /// Creates a thread-safe context from an existing LLVM context.
66    pub fn from_context(ctx: Context) -> Self {
67        let ctx = mem::ManuallyDrop::new(ctx);
68        unsafe { Self::from_inner(LLVMOrcCreateNewThreadSafeContextFromLLVMContext(ctx.raw())) }
69    }
70
71    /// Wraps a raw pointer.
72    pub unsafe fn from_inner(ctx: LLVMOrcThreadSafeContextRef) -> Self {
73        Self { ctx }
74    }
75
76    /// Unwraps the raw pointer.
77    pub fn as_inner(&self) -> LLVMOrcThreadSafeContextRef {
78        self.ctx
79    }
80
81    /// Create a ThreadSafeModule wrapper around the given LLVM module.
82    pub fn create_module<'ctx>(&'ctx self, module: Module<'ctx>) -> ThreadSafeModule {
83        ThreadSafeModule::create_in_context(module, self)
84    }
85}
86
87impl Drop for ThreadSafeContext {
88    fn drop(&mut self) {
89        unsafe { LLVMOrcDisposeThreadSafeContext(self.ctx) };
90    }
91}
92
93/// A thread-safe module.
94///
95/// See [the ORCv2 docs](https://releases.llvm.org/17.0.1/docs/ORCv2.html).
96// NOTE: A lifetime is not needed according to `LLVMOrcCreateNewThreadSafeContext`
97// > Ownership of the underlying ThreadSafeContext data is shared: Clients can and should dispose of
98// > their ThreadSafeContext as soon as they no longer need to refer to it directly. Other
99// > references (e.g. from ThreadSafeModules) will keep the data alive as long as it is needed.
100pub struct ThreadSafeModule {
101    ptr: LLVMOrcThreadSafeModuleRef,
102}
103
104impl ThreadSafeModule {
105    /// Creates a new module with the given name in a new context.
106    ///
107    /// Use [`Self::with_module`] to access and modify the module.
108    pub fn create(name: &str) -> Self {
109        let name_cstr = CString::new(name).unwrap();
110        unsafe {
111            let ctx = LLVMContextCreate();
112            let module = LLVMModuleCreateWithNameInContext(name_cstr.as_ptr(), ctx);
113            let tsc = LLVMOrcCreateNewThreadSafeContextFromLLVMContext(ctx);
114            let ptr = LLVMOrcCreateNewThreadSafeModule(module, tsc);
115            LLVMOrcDisposeThreadSafeContext(tsc);
116            Self { ptr }
117        }
118    }
119
120    /// Create a ThreadSafeModule wrapper around the given LLVM module.
121    pub fn create_in_context<'ctx>(module: Module<'ctx>, ctx: &'ctx ThreadSafeContext) -> Self {
122        let module = mem::ManuallyDrop::new(module);
123        let ptr = unsafe { LLVMOrcCreateNewThreadSafeModule(module.as_mut_ptr(), ctx.as_inner()) };
124        Self { ptr }
125    }
126
127    /// Wraps a raw pointer.
128    pub unsafe fn from_inner(ptr: LLVMOrcThreadSafeModuleRef) -> Self {
129        Self { ptr }
130    }
131
132    /// Unwraps the raw pointer.
133    pub fn as_inner(&self) -> LLVMOrcThreadSafeModuleRef {
134        self.ptr
135    }
136
137    /// Runs the given closure with the module.
138    ///
139    /// This implicitly locks the associated context.
140    pub fn with_module<'tsm>(
141        &'tsm self,
142        mut f: impl FnMut(&Module<'tsm>) -> Result<(), String>,
143    ) -> Result<(), LLVMString> {
144        extern "C" fn shim(ctx: *mut c_void, m: LLVMModuleRef) -> LLVMErrorRef {
145            let f = ctx.cast::<&mut dyn FnMut(&Module<'_>) -> Result<(), String>>();
146            let m = mem::ManuallyDrop::new(unsafe { Module::new(m) });
147            let res = std::panic::catch_unwind(AssertUnwindSafe(|| unsafe { (*f)(&m) }));
148            cvt_cb_res(res)
149        }
150
151        let mut f = &mut f as &mut dyn FnMut(&Module<'tsm>) -> Result<(), String>;
152        let ctx = &mut f as *mut _ as *mut c_void;
153        cvt(unsafe { LLVMOrcThreadSafeModuleWithModuleDo(self.as_inner(), shim, ctx) })
154    }
155}
156
157impl Drop for ThreadSafeModule {
158    fn drop(&mut self) {
159        unsafe { LLVMOrcDisposeThreadSafeModule(self.ptr) };
160    }
161}
162
163/// A symbol string pool reference.
164#[repr(C)]
165pub struct SymbolStringPoolRef {
166    ptr: LLVMOrcSymbolStringPoolRef,
167}
168
169impl SymbolStringPoolRef {
170    /// Wraps a raw pointer.
171    pub unsafe fn from_inner(ptr: LLVMOrcSymbolStringPoolRef) -> Self {
172        Self { ptr }
173    }
174
175    /// Unwraps the raw pointer.
176    pub fn as_inner(&self) -> LLVMOrcSymbolStringPoolRef {
177        self.ptr
178    }
179
180    /// Clear all unreferenced symbol string pool entries.
181    ///
182    /// This can be called at any time to release unused entries in the
183    /// ExecutionSession's string pool. Since it locks the pool (preventing
184    /// interning of any new strings) it is recommended that it only be called
185    /// infrequently, ideally when the caller has reason to believe that some
186    /// entries will have become unreferenced, e.g. after removing a module or
187    /// closing a JITDylib.
188    pub fn clear_dead_entries(&self) {
189        unsafe { LLVMOrcSymbolStringPoolClearDeadEntries(self.as_inner()) };
190    }
191}
192
193/// A reference-counted unique string interned in a `SymbolStringPool`.
194#[derive(PartialEq, Eq, Hash)]
195#[repr(C)]
196pub struct SymbolStringPoolEntry {
197    ptr: NonNull<LLVMOrcOpaqueSymbolStringPoolEntry>,
198}
199
200impl Clone for SymbolStringPoolEntry {
201    fn clone(&self) -> Self {
202        unsafe { LLVMOrcRetainSymbolStringPoolEntry(self.as_inner()) };
203        Self { ..*self }
204    }
205}
206
207impl fmt::Debug for SymbolStringPoolEntry {
208    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209        self.as_cstr().fmt(f)
210    }
211}
212
213impl std::ops::Deref for SymbolStringPoolEntry {
214    type Target = CStr;
215
216    fn deref(&self) -> &Self::Target {
217        self.as_cstr()
218    }
219}
220
221impl SymbolStringPoolEntry {
222    /// Wraps a raw pointer.
223    pub unsafe fn from_inner(ptr: LLVMOrcSymbolStringPoolEntryRef) -> Option<Self> {
224        NonNull::new(ptr).map(|ptr| Self { ptr })
225    }
226
227    /// Wraps a raw pointer. Must not be null.
228    pub unsafe fn from_inner_unchecked(ptr: LLVMOrcSymbolStringPoolEntryRef) -> Self {
229        Self { ptr: NonNull::new_unchecked(ptr) }
230    }
231
232    /// Unwraps the raw pointer.
233    pub fn as_inner(&self) -> LLVMOrcSymbolStringPoolEntryRef {
234        self.ptr.as_ptr()
235    }
236
237    /// Convert to a C string.
238    pub fn as_cstr(&self) -> &CStr {
239        unsafe { CStr::from_ptr(LLVMOrcSymbolStringPoolEntryStr(self.as_inner())) }
240    }
241}
242
243impl Drop for SymbolStringPoolEntry {
244    fn drop(&mut self) {
245        unsafe { LLVMOrcReleaseSymbolStringPoolEntry(self.as_inner()) }
246    }
247}
248
249/// An evaluated symbol.
250#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
251#[repr(C)]
252pub struct EvaluatedSymbol {
253    /// The address of the symbol.
254    pub address: u64,
255    /// The flags of the symbol.
256    pub flags: SymbolFlags,
257}
258
259impl EvaluatedSymbol {
260    /// Create a new EvaluatedSymbol from the given address and flags.
261    pub fn new(address: u64, flags: SymbolFlags) -> Self {
262        Self { address, flags }
263    }
264
265    /// Create a new EvaluatedSymbol from the given flags.
266    pub fn from_flags(flags: SymbolFlags) -> Self {
267        Self { address: 0, flags }
268    }
269
270    /// Create a new EvaluatedSymbol from the given address.
271    pub fn from_address(address: usize) -> Self {
272        Self { address: address as u64, flags: SymbolFlags::none() }
273    }
274}
275
276/// Symbol flags.
277#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
278#[repr(C)]
279pub struct SymbolFlags {
280    /// The generic flags.
281    pub generic: u8,
282    /// The target flags.
283    pub target: u8,
284}
285
286impl Default for SymbolFlags {
287    fn default() -> Self {
288        Self::none()
289    }
290}
291
292impl SymbolFlags {
293    /// Create a new, empty SymbolFlags.
294    pub fn none() -> Self {
295        Self { generic: LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsNone as u8, target: 0 }
296    }
297
298    /// Set the `Exported` flag.
299    pub fn set_exported(&mut self) {
300        self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsExported as u8;
301    }
302
303    /// Set the `Exported` flag.
304    pub fn exported(mut self) -> Self {
305        self.set_exported();
306        self
307    }
308
309    /// Returns `true` if the `Exported` flag is set.
310    pub fn is_exported(&self) -> bool {
311        (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsExported as u8) != 0
312    }
313
314    /// Set the `Weak` flag.
315    pub fn set_weak(&mut self) {
316        self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsWeak as u8;
317    }
318
319    /// Set the `Weak` flag.
320    pub fn weak(mut self) -> Self {
321        self.set_weak();
322        self
323    }
324
325    /// Returns `true` if the `Weak` flag is set.
326    pub fn is_weak(&self) -> bool {
327        (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsWeak as u8) != 0
328    }
329
330    /// Set the `Callable` flag.
331    pub fn set_callable(&mut self) {
332        self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsCallable as u8;
333    }
334
335    /// Set the `Callable` flag.
336    pub fn callable(mut self) -> Self {
337        self.set_callable();
338        self
339    }
340
341    /// Returns `true` if the `Callable` flag is set.
342    pub fn is_callable(&self) -> bool {
343        (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsCallable as u8) != 0
344    }
345
346    /// Set the `MaterializationSideEffectsOnly` flag.
347    pub fn set_materialization_side_effects_only(&mut self) {
348        self.generic |=
349            LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly
350                as u8;
351    }
352
353    /// Set the `MaterializationSideEffectsOnly` flag.
354    pub fn materialization_side_effects_only(mut self) -> Self {
355        self.set_materialization_side_effects_only();
356        self
357    }
358
359    /// Returns `true` if the `MaterializationSideEffectsOnly` flag is set.
360    pub fn is_materialization_side_effects_only(&self) -> bool {
361        (self.generic
362            & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly
363                as u8)
364            != 0
365    }
366
367    /// Add a generic flag.
368    pub fn set_generic(&mut self, flag: LLVMJITSymbolGenericFlags) {
369        self.generic |= flag as u8;
370    }
371
372    /// Add a generic flag.
373    pub fn with_generic(mut self, flag: LLVMJITSymbolGenericFlags) -> Self {
374        self.set_generic(flag);
375        self
376    }
377
378    /// Add a target flag.
379    pub fn set_target(&mut self, flag: LLVMJITSymbolTargetFlags) {
380        self.target |= flag;
381    }
382
383    /// Add a target flag.
384    pub fn with_target(mut self, flag: LLVMJITSymbolTargetFlags) -> Self {
385        self.set_target(flag);
386        self
387    }
388}
389
390/// A pair of a symbol name and flags.
391#[derive(Clone, Debug, PartialEq, Eq, Hash)]
392#[repr(C)]
393pub struct SymbolFlagsMapPair {
394    /// The symbol name.
395    pub name: SymbolStringPoolEntry,
396    /// The symbol flags.
397    pub flags: SymbolFlags,
398}
399
400impl SymbolFlagsMapPair {
401    /// Create a new pair.
402    pub fn new(name: SymbolStringPoolEntry, flags: SymbolFlags) -> Self {
403        Self { name, flags }
404    }
405}
406
407/// A pair of a symbol name and an evaluated symbol.
408#[derive(Clone, Debug, PartialEq, Eq, Hash)]
409#[repr(C)]
410pub struct SymbolMapPair {
411    /// The symbol name.
412    pub name: SymbolStringPoolEntry,
413    /// The evaluated symbol.
414    pub evaluated_symbol: EvaluatedSymbol,
415}
416
417impl SymbolMapPair {
418    /// Create a new pair.
419    pub fn new(name: SymbolStringPoolEntry, evaluated_symbol: EvaluatedSymbol) -> Self {
420        Self { name, evaluated_symbol }
421    }
422}
423
424/// An owned list of symbol flags map pairs.
425///
426/// Returned by [`MaterializationResponsibilityRef::get_symbols`].
427pub struct SymbolFlagsMapPairs<'a>(&'a [SymbolFlagsMapPair]);
428
429impl<'a> SymbolFlagsMapPairs<'a> {
430    /// Returns the slice of pairs.
431    pub fn as_slice(&self) -> &'a [SymbolFlagsMapPair] {
432        self.0
433    }
434}
435
436impl std::ops::Deref for SymbolFlagsMapPairs<'_> {
437    type Target = [SymbolFlagsMapPair];
438
439    fn deref(&self) -> &Self::Target {
440        self.0
441    }
442}
443
444impl Drop for SymbolFlagsMapPairs<'_> {
445    fn drop(&mut self) {
446        unsafe { LLVMOrcDisposeCSymbolFlagsMap(self.0.as_ptr().cast_mut().cast()) };
447    }
448}
449
450/// A materialization unit.
451pub struct MaterializationUnit {
452    mu: LLVMOrcMaterializationUnitRef,
453}
454
455impl fmt::Debug for MaterializationUnit {
456    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
457        f.debug_struct("MaterializationUnit").finish_non_exhaustive()
458    }
459}
460
461impl MaterializationUnit {
462    /// Create a custom MaterializationUnit.
463    pub fn new_custom(
464        name: &CStr,
465        syms: Vec<SymbolFlagsMapPair>,
466        init_sym: Option<SymbolStringPoolEntry>,
467        mu: Box<dyn CustomMaterializationUnit>,
468    ) -> Self {
469        extern "C" fn materialize(ctx: *mut c_void, mr: LLVMOrcMaterializationResponsibilityRef) {
470            // Ownership of the Ctx and MR arguments passes to the callback which must adhere to the
471            // LLVMOrcMaterializationResponsibilityRef contract (see comment for that type).
472            //
473            // If this callback is called then the LLVMOrcMaterializationUnitDestroy callback will
474            // NOT be called.
475            let ctx = unsafe { Box::from_raw(ctx.cast::<Box<dyn CustomMaterializationUnit>>()) };
476            let mr = unsafe { MaterializationResponsibility::from_inner(mr) };
477            let res = std::panic::catch_unwind(AssertUnwindSafe(move || ctx.materialize(mr)));
478            if let Err(e) = res {
479                error!(msg=?panic_payload(&e), "materialize callback panicked");
480            }
481        }
482
483        extern "C" fn discard(
484            ctx: *mut c_void,
485            jd: LLVMOrcJITDylibRef,
486            symbol: LLVMOrcSymbolStringPoolEntryRef,
487        ) {
488            // Ownership of JD and Symbol remain with the caller:
489            // these arguments should not be disposed of or released.
490            let ctx = unsafe { &mut **ctx.cast::<Box<dyn CustomMaterializationUnit>>() };
491            let jd = unsafe { JITDylibRef::from_inner_unchecked(jd) };
492            let symbol = mem::ManuallyDrop::new(unsafe {
493                SymbolStringPoolEntry::from_inner_unchecked(symbol)
494            });
495            let res = std::panic::catch_unwind(AssertUnwindSafe(|| ctx.discard(jd, &symbol)));
496            if let Err(e) = res {
497                error!(msg=?panic_payload(&e), "discard callback panicked");
498            }
499        }
500
501        extern "C" fn destroy(ctx: *mut c_void) {
502            // If a custom MaterializationUnit is destroyed before its Materialize function is
503            // called then this function will be called to provide an opportunity for the underlying
504            // program representation to be destroyed.
505            let ctx = unsafe { Box::from_raw(ctx.cast::<Box<dyn CustomMaterializationUnit>>()) };
506            let res = std::panic::catch_unwind(AssertUnwindSafe(|| drop(ctx)));
507            if let Err(e) = res {
508                error!(msg=?panic_payload(&e), "destroy callback panicked");
509            }
510        }
511
512        let ctx = Box::into_raw(Box::new(mu)).cast();
513        let init_sym = if let Some(init_sym) = init_sym {
514            mem::ManuallyDrop::new(init_sym).as_inner()
515        } else {
516            ptr::null_mut()
517        };
518        let syms = ManuallyDropElements::new(syms);
519        unsafe {
520            Self::new_custom_raw(
521                name,
522                ctx,
523                syms.as_ptr().cast_mut().cast(),
524                syms.len(),
525                init_sym,
526                materialize,
527                discard,
528                destroy,
529            )
530        }
531    }
532
533    /// Create a custom MaterializationUnit.
534    ///
535    /// See [`Self::new_custom`].
536    pub unsafe fn new_custom_raw(
537        name: &CStr,
538        ctx: *mut c_void,
539        syms: LLVMOrcCSymbolFlagsMapPairs,
540        num_syms: usize,
541        init_sym: LLVMOrcSymbolStringPoolEntryRef,
542        materialize: LLVMOrcMaterializationUnitMaterializeFunction,
543        discard: LLVMOrcMaterializationUnitDiscardFunction,
544        destroy: LLVMOrcMaterializationUnitDestroyFunction,
545    ) -> Self {
546        Self::from_inner(LLVMOrcCreateCustomMaterializationUnit(
547            name.as_ptr(),
548            ctx,
549            syms,
550            num_syms,
551            init_sym,
552            materialize,
553            discard,
554            destroy,
555        ))
556    }
557
558    /// Create a MaterializationUnit to define the given symbols as pointing to the corresponding
559    /// raw addresses.
560    pub fn absolute_symbols(syms: Vec<SymbolMapPair>) -> Self {
561        let syms = ManuallyDropElements::new(syms);
562        unsafe { Self::absolute_symbols_raw(syms.as_ptr().cast_mut().cast(), syms.len()) }
563    }
564
565    /// Create a MaterializationUnit to define the given symbols as pointing to the corresponding
566    /// raw addresses.
567    ///
568    /// See [`Self::absolute_symbols`].
569    pub unsafe fn absolute_symbols_raw(syms: LLVMOrcCSymbolMapPairs, len: usize) -> Self {
570        unsafe { Self::from_inner(LLVMOrcAbsoluteSymbols(syms, len)) }
571    }
572
573    // TODO: fn lazy_reexports
574
575    /// Wraps a raw pointer.
576    pub unsafe fn from_inner(mu: LLVMOrcMaterializationUnitRef) -> Self {
577        Self { mu }
578    }
579
580    /// Unwraps the raw pointer.
581    pub fn as_inner(&self) -> LLVMOrcMaterializationUnitRef {
582        self.mu
583    }
584}
585
586impl Drop for MaterializationUnit {
587    fn drop(&mut self) {
588        unsafe { LLVMOrcDisposeMaterializationUnit(self.as_inner()) };
589    }
590}
591
592/// A custom materialization unit.
593///
594/// Use with [`MaterializationUnit::new_custom`].
595pub trait CustomMaterializationUnit {
596    /// Materialize callback.
597    fn materialize(self: Box<Self>, mr: MaterializationResponsibility);
598
599    /// Discard callback.
600    fn discard(&mut self, jd: JITDylibRef, symbol: &SymbolStringPoolEntry);
601
602    // fn destroy is Drop
603}
604
605/// An owned materialization responsibility.
606pub struct MaterializationResponsibility {
607    mr: LLVMOrcMaterializationResponsibilityRef,
608}
609
610impl MaterializationResponsibility {
611    /// Wraps a raw pointer.
612    pub unsafe fn from_inner(mr: LLVMOrcMaterializationResponsibilityRef) -> Self {
613        Self { mr }
614    }
615
616    /// Unwraps the raw pointer.
617    pub fn as_inner(&self) -> LLVMOrcMaterializationResponsibilityRef {
618        self.mr
619    }
620
621    /// Returns a reference to the MaterializationResponsibility.
622    #[inline]
623    pub fn as_ref(&self) -> MaterializationResponsibilityRef<'_> {
624        unsafe { MaterializationResponsibilityRef::from_inner(self.as_inner()) }
625    }
626}
627
628impl Drop for MaterializationResponsibility {
629    fn drop(&mut self) {
630        unsafe { LLVMOrcDisposeMaterializationResponsibility(self.as_inner()) };
631    }
632}
633
634/// A reference to a materialization responsibility.
635pub struct MaterializationResponsibilityRef<'mr> {
636    mr: LLVMOrcMaterializationResponsibilityRef,
637    _marker: PhantomData<&'mr ()>,
638}
639
640impl<'mr> MaterializationResponsibilityRef<'mr> {
641    /// Wraps a raw pointer.
642    pub unsafe fn from_inner(mr: LLVMOrcMaterializationResponsibilityRef) -> Self {
643        Self { mr, _marker: PhantomData }
644    }
645
646    /// Unwraps the raw pointer.
647    pub fn as_inner(&self) -> LLVMOrcMaterializationResponsibilityRef {
648        self.mr
649    }
650
651    /// Returns the target JITDylib that these symbols are being materialized into.
652    pub fn get_target_dylib(&self) -> JITDylibRef {
653        unsafe {
654            JITDylibRef::from_inner_unchecked(LLVMOrcMaterializationResponsibilityGetTargetDylib(
655                self.as_inner(),
656            ))
657        }
658    }
659
660    /// Returns the ExecutionSession for this MaterializationResponsibility.
661    pub fn get_execution_session(&self) -> ExecutionSessionRef<'mr> {
662        unsafe {
663            ExecutionSessionRef::from_inner(
664                LLVMOrcMaterializationResponsibilityGetExecutionSession(self.as_inner()),
665            )
666        }
667    }
668
669    /// Returns the symbol flags map for this responsibility instance.
670    pub fn get_symbols(&self) -> SymbolFlagsMapPairs<'mr> {
671        /*
672         * The length of the array is returned in NumPairs and the caller is responsible
673         * for the returned memory and needs to call LLVMOrcDisposeCSymbolFlagsMap.
674         *
675         * To use the returned symbols beyond the lifetime of the
676         * MaterializationResponsibility requires the caller to retain the symbols
677         * explicitly.
678         */
679        let mut len = MaybeUninit::uninit();
680        let data = unsafe {
681            LLVMOrcMaterializationResponsibilityGetSymbols(self.as_inner(), len.as_mut_ptr())
682        };
683        SymbolFlagsMapPairs(unsafe { std::slice::from_raw_parts(data.cast(), len.assume_init()) })
684    }
685
686    /// Returns the initialization pseudo-symbol, if any.
687    ///
688    /// This symbol will also be present in the SymbolFlagsMap for this
689    /// MaterializationResponsibility object.
690    pub fn get_initializer_symbol(&self) -> Option<SymbolStringPoolEntry> {
691        let ptr =
692            unsafe { LLVMOrcMaterializationResponsibilityGetInitializerSymbol(self.as_inner()) };
693        unsafe { SymbolStringPoolEntry::from_inner(ptr) }
694    }
695
696    /// Returns the names of any symbols covered by this MaterializationResponsibility object that
697    /// have queries pending.
698    ///
699    /// This information can be used to return responsibility for unrequested symbols back to the
700    /// JITDylib via the delegate method.
701    pub fn get_requested_symbols(&self) -> &[SymbolStringPoolEntry] {
702        let mut len = MaybeUninit::uninit();
703        let ptr = unsafe {
704            LLVMOrcMaterializationResponsibilityGetRequestedSymbols(
705                self.as_inner(),
706                len.as_mut_ptr(),
707            )
708        };
709        unsafe { std::slice::from_raw_parts(ptr.cast(), len.assume_init()) }
710    }
711
712    /// Notifies the target JITDylib that the given symbols have been resolved.
713    pub fn notify_resolved(&self, syms: &[SymbolFlagsMapPair]) -> Result<(), LLVMString> {
714        cvt(unsafe {
715            LLVMOrcMaterializationResponsibilityNotifyResolved(
716                self.as_inner(),
717                syms.as_ptr().cast_mut().cast(),
718                syms.len(),
719            )
720        })
721    }
722
723    /// Notifies the target JITDylib (and any pending queries on that JITDylib)
724    /// that all symbols covered by this MaterializationResponsibility instance
725    /// have been emitted.
726    ///
727    /// `symbol_dep_groups` specifies the symbol dependency groups for this materialization unit.
728    /// Pass an empty slice if there are no dependencies.
729    pub fn notify_emitted(
730        &self,
731        symbol_dep_groups: &mut [LLVMOrcCSymbolDependenceGroup],
732    ) -> Result<(), LLVMString> {
733        cvt(unsafe {
734            LLVMOrcMaterializationResponsibilityNotifyEmitted(
735                self.as_inner(),
736                symbol_dep_groups.as_mut_ptr(),
737                symbol_dep_groups.len(),
738            )
739        })
740    }
741
742    /// Notify all not-yet-emitted covered by this MaterializationResponsibility instance that an
743    /// error has occurred.
744    ///
745    /// This will remove all symbols covered by this MaterializationResponsibility from the target
746    /// JITDylib, and send an error to any queries waiting on these symbols.
747    pub fn fail_materialization(&self) {
748        unsafe { LLVMOrcMaterializationResponsibilityFailMaterialization(self.as_inner()) };
749    }
750
751    /// Transfers responsibility to the given MaterializationUnit for all symbols defined by that
752    /// MaterializationUnit.
753    ///
754    /// This allows materializers to break up work based on run-time information (e.g.
755    /// by introspecting which symbols have actually been looked up and
756    /// materializing only those).
757    pub fn replace(&self, mu: MaterializationUnit) -> Result<(), LLVMString> {
758        let mu = mem::ManuallyDrop::new(mu);
759        cvt(unsafe { LLVMOrcMaterializationResponsibilityReplace(self.as_inner(), mu.as_inner()) })
760    }
761
762    /// Delegates responsibility for the given symbols to the returned
763    /// materialization responsibility. Useful for breaking up work between
764    /// threads, or different kinds of materialization processes.
765    ///
766    /// The caller retains responsibility of the the passed
767    /// MaterializationResponsibility.
768    pub fn delegate(&self, syms: &[SymbolStringPoolEntry]) -> Result<Self, LLVMString> {
769        let mut res = MaybeUninit::uninit();
770        cvt(unsafe {
771            LLVMOrcMaterializationResponsibilityDelegate(
772                self.as_inner(),
773                syms.as_ptr().cast_mut().cast(),
774                syms.len(),
775                res.as_mut_ptr(),
776            )
777        })?;
778        Ok(unsafe { Self::from_inner(res.assume_init()) })
779    }
780}
781
782/// A resource tracker.
783///
784/// ResourceTrackers allow you to remove code.
785pub struct ResourceTracker {
786    rt: LLVMOrcResourceTrackerRef,
787}
788
789impl fmt::Debug for ResourceTracker {
790    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
791        f.debug_struct("ResourceTracker").finish_non_exhaustive()
792    }
793}
794
795impl ResourceTracker {
796    /// Wraps a raw pointer.
797    pub unsafe fn from_inner(rt: LLVMOrcResourceTrackerRef) -> Self {
798        Self { rt }
799    }
800
801    /// Unwraps the raw pointer.
802    pub fn as_inner(&self) -> LLVMOrcResourceTrackerRef {
803        self.rt
804    }
805
806    /// Remove all resources associated with this tracker.
807    pub fn remove(&self) -> Result<(), LLVMString> {
808        cvt(unsafe { LLVMOrcResourceTrackerRemove(self.as_inner()) })
809    }
810
811    /// Transfers tracking of all resources associated with this resource tracker to the given
812    /// resource tracker.
813    pub fn transfer_to(&self, rt: &Self) {
814        unsafe { LLVMOrcResourceTrackerTransferTo(self.as_inner(), rt.as_inner()) };
815    }
816}
817
818impl Drop for ResourceTracker {
819    fn drop(&mut self) {
820        unsafe { LLVMOrcReleaseResourceTracker(self.as_inner()) };
821    }
822}
823
824/// A JIT execution session reference.
825///
826/// Returned by [`LLJIT::get_execution_session`] and
827/// [`MaterializationResponsibilityRef::get_execution_session`].
828///
829/// ExecutionSession represents the JIT'd program and provides context for the JIT: It contains the
830/// JITDylibs, error reporting mechanisms, and dispatches the materializers.
831///
832/// See [the ORCv2 docs](https://releases.llvm.org/17.0.1/docs/ORCv2.html).
833pub struct ExecutionSessionRef<'ee> {
834    es: LLVMOrcExecutionSessionRef,
835    _marker: PhantomData<&'ee ()>,
836}
837
838impl ExecutionSessionRef<'_> {
839    /// Wraps a raw pointer.
840    pub unsafe fn from_inner(es: LLVMOrcExecutionSessionRef) -> Self {
841        Self { es, _marker: PhantomData }
842    }
843
844    /// Unwraps the raw pointer.
845    pub fn as_inner(&self) -> LLVMOrcExecutionSessionRef {
846        self.es
847    }
848
849    /// Returns the SymbolStringPool for this ExecutionSession.
850    pub fn get_symbol_string_pool(&self) -> SymbolStringPoolRef {
851        unsafe {
852            SymbolStringPoolRef::from_inner(LLVMOrcExecutionSessionGetSymbolStringPool(
853                self.as_inner(),
854            ))
855        }
856    }
857
858    /// Intern a string in the ExecutionSession's SymbolStringPool and return a reference to it.
859    pub fn intern(&self, name: &CStr) -> SymbolStringPoolEntry {
860        unsafe {
861            SymbolStringPoolEntry::from_inner_unchecked(LLVMOrcExecutionSessionIntern(
862                self.as_inner(),
863                name.as_ptr(),
864            ))
865        }
866    }
867
868    /// Returns the JITDylib with the given name, if any.
869    pub fn get_dylib_by_name(&self, name: &CStr) -> Option<JITDylibRef> {
870        unsafe {
871            let dylib = LLVMOrcExecutionSessionGetJITDylibByName(self.as_inner(), name.as_ptr());
872            JITDylibRef::from_inner(dylib)
873        }
874    }
875
876    /// Create a "bare" JITDylib.
877    ///
878    /// The client is responsible for ensuring that the JITDylib's name is unique.
879    ///
880    /// This call does not install any library code or symbols into the newly created JITDylib. The
881    /// client is responsible for all configuration.
882    pub fn create_bare_jit_dylib(&self, name: &CStr) -> JITDylibRef {
883        debug_assert!(self.get_dylib_by_name(name).is_none());
884        unsafe {
885            JITDylibRef::from_inner_unchecked(LLVMOrcExecutionSessionCreateBareJITDylib(
886                self.as_inner(),
887                name.as_ptr(),
888            ))
889        }
890    }
891
892    /// Create a JITDylib.
893    ///
894    /// The client is responsible for ensuring that the JITDylib's name is unique.
895    ///
896    /// If a Platform is attached to the ExecutionSession then Platform::setupJITDylib will be
897    /// called to install standard platform symbols (e.g. standard library interposes). If no
898    /// Platform is installed then this call is equivalent to [Self::create_bare_jit_dylib] and will
899    /// always return success.
900    pub fn create_jit_dylib(&self, name: &CStr) -> Result<JITDylibRef, LLVMString> {
901        debug_assert!(self.get_dylib_by_name(name).is_none());
902        let mut res = MaybeUninit::uninit();
903        cvt(unsafe {
904            LLVMOrcExecutionSessionCreateJITDylib(self.as_inner(), res.as_mut_ptr(), name.as_ptr())
905        })?;
906        Ok(unsafe { JITDylibRef::from_inner_unchecked(res.assume_init()) })
907    }
908
909    /// Remove a JITDylib from the ExecutionSession, freeing all its resources once the last handle
910    /// is dropped.
911    pub fn remove_jit_dylib(&self, jd: JITDylibRef) -> Result<(), LLVMString> {
912        cvt(unsafe {
913            crate::cpp::revmc_llvm_execution_session_remove_jit_dylib(
914                self.as_inner(),
915                jd.as_inner(),
916            )
917        })
918    }
919
920    /// Sets the default error reporter to the ExecutionSession.
921    ///
922    /// Uses [`tracing::error!`] to log the error message.
923    pub fn set_default_error_reporter(&self) {
924        self.set_error_reporter(|msg| error!(msg = %msg.to_string_lossy(), "LLVM error"))
925    }
926
927    /// Attach a custom error reporter function to the ExecutionSession.
928    pub fn set_error_reporter(&self, f: fn(&CStr)) {
929        extern "C" fn shim(ctx: *mut c_void, err: LLVMErrorRef) {
930            let f: fn(&CStr) = unsafe { mem::transmute(ctx) };
931            let Err(e) = cvt(err) else { return };
932            let res = std::panic::catch_unwind(AssertUnwindSafe(|| f(&e)));
933            if let Err(e) = res {
934                error!(msg=?panic_payload(&e), "error reporter closure panicked");
935            }
936        }
937
938        let ctx = f as *mut c_void;
939        unsafe { LLVMOrcExecutionSessionSetErrorReporter(self.as_inner(), shim, ctx) };
940    }
941}
942
943/// A JIT dynamic library reference.
944///
945/// JITDylibs provide the symbol tables.
946#[derive(Clone, Copy)]
947pub struct JITDylibRef {
948    dylib: NonNull<LLVMOrcOpaqueJITDylib>,
949}
950
951impl JITDylibRef {
952    /// Wraps a raw pointer.
953    pub unsafe fn from_inner(dylib: LLVMOrcJITDylibRef) -> Option<Self> {
954        NonNull::new(dylib).map(|dylib| Self { dylib })
955    }
956
957    /// Wraps a raw pointer. Must not be null.
958    pub unsafe fn from_inner_unchecked(dylib: LLVMOrcJITDylibRef) -> Self {
959        Self { dylib: NonNull::new_unchecked(dylib) }
960    }
961
962    /// Unwraps the raw pointer.
963    pub fn as_inner(self) -> LLVMOrcJITDylibRef {
964        self.dylib.as_ptr()
965    }
966
967    /// Return a reference to a newly created resource tracker associated with JD.
968    pub fn create_resource_tracker(self) -> ResourceTracker {
969        unsafe {
970            ResourceTracker::from_inner(LLVMOrcJITDylibCreateResourceTracker(self.as_inner()))
971        }
972    }
973
974    /// Return a reference to the default resource tracker for the given JITDylib.
975    pub fn get_default_resource_tracker(self) -> ResourceTracker {
976        unsafe {
977            ResourceTracker::from_inner(LLVMOrcJITDylibGetDefaultResourceTracker(self.as_inner()))
978        }
979    }
980
981    /// Add the given MaterializationUnit to the given JITDylib.
982    pub fn define(self, mu: MaterializationUnit) -> Result<(), (LLVMString, MaterializationUnit)> {
983        // If this operation succeeds then JITDylib JD will take ownership of MU.
984        // If the operation fails then ownership remains with the caller who should call
985        // LLVMOrcDisposeMaterializationUnit to destroy it.
986        let mu = mem::ManuallyDrop::new(mu);
987        cvt(unsafe { LLVMOrcJITDylibDefine(self.as_inner(), mu.as_inner()) })
988            .map_err(|e| (e, mem::ManuallyDrop::into_inner(mu)))
989    }
990
991    /// Add another JITDylib to this JITDylib's link order.
992    ///
993    /// Symbols not found in this JITDylib will be searched for in `other`.
994    pub fn add_to_link_order(self, other: Self) {
995        unsafe {
996            crate::cpp::revmc_llvm_jit_dylib_add_to_link_order(self.as_inner(), other.as_inner())
997        };
998    }
999
1000    /// Calls remove on all trackers associated with this JITDylib.
1001    pub fn clear(self) -> Result<(), LLVMString> {
1002        cvt(unsafe { LLVMOrcJITDylibClear(self.as_inner()) })
1003    }
1004
1005    /// Add a DefinitionGenerator to the given JITDylib.
1006    pub fn add_generator(self, dg: DefinitionGenerator) {
1007        // The JITDylib will take ownership of the given generator:
1008        // the client is no longer responsible for managing its memory.
1009        let dg = mem::ManuallyDrop::new(dg);
1010        unsafe { LLVMOrcJITDylibAddGenerator(self.as_inner(), dg.as_inner()) };
1011    }
1012}
1013
1014/// Definition generator.
1015pub struct DefinitionGenerator {
1016    dg: LLVMOrcDefinitionGeneratorRef,
1017}
1018
1019impl DefinitionGenerator {
1020    /// Creates a generator that resolves symbols from the current process.
1021    pub fn for_current_process(global_prefix: c_char) -> Result<Self, LLVMString> {
1022        let mut generator = MaybeUninit::uninit();
1023        cvt(unsafe {
1024            LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(
1025                generator.as_mut_ptr(),
1026                global_prefix,
1027                None,
1028                ptr::null_mut(),
1029            )
1030        })?;
1031        Ok(unsafe { Self::from_inner(generator.assume_init()) })
1032    }
1033
1034    /// Creates a new custom DefinitionGenerator.
1035    pub fn new_custom(generator: Box<dyn CustomDefinitionGenerator>) -> Self {
1036        extern "C" fn try_to_generate(
1037            generator_obj: LLVMOrcDefinitionGeneratorRef,
1038            ctx: *mut c_void,
1039            lookup_state: *mut LLVMOrcLookupStateRef,
1040            kind: LLVMOrcLookupKind,
1041            jd: LLVMOrcJITDylibRef,
1042            jd_lookup_flags: LLVMOrcJITDylibLookupFlags,
1043            lookup_set: LLVMOrcCLookupSet,
1044            lookup_set_size: usize,
1045        ) -> LLVMErrorRef {
1046            let generator = unsafe { &mut **ctx.cast::<Box<dyn CustomDefinitionGenerator>>() };
1047            let lookup_state = unsafe { &mut *lookup_state };
1048            let jd = unsafe { JITDylibRef::from_inner_unchecked(jd) };
1049            let lookup_set = unsafe { std::slice::from_raw_parts(lookup_set, lookup_set_size) };
1050            let res = std::panic::catch_unwind(AssertUnwindSafe(|| {
1051                generator.try_to_generate(
1052                    generator_obj,
1053                    lookup_state,
1054                    kind,
1055                    jd,
1056                    jd_lookup_flags,
1057                    lookup_set,
1058                )
1059            }));
1060            cvt_cb_res(res)
1061        }
1062
1063        extern "C" fn dispose(ctx: *mut c_void) {
1064            let generator =
1065                unsafe { Box::from_raw(ctx.cast::<Box<dyn CustomDefinitionGenerator>>()) };
1066            let res = std::panic::catch_unwind(AssertUnwindSafe(|| drop(generator)));
1067            if let Err(e) = res {
1068                error!(msg=?panic_payload(&e), "dispose callback panicked");
1069            }
1070        }
1071
1072        let ctx = Box::into_raw(Box::new(generator)).cast();
1073        unsafe { Self::new_custom_raw(try_to_generate, ctx, dispose) }
1074    }
1075
1076    /// Creates a new custom DefinitionGenerator.
1077    ///
1078    /// See [`Self::new_custom`].
1079    pub unsafe fn new_custom_raw(
1080        f: LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction,
1081        ctx: *mut c_void,
1082        dispose: LLVMOrcDisposeCAPIDefinitionGeneratorFunction,
1083    ) -> Self {
1084        Self::from_inner(LLVMOrcCreateCustomCAPIDefinitionGenerator(f, ctx, dispose))
1085    }
1086
1087    /// Wraps a raw pointer.
1088    pub unsafe fn from_inner(dg: LLVMOrcDefinitionGeneratorRef) -> Self {
1089        Self { dg }
1090    }
1091
1092    /// Unwraps the raw pointer.
1093    pub fn as_inner(&self) -> LLVMOrcDefinitionGeneratorRef {
1094        self.dg
1095    }
1096}
1097
1098impl Drop for DefinitionGenerator {
1099    fn drop(&mut self) {
1100        unsafe { LLVMOrcDisposeDefinitionGenerator(self.as_inner()) };
1101    }
1102}
1103
1104/// A custom definition generator.
1105pub trait CustomDefinitionGenerator {
1106    /// A custom generator function.
1107    ///
1108    /// This can be used to create a custom generator object using
1109    /// LLVMOrcCreateCustomCAPIDefinitionGenerator. The resulting object can be attached to a
1110    /// JITDylib, via LLVMOrcJITDylibAddGenerator, to receive callbacks when lookups fail to match
1111    /// existing definitions.
1112    ///
1113    /// GeneratorObj will contain the address of the custom generator object.
1114    ///
1115    /// Ctx will contain the context object passed to LLVMOrcCreateCustomCAPIDefinitionGenerator.
1116    ///
1117    /// LookupState will contain a pointer to an LLVMOrcLookupStateRef object. This can optionally
1118    /// be modified to make the definition generation process asynchronous: If the LookupStateRef
1119    /// value is copied, and the original LLVMOrcLookupStateRef set to null, the lookup will be
1120    /// suspended. Once the asynchronous definition process has been completed clients must call
1121    /// LLVMOrcLookupStateContinueLookup to continue the lookup (this should be done
1122    /// unconditionally, even if errors have occurred in the mean time, to free the lookup state
1123    /// memory and notify the query object of the failures). If LookupState is captured this
1124    /// function must return LLVMErrorSuccess.
1125    ///
1126    /// The Kind argument can be inspected to determine the lookup kind (e.g.
1127    /// as-if-during-static-link, or as-if-during-dlsym).
1128    ///
1129    /// The JD argument specifies which JITDylib the definitions should be generated into.
1130    ///
1131    /// The JDLookupFlags argument can be inspected to determine whether the original lookup
1132    /// included non-exported symbols.
1133    ///
1134    /// Finally, the LookupSet argument contains the set of symbols that could not be found in JD
1135    /// already (the set of generation candidates).
1136    fn try_to_generate(
1137        &mut self,
1138        generator_obj: LLVMOrcDefinitionGeneratorRef,
1139        lookup_state: &mut LLVMOrcLookupStateRef,
1140        kind: LLVMOrcLookupKind,
1141        jd: JITDylibRef,
1142        jd_lookup_flags: LLVMOrcJITDylibLookupFlags,
1143        lookup_set: &[LLVMOrcCLookupSetElement],
1144    ) -> Result<(), String>;
1145}
1146
1147impl<T> CustomDefinitionGenerator for T
1148where
1149    T: FnMut(
1150        LLVMOrcDefinitionGeneratorRef,
1151        &mut LLVMOrcLookupStateRef,
1152        LLVMOrcLookupKind,
1153        JITDylibRef,
1154        LLVMOrcJITDylibLookupFlags,
1155        &[LLVMOrcCLookupSetElement],
1156    ) -> Result<(), String>,
1157{
1158    #[inline]
1159    fn try_to_generate(
1160        &mut self,
1161        generator_obj: LLVMOrcDefinitionGeneratorRef,
1162        lookup_state: &mut LLVMOrcLookupStateRef,
1163        kind: LLVMOrcLookupKind,
1164        jd: JITDylibRef,
1165        jd_lookup_flags: LLVMOrcJITDylibLookupFlags,
1166        lookup_set: &[LLVMOrcCLookupSetElement],
1167    ) -> Result<(), String> {
1168        self(generator_obj, lookup_state, kind, jd, jd_lookup_flags, lookup_set)
1169    }
1170}
1171
1172/// [`LLVMOrcJITTargetMachineBuilderRef`], used in [`LLJITBuilder`].
1173pub struct JITTargetMachineBuilder {
1174    builder: LLVMOrcJITTargetMachineBuilderRef,
1175}
1176
1177impl JITTargetMachineBuilder {
1178    /// Create a JITTargetMachineBuilder from the given TargetMachine template.
1179    pub fn new(tm: TargetMachine) -> Self {
1180        let tm = mem::ManuallyDrop::new(tm);
1181        unsafe {
1182            Self::from_inner(LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm.as_mut_ptr()))
1183        }
1184    }
1185
1186    /// Create a JITTargetMachineBuilder by detecting the host.
1187    pub fn detect_host() -> Result<Self, LLVMString> {
1188        let mut res = MaybeUninit::uninit();
1189        cvt(unsafe { LLVMOrcJITTargetMachineBuilderDetectHost(res.as_mut_ptr()) })?;
1190        Ok(Self { builder: unsafe { res.assume_init() } })
1191    }
1192
1193    /// Wraps a raw pointer.
1194    pub unsafe fn from_inner(builder: LLVMOrcJITTargetMachineBuilderRef) -> Self {
1195        Self { builder }
1196    }
1197
1198    /// Unwraps the raw pointer.
1199    pub fn as_inner(&self) -> LLVMOrcJITTargetMachineBuilderRef {
1200        self.builder
1201    }
1202
1203    /// Returns the target triple for the given JITTargetMachineBuilder as a string.
1204    pub fn get_target_triple(&self) -> LLVMString {
1205        unsafe { llvm_string(LLVMOrcJITTargetMachineBuilderGetTargetTriple(self.as_inner())) }
1206    }
1207
1208    /// Sets the target triple for the given JITTargetMachineBuilder to the given string.
1209    pub fn set_target_triple(&self, triple: &CStr) {
1210        unsafe { LLVMOrcJITTargetMachineBuilderSetTargetTriple(self.as_inner(), triple.as_ptr()) }
1211    }
1212}
1213
1214impl Drop for JITTargetMachineBuilder {
1215    fn drop(&mut self) {
1216        unsafe { LLVMOrcDisposeJITTargetMachineBuilder(self.builder) }
1217    }
1218}
1219
1220/// Lazily-initialized [`LLJIT`] builder.
1221#[must_use]
1222pub struct LLJITBuilder {
1223    builder: lljit::LLVMOrcLLJITBuilderRef,
1224}
1225
1226impl LLJITBuilder {
1227    /// Creates a new default LLJIT builder.
1228    pub fn new() -> Self {
1229        Self { builder: ptr::null_mut() }
1230    }
1231
1232    /// Wraps a raw pointer.
1233    pub unsafe fn from_inner(builder: LLVMOrcLLJITBuilderRef) -> Self {
1234        Self { builder }
1235    }
1236
1237    /// Unwraps the raw pointer.
1238    pub fn as_inner(&self) -> LLVMOrcLLJITBuilderRef {
1239        self.builder
1240    }
1241
1242    fn as_inner_init(&mut self) -> LLVMOrcLLJITBuilderRef {
1243        if self.builder.is_null() {
1244            self.builder = unsafe { LLVMOrcCreateLLJITBuilder() };
1245        }
1246        self.builder
1247    }
1248
1249    /// Set the target machine builder by creating it from the given template.
1250    pub fn set_target_machine(self, tm: TargetMachine) -> Self {
1251        self.set_target_machine_builder(JITTargetMachineBuilder::new(tm))
1252    }
1253
1254    /// Set the target machine builder by detecting the host.
1255    pub fn set_target_machine_from_host(self) -> Result<Self, LLVMString> {
1256        JITTargetMachineBuilder::detect_host().map(|jtmb| self.set_target_machine_builder(jtmb))
1257    }
1258
1259    /// Set the target machine builder.
1260    pub fn set_target_machine_builder(mut self, jtmb: JITTargetMachineBuilder) -> Self {
1261        let jtmb = mem::ManuallyDrop::new(jtmb);
1262        unsafe {
1263            LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(self.as_inner_init(), jtmb.as_inner())
1264        };
1265        self
1266    }
1267
1268    /*
1269    pub fn set_object_linking_layer_creator(self, mut f: &mut dyn FnMut(*const (), &CStr)) -> Self {
1270        extern "C" fn shim(
1271            ctx: *mut c_void,
1272            es: LLVMOrcExecutionSessionRef,
1273            triple: *const c_char,
1274        ) -> LLVMOrcObjectLayerRef {
1275            let f = ctx.cast::<&mut dyn FnMut(*const (), &CStr)>();
1276            let name = unsafe { CStr::from_ptr(triple) };
1277            unsafe { (*f)(es.cast(), name) };
1278            ptr::null_mut()
1279        }
1280
1281        let ctx = &mut f as *mut _ as *mut c_void;
1282        unsafe { LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator(self.as_inner_init(), shim, ctx) };
1283        self
1284    }
1285    */
1286
1287    /// Use a thread-safe compiler without spawning background threads.
1288    ///
1289    /// Installs `ConcurrentIRCompiler` (fresh `TargetMachine` per compilation)
1290    /// so multiple caller threads can compile through the same LLJIT safely.
1291    /// The default `InPlaceTaskDispatcher` is preserved, meaning compilation
1292    /// runs inline on the thread that triggers it — no background threads.
1293    pub fn concurrent_compiler(mut self) -> Self {
1294        unsafe {
1295            crate::cpp::revmc_llvm_lljit_builder_set_concurrent_compiler(self.as_inner_init())
1296        };
1297        self
1298    }
1299
1300    /// Builds the JIT.
1301    pub fn build(self) -> Result<LLJIT, LLVMString> {
1302        // This operation takes ownership of the Builder argument: clients should not
1303        // dispose of the builder after calling this function (even if the function
1304        // returns an error).
1305        let builder = mem::ManuallyDrop::new(self);
1306        let mut res = MaybeUninit::uninit();
1307        cvt(unsafe { LLVMOrcCreateLLJIT(res.as_mut_ptr(), builder.as_inner()) })?;
1308        Ok(unsafe { LLJIT::from_inner(res.assume_init()) })
1309    }
1310}
1311
1312impl Drop for LLJITBuilder {
1313    fn drop(&mut self) {
1314        if !self.builder.is_null() {
1315            unsafe { LLVMOrcDisposeLLJITBuilder(self.builder) };
1316        }
1317    }
1318}
1319
1320/// An ORC JIT.
1321///
1322/// Manages the memory of all JIT'd code and all modules that are transferred to it.
1323///
1324/// See [the ORCv2 docs](https://releases.llvm.org/17.0.1/docs/ORCv2.html).
1325pub struct LLJIT {
1326    jit: LLVMOrcLLJITRef,
1327}
1328
1329impl fmt::Debug for LLJIT {
1330    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1331        f.debug_struct("LLJIT").finish_non_exhaustive()
1332    }
1333}
1334
1335impl LLJIT {
1336    /// Creates a new LLJIT builder.
1337    pub fn builder() -> LLJITBuilder {
1338        LLJITBuilder::new()
1339    }
1340
1341    /// Creates a new ORC JIT, auto-detecting the host target.
1342    pub fn new() -> Result<Self, LLVMString> {
1343        LLJITBuilder::new().build()
1344    }
1345
1346    /// Wraps a raw pointer.
1347    pub unsafe fn from_inner(jit: LLVMOrcLLJITRef) -> Self {
1348        Self { jit }
1349    }
1350
1351    /// Unwraps the raw pointer.
1352    pub fn as_inner(&self) -> LLVMOrcLLJITRef {
1353        self.jit
1354    }
1355
1356    /// Return the target triple for this LLJIT instance.
1357    pub fn get_triple_string(&self) -> &CStr {
1358        // This string is owned by the LLJIT instance and does not need to be freed by the caller.
1359        unsafe { CStr::from_ptr(LLVMOrcLLJITGetTripleString(self.jit)) }
1360    }
1361
1362    /// Return the data layout for this LLJIT instance.
1363    pub fn get_data_layout_string(&self) -> &CStr {
1364        // This string is owned by the LLJIT instance and does not need to be freed by the caller.
1365        unsafe { CStr::from_ptr(LLVMOrcLLJITGetDataLayoutStr(self.jit)) }
1366    }
1367
1368    /// Returns the global prefix character according to the LLJIT's DataLayout.
1369    pub fn get_global_prefix(&self) -> c_char {
1370        unsafe { LLVMOrcLLJITGetGlobalPrefix(self.jit) }
1371    }
1372
1373    /// Add an IR module to the main JITDylib.
1374    pub fn add_module(&self, tsm: ThreadSafeModule) -> Result<(), LLVMString> {
1375        let jd = self.get_main_jit_dylib();
1376        self.add_module_with_dylib(tsm, jd)
1377    }
1378
1379    /// Add an IR module to the given JITDylib.
1380    pub fn add_module_with_dylib(
1381        &self,
1382        tsm: ThreadSafeModule,
1383        jd: JITDylibRef,
1384    ) -> Result<(), LLVMString> {
1385        let tsm = mem::ManuallyDrop::new(tsm);
1386        cvt(unsafe { LLVMOrcLLJITAddLLVMIRModule(self.as_inner(), jd.as_inner(), tsm.as_inner()) })
1387    }
1388
1389    /// Add an IR module to the given ResourceTracker's JITDylib.
1390    pub fn add_module_with_rt(
1391        &self,
1392        tsm: ThreadSafeModule,
1393        rt: &ResourceTracker,
1394    ) -> Result<(), LLVMString> {
1395        let tsm = mem::ManuallyDrop::new(tsm);
1396        cvt(unsafe {
1397            LLVMOrcLLJITAddLLVMIRModuleWithRT(self.as_inner(), rt.as_inner(), tsm.as_inner())
1398        })
1399    }
1400
1401    /// Gets the execution session.
1402    pub fn get_execution_session(&self) -> ExecutionSessionRef<'_> {
1403        unsafe { ExecutionSessionRef::from_inner(LLVMOrcLLJITGetExecutionSession(self.as_inner())) }
1404    }
1405
1406    /// Return a reference to the Main JITDylib.
1407    pub fn get_main_jit_dylib(&self) -> JITDylibRef {
1408        unsafe { JITDylibRef::from_inner_unchecked(LLVMOrcLLJITGetMainJITDylib(self.as_inner())) }
1409    }
1410
1411    /// Mangles the given string according to the LLJIT instance's DataLayout, then interns the
1412    /// result in the SymbolStringPool and returns a reference to the pool entry.
1413    pub fn mangle_and_intern(&self, unmangled_name: &CStr) -> SymbolStringPoolEntry {
1414        unsafe {
1415            SymbolStringPoolEntry::from_inner_unchecked(LLVMOrcLLJITMangleAndIntern(
1416                self.as_inner(),
1417                unmangled_name.as_ptr(),
1418            ))
1419        }
1420    }
1421
1422    /// Look up the given symbol in the main JITDylib of the given LLJIT instance.
1423    ///
1424    /// The name is **unmangled** — `LLVMOrcLLJITLookup` applies the data layout
1425    /// prefix (e.g. `_` on macOS) internally.
1426    pub fn lookup(&self, name: &CStr) -> Result<usize, LLVMString> {
1427        let mut res = MaybeUninit::uninit();
1428        cvt(unsafe { LLVMOrcLLJITLookup(self.as_inner(), res.as_mut_ptr(), name.as_ptr()) })?;
1429        Ok(unsafe { res.assume_init() }.try_into().unwrap())
1430    }
1431
1432    /// Look up a symbol in a specific JITDylib.
1433    ///
1434    /// Unlike [`lookup`](Self::lookup), which only searches the main JITDylib,
1435    /// this searches the given `jd`. The name is **unmangled** — the LLJIT
1436    /// applies the data layout prefix (e.g. `_` on macOS) internally.
1437    pub fn lookup_in(&self, jd: JITDylibRef, name: &CStr) -> Result<usize, LLVMString> {
1438        let mut res = MaybeUninit::uninit();
1439        cvt(unsafe {
1440            crate::cpp::revmc_llvm_lljit_lookup_in(
1441                self.as_inner(),
1442                jd.as_inner(),
1443                res.as_mut_ptr(),
1444                name.as_ptr(),
1445            )
1446        })?;
1447        Ok(unsafe { res.assume_init() }.try_into().unwrap())
1448    }
1449
1450    /// Returns a non-owning reference to the LLJIT instance's IR transform layer.
1451    pub fn get_ir_transform_layer(&self) -> IRTransformLayerRef {
1452        unsafe { IRTransformLayerRef::from_inner(LLVMOrcLLJITGetIRTransformLayer(self.as_inner())) }
1453    }
1454
1455    /// Returns a non-owning reference to the LLJIT instance's object transform layer.
1456    pub fn get_obj_transform_layer(&self) -> ObjectTransformLayerRef {
1457        unsafe {
1458            ObjectTransformLayerRef::from_inner(LLVMOrcLLJITGetObjTransformLayer(self.as_inner()))
1459        }
1460    }
1461
1462    /// Install `PerfSupportPlugin` on the LLJIT's `ObjectLinkingLayer`.
1463    ///
1464    /// Writes perf jitdump records so `perf record -k 1` / `perf inject --jit`
1465    /// can resolve JIT-compiled symbols with full debug info and unwind info.
1466    /// Requires `ObjectLinkingLayer` (JITLink), which is the LLJIT default.
1467    pub fn enable_perf_support(&self) -> Result<(), LLVMString> {
1468        cvt(unsafe { crate::cpp::revmc_llvm_lljit_enable_perf_support(self.as_inner()) })
1469    }
1470
1471    /// Install `SimplePerfSupportPlugin` on the LLJIT's `ObjectLinkingLayer`.
1472    ///
1473    /// Writes `/tmp/perf-<pid>.map` in the perf map format so that profilers
1474    /// like `perf` and `samply` can resolve JIT-compiled symbols without
1475    /// the heavyweight jitdump machinery.
1476    /// Requires `ObjectLinkingLayer` (JITLink), which is the LLJIT default.
1477    ///
1478    /// Not suitable for long-running programs. The map file is append-only
1479    /// and never cleaned up, so entries for freed JIT code accumulate
1480    /// indefinitely. Prefer [`enable_perf_support`](Self::enable_perf_support)
1481    /// (jitdump) for long-lived processes.
1482    pub fn enable_simple_perf(&self) -> Result<(), LLVMString> {
1483        cvt(unsafe { crate::cpp::revmc_llvm_lljit_enable_simple_perf(self.as_inner()) })
1484    }
1485
1486    /// Install the plugin that submits debug objects to the executor via the
1487    /// GDB JIT Interface (`__jit_debug_register_code`).
1488    ///
1489    /// On ELF this installs `ELFDebugObjectPlugin`; on MachO,
1490    /// `GDBJITDebugInfoRegistrationPlugin`. Requires `ObjectLinkingLayer`
1491    /// (JITLink), which is the LLJIT default.
1492    ///
1493    /// Once enabled, compiled objects containing DWARF debug info are
1494    /// automatically registered so that GDB, LLDB, `perf`, and other profilers
1495    /// can resolve JIT-compiled function names and source locations.
1496    pub fn enable_debug_support(&self) -> Result<(), LLVMString> {
1497        cvt(unsafe { crate::cpp::revmc_llvm_lljit_enable_debug_support(self.as_inner()) })
1498    }
1499}
1500
1501impl Drop for LLJIT {
1502    fn drop(&mut self) {
1503        if let Err(e) = cvt(unsafe { LLVMOrcDisposeLLJIT(self.jit) }) {
1504            error!("Failed to dispose JIT: {e}");
1505        }
1506    }
1507}
1508
1509/// A reference to an object layer.
1510pub struct ObjectLayerRef {
1511    ptr: LLVMOrcObjectLayerRef,
1512}
1513
1514impl ObjectLayerRef {
1515    /// Wraps a raw pointer.
1516    pub unsafe fn from_inner(ptr: LLVMOrcObjectLayerRef) -> Self {
1517        Self { ptr }
1518    }
1519
1520    /// Unwraps the raw pointer.
1521    pub fn as_inner(&self) -> LLVMOrcObjectLayerRef {
1522        self.ptr
1523    }
1524}
1525
1526/// Callback for [`ObjectTransformLayerRef::set_transform`].
1527type ObjTransformFn = fn(&[u8]) -> Result<Option<Vec<u8>>, String>;
1528
1529/// A reference to an object transform layer.
1530///
1531/// The transform layer sits between the IR compiler and the object linking layer.
1532/// A transform callback can inspect or modify the compiled object buffer before linking.
1533pub struct ObjectTransformLayerRef {
1534    ptr: LLVMOrcObjectTransformLayerRef,
1535}
1536
1537impl ObjectTransformLayerRef {
1538    /// Wraps a raw pointer.
1539    pub unsafe fn from_inner(ptr: LLVMOrcObjectTransformLayerRef) -> Self {
1540        Self { ptr }
1541    }
1542
1543    /// Unwraps the raw pointer.
1544    pub fn as_inner(&self) -> LLVMOrcObjectTransformLayerRef {
1545        self.ptr
1546    }
1547
1548    // TODO: avoid copying, better api for mutation
1549    /// Set the transform function on this object transform layer.
1550    ///
1551    /// The callback receives the compiled object buffer as `&[u8]`. Returning `Ok(None)`
1552    /// passes the buffer through unchanged; returning `Ok(Some(new_bytes))` replaces it.
1553    /// Returning `Err` aborts materialization.
1554    pub fn set_transform(&self, f: ObjTransformFn) {
1555        extern "C" fn shim(ctx: *mut c_void, obj_in_out: *mut LLVMMemoryBufferRef) -> LLVMErrorRef {
1556            use inkwell::llvm_sys::core::{
1557                LLVMCreateMemoryBufferWithMemoryRangeCopy, LLVMDisposeMemoryBuffer,
1558                LLVMGetBufferSize, LLVMGetBufferStart,
1559            };
1560            let f: ObjTransformFn = unsafe { mem::transmute(ctx) };
1561            let buf = unsafe { *obj_in_out };
1562            let data = unsafe {
1563                let start = LLVMGetBufferStart(buf);
1564                let size = LLVMGetBufferSize(buf);
1565                std::slice::from_raw_parts(start.cast::<u8>(), size)
1566            };
1567            let res = std::panic::catch_unwind(AssertUnwindSafe(|| f(data)));
1568            cvt_cb_res_t(res, |new_bytes| {
1569                if let Some(new_bytes) = new_bytes {
1570                    unsafe {
1571                        LLVMDisposeMemoryBuffer(buf);
1572                        *obj_in_out = LLVMCreateMemoryBufferWithMemoryRangeCopy(
1573                            new_bytes.as_ptr().cast(),
1574                            new_bytes.len(),
1575                            c"".as_ptr(),
1576                        );
1577                    }
1578                }
1579            })
1580        }
1581
1582        let ctx = f as *mut c_void;
1583        unsafe { self.set_transform_raw(shim, ctx) }
1584    }
1585
1586    /// Set a raw transform function on this object transform layer.
1587    ///
1588    /// # Safety
1589    ///
1590    /// `ctx` must be valid for the lifetime of this layer and `f` must not unwind.
1591    pub unsafe fn set_transform_raw(
1592        &self,
1593        f: extern "C" fn(ctx: *mut c_void, obj_in_out: *mut LLVMMemoryBufferRef) -> LLVMErrorRef,
1594        ctx: *mut c_void,
1595    ) {
1596        LLVMOrcObjectTransformLayerSetTransform(self.as_inner(), f, ctx);
1597    }
1598}
1599
1600/// A reference to an IR transform layer.
1601pub struct IRTransformLayerRef {
1602    ptr: LLVMOrcIRTransformLayerRef,
1603}
1604
1605impl IRTransformLayerRef {
1606    /// Wraps a raw pointer.
1607    pub unsafe fn from_inner(ptr: LLVMOrcIRTransformLayerRef) -> Self {
1608        Self { ptr }
1609    }
1610
1611    /// Unwraps the raw pointer.
1612    pub fn as_inner(&self) -> LLVMOrcIRTransformLayerRef {
1613        self.ptr
1614    }
1615
1616    /// Emit should materialize the given IR.
1617    pub fn emit(&self, mr: MaterializationResponsibility, tsm: ThreadSafeModule) {
1618        let mr = mem::ManuallyDrop::new(mr);
1619        let tsm = mem::ManuallyDrop::new(tsm);
1620        unsafe { LLVMOrcIRTransformLayerEmit(self.as_inner(), mr.as_inner(), tsm.as_inner()) };
1621    }
1622
1623    /// Set the transform function of this transform layer.
1624    pub fn set_transform(
1625        &self,
1626        f: fn(&ThreadSafeModule, MaterializationResponsibilityRef<'_>) -> Result<(), String>,
1627    ) {
1628        extern "C" fn shim(
1629            ctx: *mut c_void,
1630            m: *mut LLVMOrcThreadSafeModuleRef,
1631            mr: LLVMOrcMaterializationResponsibilityRef,
1632        ) -> LLVMErrorRef {
1633            let f: fn(
1634                &ThreadSafeModule,
1635                MaterializationResponsibilityRef<'_>,
1636            ) -> Result<(), String> = unsafe { mem::transmute(ctx) };
1637            let m = mem::ManuallyDrop::new(unsafe { ThreadSafeModule::from_inner(*m) });
1638            let mr = unsafe { MaterializationResponsibilityRef::from_inner(mr) };
1639            let res = std::panic::catch_unwind(AssertUnwindSafe(|| f(&m, mr)));
1640            cvt_cb_res(res)
1641        }
1642
1643        let ctx = f as *mut c_void;
1644        unsafe { LLVMOrcIRTransformLayerSetTransform(self.as_inner(), shim, ctx) };
1645    }
1646}
1647
1648// SAFETY: ORC/LLJIT is designed for concurrent use from multiple threads.
1649// All session operations are internally synchronized.
1650unsafe impl Send for LLJIT {}
1651unsafe impl Sync for LLJIT {}
1652
1653unsafe impl Send for ExecutionSessionRef<'_> {}
1654unsafe impl Sync for ExecutionSessionRef<'_> {}
1655
1656unsafe impl Send for JITDylibRef {}
1657unsafe impl Sync for JITDylibRef {}
1658
1659unsafe impl Send for ResourceTracker {}
1660unsafe impl Sync for ResourceTracker {}
1661
1662unsafe impl Send for ObjectTransformLayerRef {}
1663unsafe impl Sync for ObjectTransformLayerRef {}
1664
1665unsafe impl Send for IRTransformLayerRef {}
1666unsafe impl Sync for IRTransformLayerRef {}
1667
1668unsafe impl Send for SymbolStringPoolRef {}
1669unsafe impl Sync for SymbolStringPoolRef {}
1670
1671unsafe impl Send for SymbolStringPoolEntry {}
1672unsafe impl Sync for SymbolStringPoolEntry {}
1673
1674unsafe impl Send for ThreadSafeContext {}
1675
1676unsafe impl Send for ThreadSafeModule {}
1677
1678unsafe impl Send for MaterializationUnit {}
1679
1680unsafe impl Send for DefinitionGenerator {}
1681
1682unsafe impl Send for JITTargetMachineBuilder {}
1683
1684unsafe impl Send for LLJITBuilder {}
1685
1686/// Converts an `LLVMErrorRef` to a `Result`.
1687pub(crate) fn cvt(ptr: LLVMErrorRef) -> Result<(), LLVMString> {
1688    if ptr.is_null() { Ok(()) } else { Err(unsafe { llvm_string(LLVMGetErrorMessage(ptr)) }) }
1689}
1690
1691fn cvt_cb_res(res: Result<Result<(), String>, Box<dyn std::any::Any + Send>>) -> LLVMErrorRef {
1692    cvt_cb_res_t(res, drop)
1693}
1694
1695fn cvt_cb_res_t<T>(
1696    res: Result<Result<T, String>, Box<dyn std::any::Any + Send>>,
1697    f: impl FnOnce(T),
1698) -> LLVMErrorRef {
1699    let msg = match res {
1700        Ok(Ok(x)) => {
1701            f(x);
1702            return ptr::null_mut(); // LLVMErrorSuccess
1703        }
1704        Ok(Err(e)) => e,
1705        Err(e) => format!("callback panicked, payload: {:?}", panic_payload(&e)),
1706    };
1707    unsafe { LLVMCreateStringError(CString::new(msg).unwrap_or_default().as_ptr()) }
1708}
1709
1710fn panic_payload(any: &dyn std::any::Any) -> Option<&str> {
1711    if let Some(s) = any.downcast_ref::<&str>() {
1712        Some(*s)
1713    } else if let Some(s) = any.downcast_ref::<String>() {
1714        Some(s.as_str())
1715    } else {
1716        None
1717    }
1718}
1719
1720/// Deallocates the vector without running the elements' destructors.
1721// Comment from LLVMOrcAbsoluteSymbols:
1722/*
1723 * This function takes ownership of the elements of the Syms array. The Name
1724 * fields of the array elements are taken to have been retained for this
1725 * function. This allows the following pattern...
1726 *
1727 *   size_t NumPairs;
1728 *   LLVMOrcCSymbolMapPairs Sym;
1729 *   -- Build Syms array --
1730 *   LLVMOrcMaterializationUnitRef MU =
1731 *       LLVMOrcAbsoluteSymbols(Syms, NumPairs);
1732 *
1733 * ... without requiring cleanup of the elements of the Sym array afterwards.
1734 *
1735 * The client is still responsible for deleting the Sym array itself.
1736 *
1737 * If a client wishes to reuse elements of the Sym array after this call they
1738 * must explicitly retain each of the elements for themselves.
1739 */
1740struct ManuallyDropElements<T> {
1741    vec: Vec<T>,
1742}
1743
1744impl<T> ManuallyDropElements<T> {
1745    #[inline(always)]
1746    fn new(vec: Vec<T>) -> Self {
1747        Self { vec }
1748    }
1749}
1750
1751impl<T> std::ops::Deref for ManuallyDropElements<T> {
1752    type Target = Vec<T>;
1753
1754    #[inline(always)]
1755    fn deref(&self) -> &Vec<T> {
1756        &self.vec
1757    }
1758}
1759
1760impl<T> std::ops::DerefMut for ManuallyDropElements<T> {
1761    #[inline(always)]
1762    fn deref_mut(&mut self) -> &mut Vec<T> {
1763        &mut self.vec
1764    }
1765}
1766
1767impl<T> Drop for ManuallyDropElements<T> {
1768    #[inline(always)]
1769    fn drop(&mut self) {
1770        unsafe { self.vec.set_len(0) };
1771    }
1772}
1773
1774#[cfg(test)]
1775mod tests {
1776    use super::*;
1777    use inkwell::{passes::PassBuilderOptions, targets::Target};
1778
1779    #[test]
1780    fn e2e_with_tsc() {
1781        use mem::ManuallyDrop;
1782
1783        Target::initialize_native(&Default::default()).unwrap();
1784        let triple = TargetMachine::get_default_triple();
1785        let cpu = TargetMachine::get_host_cpu_name();
1786        let features = TargetMachine::get_host_cpu_features();
1787        let target = Target::from_triple(&triple).unwrap();
1788
1789        let cx = Context::create();
1790        let raw = cx.raw();
1791        let tscx = ThreadSafeContext::from_context(cx);
1792        let cx_handle = Box::new(ManuallyDrop::new(unsafe { Context::new(raw) }));
1793        let cx: &Context = unsafe { &*(&**cx_handle as *const Context) };
1794
1795        let machine = target
1796            .create_target_machine(
1797                &triple,
1798                &cpu.to_string_lossy(),
1799                &features.to_string_lossy(),
1800                inkwell::OptimizationLevel::None,
1801                inkwell::targets::RelocMode::Static,
1802                inkwell::targets::CodeModel::JITDefault,
1803            )
1804            .unwrap();
1805
1806        let jit = LLJITBuilder::new().build().unwrap();
1807
1808        // Build module.
1809        let m = cx.create_module("test");
1810        m.set_data_layout(&machine.get_target_data().get_data_layout());
1811        m.set_triple(&triple);
1812
1813        let fn_name = "my_fn";
1814        let bcx = cx.create_builder();
1815
1816        // Add an unused external declaration and register absolute symbol.
1817        extern "C" fn my_external(x: i64) -> i64 {
1818            x + 100
1819        }
1820        let ext_ty = cx.i64_type().fn_type(&[cx.i64_type().into()], false);
1821        let _ext_fn =
1822            m.add_function("my_external", ext_ty, Some(inkwell::module::Linkage::External));
1823        let ext_name = CString::new("my_external").unwrap();
1824        let sym = SymbolMapPair::new(
1825            jit.mangle_and_intern(&ext_name),
1826            EvaluatedSymbol::new(
1827                my_external as *const () as u64,
1828                SymbolFlags::none().exported().callable(),
1829            ),
1830        );
1831        jit.get_main_jit_dylib()
1832            .define(MaterializationUnit::absolute_symbols(vec![sym]))
1833            .map_err(|(e, _)| e)
1834            .unwrap();
1835
1836        let ty = cx.i64_type().fn_type(&[], false);
1837        let f = m.add_function(fn_name, ty, Some(inkwell::module::Linkage::External));
1838        let bb = cx.append_basic_block(f, "entry");
1839        bcx.position_at_end(bb);
1840        bcx.build_return(Some(&cx.i64_type().const_int(142, false))).unwrap();
1841
1842        eprintln!("module:\n{}", m.print_to_string().to_string_lossy());
1843        m.verify().unwrap();
1844
1845        // Wrap and add to JIT.
1846        let tsm = tscx.create_module(m);
1847        jit.add_module(tsm).unwrap();
1848
1849        // Lookup.
1850        let address = jit.lookup(&CString::new(fn_name).unwrap()).unwrap();
1851        eprintln!("address: {address:#x}");
1852        // Check the first few bytes at the address to see if it's valid code.
1853        let code = unsafe { std::slice::from_raw_parts(address as *const u8, 16) };
1854        eprintln!("code bytes: {code:02x?}");
1855        let f = unsafe { mem::transmute::<usize, extern "C" fn() -> u64>(address) };
1856        eprintln!("about to call...");
1857        let r = f();
1858        eprintln!("result: {r}");
1859        assert_eq!(r, 142);
1860        eprintln!("dropping jit...");
1861        drop(jit);
1862        eprintln!("dropping machine...");
1863        drop(machine);
1864        eprintln!("dropping cx_handle...");
1865        drop(cx_handle);
1866        eprintln!("dropping tscx...");
1867        drop(tscx);
1868        eprintln!("all dropped, test done");
1869    }
1870
1871    #[test]
1872    fn lookup_in_custom_jd() {
1873        use mem::ManuallyDrop;
1874
1875        Target::initialize_native(&Default::default()).unwrap();
1876        let triple = TargetMachine::get_default_triple();
1877        let cpu = TargetMachine::get_host_cpu_name();
1878        let features = TargetMachine::get_host_cpu_features();
1879        let target = Target::from_triple(&triple).unwrap();
1880
1881        let cx = Context::create();
1882        let raw = cx.raw();
1883        let tscx = ThreadSafeContext::from_context(cx);
1884        let cx_handle = Box::new(ManuallyDrop::new(unsafe { Context::new(raw) }));
1885        let cx: &Context = unsafe { &*(&**cx_handle as *const Context) };
1886
1887        let machine = target
1888            .create_target_machine(
1889                &triple,
1890                &cpu.to_string_lossy(),
1891                &features.to_string_lossy(),
1892                inkwell::OptimizationLevel::None,
1893                inkwell::targets::RelocMode::Static,
1894                inkwell::targets::CodeModel::JITDefault,
1895            )
1896            .unwrap();
1897
1898        let jit = LLJITBuilder::new().build().unwrap();
1899
1900        // Create two custom JITDylibs with functions returning different values.
1901        let jd_a = jit.get_execution_session().create_bare_jit_dylib(c"test_a");
1902        let jd_b = jit.get_execution_session().create_bare_jit_dylib(c"test_b");
1903
1904        for (jd, value) in [(&jd_a, 111u64), (&jd_b, 222u64)] {
1905            let m = cx.create_module("test");
1906            m.set_data_layout(&machine.get_target_data().get_data_layout());
1907            m.set_triple(&triple);
1908
1909            let fn_name = "test_fn";
1910            let bcx = cx.create_builder();
1911            let ty = cx.i64_type().fn_type(&[], false);
1912            let f = m.add_function(fn_name, ty, Some(inkwell::module::Linkage::External));
1913            let bb = cx.append_basic_block(f, "entry");
1914            bcx.position_at_end(bb);
1915            bcx.build_return(Some(&cx.i64_type().const_int(value, false))).unwrap();
1916            m.verify().unwrap();
1917
1918            let module = ManuallyDrop::new(m);
1919            let tsm = unsafe {
1920                ThreadSafeModule::create_in_context(Module::new(module.as_mut_ptr()), &tscx)
1921            };
1922            jit.add_module_with_dylib(tsm, unsafe {
1923                JITDylibRef::from_inner_unchecked(jd.as_inner())
1924            })
1925            .unwrap();
1926        }
1927
1928        // Lookup in each JD should return the correct function.
1929        let addr_a = jit.lookup_in(jd_a, c"test_fn").unwrap();
1930        let addr_b = jit.lookup_in(jd_b, c"test_fn").unwrap();
1931        assert_ne!(addr_a, addr_b);
1932
1933        let f_a = unsafe { mem::transmute::<usize, extern "C" fn() -> u64>(addr_a) };
1934        let f_b = unsafe { mem::transmute::<usize, extern "C" fn() -> u64>(addr_b) };
1935        assert_eq!(f_a(), 111);
1936        assert_eq!(f_b(), 222);
1937
1938        // Clearing one JD should not affect the other.
1939        jd_a.clear().unwrap();
1940        assert_eq!(f_b(), 222);
1941    }
1942
1943    #[test]
1944    fn e2e() {
1945        let tsm = ThreadSafeModule::create("test");
1946        let fn_name = "my_fn";
1947        tsm.with_module(|m| {
1948            let cx = m.get_context();
1949            let bcx = cx.create_builder();
1950            let ty = cx.i64_type().fn_type(&[], false);
1951
1952            let f = m.add_function(fn_name, ty, Some(inkwell::module::Linkage::External));
1953            let bb = cx.append_basic_block(f, "entry");
1954            bcx.position_at_end(bb);
1955            bcx.build_int_compare(
1956                inkwell::IntPredicate::EQ,
1957                cx.i64_type().const_zero(),
1958                cx.i64_type().const_all_ones(),
1959                "a",
1960            )
1961            .unwrap();
1962            bcx.build_return(Some(&cx.i64_type().const_int(69, false))).unwrap();
1963
1964            eprintln!("--before--");
1965            eprintln!("{}", m.print_to_string().to_string_lossy());
1966
1967            m.verify().map_err(|e| e.to_string())?;
1968
1969            Target::initialize_native(&Default::default()).unwrap();
1970            let triple = TargetMachine::get_default_triple();
1971            let cpu = TargetMachine::get_host_cpu_name();
1972            let features = TargetMachine::get_host_cpu_features();
1973            let target = Target::from_triple(&triple).map_err(|e| e.to_string())?;
1974            let machine = target
1975                .create_target_machine(
1976                    &triple,
1977                    &cpu.to_string_lossy(),
1978                    &features.to_string_lossy(),
1979                    Default::default(),
1980                    inkwell::targets::RelocMode::Default,
1981                    inkwell::targets::CodeModel::Default,
1982                )
1983                .ok_or_else(|| String::from("failed to create target machine"))?;
1984
1985            m.run_passes("default<O3>", &machine, PassBuilderOptions::create()).unwrap();
1986
1987            eprintln!("--after--");
1988            eprintln!("{}", m.print_to_string().to_string_lossy());
1989
1990            Ok(())
1991        })
1992        .unwrap();
1993
1994        let jit = LLJIT::new().unwrap();
1995        jit.add_module(tsm).unwrap();
1996        let address = jit.lookup(&CString::new(fn_name).unwrap()).unwrap();
1997        eprintln!("address: {address:#x}");
1998        let f = unsafe { mem::transmute::<usize, extern "C" fn() -> u64>(address) };
1999        let r = f();
2000        assert_eq!(r, 69);
2001    }
2002}