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