1#![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
44pub 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 pub fn new() -> Self {
62 unsafe { Self::from_inner(LLVMOrcCreateNewThreadSafeContext()) }
63 }
64
65 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 pub unsafe fn from_inner(ctx: LLVMOrcThreadSafeContextRef) -> Self {
73 Self { ctx }
74 }
75
76 pub fn as_inner(&self) -> LLVMOrcThreadSafeContextRef {
78 self.ctx
79 }
80
81 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
93pub struct ThreadSafeModule {
101 ptr: LLVMOrcThreadSafeModuleRef,
102}
103
104impl ThreadSafeModule {
105 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 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 pub unsafe fn from_inner(ptr: LLVMOrcThreadSafeModuleRef) -> Self {
129 Self { ptr }
130 }
131
132 pub fn as_inner(&self) -> LLVMOrcThreadSafeModuleRef {
134 self.ptr
135 }
136
137 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#[repr(C)]
165pub struct SymbolStringPoolRef {
166 ptr: LLVMOrcSymbolStringPoolRef,
167}
168
169impl SymbolStringPoolRef {
170 pub unsafe fn from_inner(ptr: LLVMOrcSymbolStringPoolRef) -> Self {
172 Self { ptr }
173 }
174
175 pub fn as_inner(&self) -> LLVMOrcSymbolStringPoolRef {
177 self.ptr
178 }
179
180 pub fn clear_dead_entries(&self) {
189 unsafe { LLVMOrcSymbolStringPoolClearDeadEntries(self.as_inner()) };
190 }
191}
192
193#[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 pub unsafe fn from_inner(ptr: LLVMOrcSymbolStringPoolEntryRef) -> Option<Self> {
224 NonNull::new(ptr).map(|ptr| Self { ptr })
225 }
226
227 pub unsafe fn from_inner_unchecked(ptr: LLVMOrcSymbolStringPoolEntryRef) -> Self {
229 Self { ptr: NonNull::new_unchecked(ptr) }
230 }
231
232 pub fn as_inner(&self) -> LLVMOrcSymbolStringPoolEntryRef {
234 self.ptr.as_ptr()
235 }
236
237 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#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
251#[repr(C)]
252pub struct EvaluatedSymbol {
253 pub address: u64,
255 pub flags: SymbolFlags,
257}
258
259impl EvaluatedSymbol {
260 pub fn new(address: u64, flags: SymbolFlags) -> Self {
262 Self { address, flags }
263 }
264
265 pub fn from_flags(flags: SymbolFlags) -> Self {
267 Self { address: 0, flags }
268 }
269
270 pub fn from_address(address: usize) -> Self {
272 Self { address: address as u64, flags: SymbolFlags::none() }
273 }
274}
275
276#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
278#[repr(C)]
279pub struct SymbolFlags {
280 pub generic: u8,
282 pub target: u8,
284}
285
286impl Default for SymbolFlags {
287 fn default() -> Self {
288 Self::none()
289 }
290}
291
292impl SymbolFlags {
293 pub fn none() -> Self {
295 Self { generic: LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsNone as u8, target: 0 }
296 }
297
298 pub fn set_exported(&mut self) {
300 self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsExported as u8;
301 }
302
303 pub fn exported(mut self) -> Self {
305 self.set_exported();
306 self
307 }
308
309 pub fn is_exported(&self) -> bool {
311 (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsExported as u8) != 0
312 }
313
314 pub fn set_weak(&mut self) {
316 self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsWeak as u8;
317 }
318
319 pub fn weak(mut self) -> Self {
321 self.set_weak();
322 self
323 }
324
325 pub fn is_weak(&self) -> bool {
327 (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsWeak as u8) != 0
328 }
329
330 pub fn set_callable(&mut self) {
332 self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsCallable as u8;
333 }
334
335 pub fn callable(mut self) -> Self {
337 self.set_callable();
338 self
339 }
340
341 pub fn is_callable(&self) -> bool {
343 (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsCallable as u8) != 0
344 }
345
346 pub fn set_materialization_side_effects_only(&mut self) {
348 self.generic |=
349 LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly
350 as u8;
351 }
352
353 pub fn materialization_side_effects_only(mut self) -> Self {
355 self.set_materialization_side_effects_only();
356 self
357 }
358
359 pub fn is_materialization_side_effects_only(&self) -> bool {
361 (self.generic
362 & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly
363 as u8)
364 != 0
365 }
366
367 pub fn set_generic(&mut self, flag: LLVMJITSymbolGenericFlags) {
369 self.generic |= flag as u8;
370 }
371
372 pub fn with_generic(mut self, flag: LLVMJITSymbolGenericFlags) -> Self {
374 self.set_generic(flag);
375 self
376 }
377
378 pub fn set_target(&mut self, flag: LLVMJITSymbolTargetFlags) {
380 self.target |= flag;
381 }
382
383 pub fn with_target(mut self, flag: LLVMJITSymbolTargetFlags) -> Self {
385 self.set_target(flag);
386 self
387 }
388}
389
390#[derive(Clone, Debug, PartialEq, Eq, Hash)]
392#[repr(C)]
393pub struct SymbolFlagsMapPair {
394 pub name: SymbolStringPoolEntry,
396 pub flags: SymbolFlags,
398}
399
400impl SymbolFlagsMapPair {
401 pub fn new(name: SymbolStringPoolEntry, flags: SymbolFlags) -> Self {
403 Self { name, flags }
404 }
405}
406
407#[derive(Clone, Debug, PartialEq, Eq, Hash)]
409#[repr(C)]
410pub struct SymbolMapPair {
411 pub name: SymbolStringPoolEntry,
413 pub evaluated_symbol: EvaluatedSymbol,
415}
416
417impl SymbolMapPair {
418 pub fn new(name: SymbolStringPoolEntry, evaluated_symbol: EvaluatedSymbol) -> Self {
420 Self { name, evaluated_symbol }
421 }
422}
423
424pub struct SymbolFlagsMapPairs<'a>(&'a [SymbolFlagsMapPair]);
428
429impl<'a> SymbolFlagsMapPairs<'a> {
430 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
450pub 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 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 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 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 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 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 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 pub unsafe fn absolute_symbols_raw(syms: LLVMOrcCSymbolMapPairs, len: usize) -> Self {
570 unsafe { Self::from_inner(LLVMOrcAbsoluteSymbols(syms, len)) }
571 }
572
573 pub unsafe fn from_inner(mu: LLVMOrcMaterializationUnitRef) -> Self {
577 Self { mu }
578 }
579
580 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
592pub trait CustomMaterializationUnit {
596 fn materialize(self: Box<Self>, mr: MaterializationResponsibility);
598
599 fn discard(&mut self, jd: JITDylibRef, symbol: &SymbolStringPoolEntry);
601
602 }
604
605pub struct MaterializationResponsibility {
607 mr: LLVMOrcMaterializationResponsibilityRef,
608}
609
610impl MaterializationResponsibility {
611 pub unsafe fn from_inner(mr: LLVMOrcMaterializationResponsibilityRef) -> Self {
613 Self { mr }
614 }
615
616 pub fn as_inner(&self) -> LLVMOrcMaterializationResponsibilityRef {
618 self.mr
619 }
620
621 #[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
634pub struct MaterializationResponsibilityRef<'mr> {
636 mr: LLVMOrcMaterializationResponsibilityRef,
637 _marker: PhantomData<&'mr ()>,
638}
639
640impl<'mr> MaterializationResponsibilityRef<'mr> {
641 pub unsafe fn from_inner(mr: LLVMOrcMaterializationResponsibilityRef) -> Self {
643 Self { mr, _marker: PhantomData }
644 }
645
646 pub fn as_inner(&self) -> LLVMOrcMaterializationResponsibilityRef {
648 self.mr
649 }
650
651 pub fn get_target_dylib(&self) -> JITDylibRef {
653 unsafe {
654 JITDylibRef::from_inner_unchecked(LLVMOrcMaterializationResponsibilityGetTargetDylib(
655 self.as_inner(),
656 ))
657 }
658 }
659
660 pub fn get_execution_session(&self) -> ExecutionSessionRef<'mr> {
662 unsafe {
663 ExecutionSessionRef::from_inner(
664 LLVMOrcMaterializationResponsibilityGetExecutionSession(self.as_inner()),
665 )
666 }
667 }
668
669 pub fn get_symbols(&self) -> SymbolFlagsMapPairs<'mr> {
671 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 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 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 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 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 pub fn fail_materialization(&self) {
748 unsafe { LLVMOrcMaterializationResponsibilityFailMaterialization(self.as_inner()) };
749 }
750
751 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 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
782pub 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 pub unsafe fn from_inner(rt: LLVMOrcResourceTrackerRef) -> Self {
798 Self { rt }
799 }
800
801 pub fn as_inner(&self) -> LLVMOrcResourceTrackerRef {
803 self.rt
804 }
805
806 pub fn remove(&self) -> Result<(), LLVMString> {
808 cvt(unsafe { LLVMOrcResourceTrackerRemove(self.as_inner()) })
809 }
810
811 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
824pub struct ExecutionSessionRef<'ee> {
834 es: LLVMOrcExecutionSessionRef,
835 _marker: PhantomData<&'ee ()>,
836}
837
838impl ExecutionSessionRef<'_> {
839 pub unsafe fn from_inner(es: LLVMOrcExecutionSessionRef) -> Self {
841 Self { es, _marker: PhantomData }
842 }
843
844 pub fn as_inner(&self) -> LLVMOrcExecutionSessionRef {
846 self.es
847 }
848
849 pub fn get_symbol_string_pool(&self) -> SymbolStringPoolRef {
851 unsafe {
852 SymbolStringPoolRef::from_inner(LLVMOrcExecutionSessionGetSymbolStringPool(
853 self.as_inner(),
854 ))
855 }
856 }
857
858 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 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 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 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 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 pub fn set_default_error_reporter(&self) {
924 self.set_error_reporter(|msg| error!(msg = %msg.to_string_lossy(), "LLVM error"))
925 }
926
927 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#[derive(Clone, Copy)]
947pub struct JITDylibRef {
948 dylib: NonNull<LLVMOrcOpaqueJITDylib>,
949}
950
951impl JITDylibRef {
952 pub unsafe fn from_inner(dylib: LLVMOrcJITDylibRef) -> Option<Self> {
954 NonNull::new(dylib).map(|dylib| Self { dylib })
955 }
956
957 pub unsafe fn from_inner_unchecked(dylib: LLVMOrcJITDylibRef) -> Self {
959 Self { dylib: NonNull::new_unchecked(dylib) }
960 }
961
962 pub fn as_inner(self) -> LLVMOrcJITDylibRef {
964 self.dylib.as_ptr()
965 }
966
967 pub fn create_resource_tracker(self) -> ResourceTracker {
969 unsafe {
970 ResourceTracker::from_inner(LLVMOrcJITDylibCreateResourceTracker(self.as_inner()))
971 }
972 }
973
974 pub fn get_default_resource_tracker(self) -> ResourceTracker {
976 unsafe {
977 ResourceTracker::from_inner(LLVMOrcJITDylibGetDefaultResourceTracker(self.as_inner()))
978 }
979 }
980
981 pub fn define(self, mu: MaterializationUnit) -> Result<(), (LLVMString, MaterializationUnit)> {
983 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 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 pub fn clear(self) -> Result<(), LLVMString> {
1002 cvt(unsafe { LLVMOrcJITDylibClear(self.as_inner()) })
1003 }
1004
1005 pub fn add_generator(self, dg: DefinitionGenerator) {
1007 let dg = mem::ManuallyDrop::new(dg);
1010 unsafe { LLVMOrcJITDylibAddGenerator(self.as_inner(), dg.as_inner()) };
1011 }
1012}
1013
1014pub struct DefinitionGenerator {
1016 dg: LLVMOrcDefinitionGeneratorRef,
1017}
1018
1019impl DefinitionGenerator {
1020 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 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 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 pub unsafe fn from_inner(dg: LLVMOrcDefinitionGeneratorRef) -> Self {
1089 Self { dg }
1090 }
1091
1092 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
1104pub trait CustomDefinitionGenerator {
1106 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
1172pub struct JITTargetMachineBuilder {
1174 builder: LLVMOrcJITTargetMachineBuilderRef,
1175}
1176
1177impl JITTargetMachineBuilder {
1178 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 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 pub unsafe fn from_inner(builder: LLVMOrcJITTargetMachineBuilderRef) -> Self {
1195 Self { builder }
1196 }
1197
1198 pub fn as_inner(&self) -> LLVMOrcJITTargetMachineBuilderRef {
1200 self.builder
1201 }
1202
1203 pub fn get_target_triple(&self) -> LLVMString {
1205 unsafe { llvm_string(LLVMOrcJITTargetMachineBuilderGetTargetTriple(self.as_inner())) }
1206 }
1207
1208 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#[must_use]
1222pub struct LLJITBuilder {
1223 builder: lljit::LLVMOrcLLJITBuilderRef,
1224}
1225
1226impl LLJITBuilder {
1227 pub fn new() -> Self {
1229 Self { builder: ptr::null_mut() }
1230 }
1231
1232 pub unsafe fn from_inner(builder: LLVMOrcLLJITBuilderRef) -> Self {
1234 Self { builder }
1235 }
1236
1237 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 pub fn set_target_machine(self, tm: TargetMachine) -> Self {
1251 self.set_target_machine_builder(JITTargetMachineBuilder::new(tm))
1252 }
1253
1254 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 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 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 pub fn build(self) -> Result<LLJIT, LLVMString> {
1302 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
1320pub 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 pub fn builder() -> LLJITBuilder {
1338 LLJITBuilder::new()
1339 }
1340
1341 pub fn new() -> Result<Self, LLVMString> {
1343 LLJITBuilder::new().build()
1344 }
1345
1346 pub unsafe fn from_inner(jit: LLVMOrcLLJITRef) -> Self {
1348 Self { jit }
1349 }
1350
1351 pub fn as_inner(&self) -> LLVMOrcLLJITRef {
1353 self.jit
1354 }
1355
1356 pub fn get_triple_string(&self) -> &CStr {
1358 unsafe { CStr::from_ptr(LLVMOrcLLJITGetTripleString(self.jit)) }
1360 }
1361
1362 pub fn get_data_layout_string(&self) -> &CStr {
1364 unsafe { CStr::from_ptr(LLVMOrcLLJITGetDataLayoutStr(self.jit)) }
1366 }
1367
1368 pub fn get_global_prefix(&self) -> c_char {
1370 unsafe { LLVMOrcLLJITGetGlobalPrefix(self.jit) }
1371 }
1372
1373 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 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 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 pub fn get_execution_session(&self) -> ExecutionSessionRef<'_> {
1403 unsafe { ExecutionSessionRef::from_inner(LLVMOrcLLJITGetExecutionSession(self.as_inner())) }
1404 }
1405
1406 pub fn get_main_jit_dylib(&self) -> JITDylibRef {
1408 unsafe { JITDylibRef::from_inner_unchecked(LLVMOrcLLJITGetMainJITDylib(self.as_inner())) }
1409 }
1410
1411 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 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 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 pub fn get_ir_transform_layer(&self) -> IRTransformLayerRef {
1452 unsafe { IRTransformLayerRef::from_inner(LLVMOrcLLJITGetIRTransformLayer(self.as_inner())) }
1453 }
1454
1455 pub fn get_obj_transform_layer(&self) -> ObjectTransformLayerRef {
1457 unsafe {
1458 ObjectTransformLayerRef::from_inner(LLVMOrcLLJITGetObjTransformLayer(self.as_inner()))
1459 }
1460 }
1461
1462 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 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 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
1509pub struct ObjectLayerRef {
1511 ptr: LLVMOrcObjectLayerRef,
1512}
1513
1514impl ObjectLayerRef {
1515 pub unsafe fn from_inner(ptr: LLVMOrcObjectLayerRef) -> Self {
1517 Self { ptr }
1518 }
1519
1520 pub fn as_inner(&self) -> LLVMOrcObjectLayerRef {
1522 self.ptr
1523 }
1524}
1525
1526type ObjTransformFn = fn(&[u8]) -> Result<Option<Vec<u8>>, String>;
1528
1529pub struct ObjectTransformLayerRef {
1534 ptr: LLVMOrcObjectTransformLayerRef,
1535}
1536
1537impl ObjectTransformLayerRef {
1538 pub unsafe fn from_inner(ptr: LLVMOrcObjectTransformLayerRef) -> Self {
1540 Self { ptr }
1541 }
1542
1543 pub fn as_inner(&self) -> LLVMOrcObjectTransformLayerRef {
1545 self.ptr
1546 }
1547
1548 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 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
1600pub struct IRTransformLayerRef {
1602 ptr: LLVMOrcIRTransformLayerRef,
1603}
1604
1605impl IRTransformLayerRef {
1606 pub unsafe fn from_inner(ptr: LLVMOrcIRTransformLayerRef) -> Self {
1608 Self { ptr }
1609 }
1610
1611 pub fn as_inner(&self) -> LLVMOrcIRTransformLayerRef {
1613 self.ptr
1614 }
1615
1616 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 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
1648unsafe 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
1686pub(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(); }
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
1720struct 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 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 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 let tsm = tscx.create_module(m);
1847 jit.add_module(tsm).unwrap();
1848
1849 let address = jit.lookup(&CString::new(fn_name).unwrap()).unwrap();
1851 eprintln!("address: {address:#x}");
1852 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 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 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 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}