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::{
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
47pub 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 pub fn new() -> Self {
65 unsafe { Self::from_inner(LLVMOrcCreateNewThreadSafeContext()) }
66 }
67
68 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 pub unsafe fn from_inner(ctx: LLVMOrcThreadSafeContextRef) -> Self {
76 Self { ctx }
77 }
78
79 pub fn as_inner(&self) -> LLVMOrcThreadSafeContextRef {
81 self.ctx
82 }
83
84 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
96pub struct ThreadSafeModule {
104 ptr: LLVMOrcThreadSafeModuleRef,
105}
106
107impl ThreadSafeModule {
108 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 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 pub unsafe fn from_inner(ptr: LLVMOrcThreadSafeModuleRef) -> Self {
132 Self { ptr }
133 }
134
135 pub fn as_inner(&self) -> LLVMOrcThreadSafeModuleRef {
137 self.ptr
138 }
139
140 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#[repr(C)]
168pub struct SymbolStringPoolRef {
169 ptr: LLVMOrcSymbolStringPoolRef,
170}
171
172impl SymbolStringPoolRef {
173 pub unsafe fn from_inner(ptr: LLVMOrcSymbolStringPoolRef) -> Self {
175 Self { ptr }
176 }
177
178 pub fn as_inner(&self) -> LLVMOrcSymbolStringPoolRef {
180 self.ptr
181 }
182
183 pub fn clear_dead_entries(&self) {
192 unsafe { LLVMOrcSymbolStringPoolClearDeadEntries(self.as_inner()) };
193 }
194}
195
196#[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 pub unsafe fn from_inner(ptr: LLVMOrcSymbolStringPoolEntryRef) -> Option<Self> {
227 NonNull::new(ptr).map(|ptr| Self { ptr })
228 }
229
230 pub unsafe fn from_inner_unchecked(ptr: LLVMOrcSymbolStringPoolEntryRef) -> Self {
232 Self { ptr: NonNull::new_unchecked(ptr) }
233 }
234
235 pub fn as_inner(&self) -> LLVMOrcSymbolStringPoolEntryRef {
237 self.ptr.as_ptr()
238 }
239
240 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#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
254#[repr(C)]
255pub struct EvaluatedSymbol {
256 pub address: u64,
258 pub flags: SymbolFlags,
260}
261
262impl EvaluatedSymbol {
263 pub fn new(address: u64, flags: SymbolFlags) -> Self {
265 Self { address, flags }
266 }
267
268 pub fn from_flags(flags: SymbolFlags) -> Self {
270 Self { address: 0, flags }
271 }
272
273 pub fn from_address(address: usize) -> Self {
275 Self { address: address as u64, flags: SymbolFlags::none() }
276 }
277}
278
279#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
281#[repr(C)]
282pub struct SymbolFlags {
283 pub generic: u8,
285 pub target: u8,
287}
288
289impl Default for SymbolFlags {
290 fn default() -> Self {
291 Self::none()
292 }
293}
294
295impl SymbolFlags {
296 pub fn none() -> Self {
298 Self { generic: LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsNone as u8, target: 0 }
299 }
300
301 pub fn set_exported(&mut self) {
303 self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsExported as u8;
304 }
305
306 pub fn exported(mut self) -> Self {
308 self.set_exported();
309 self
310 }
311
312 pub fn is_exported(&self) -> bool {
314 (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsExported as u8) != 0
315 }
316
317 pub fn set_weak(&mut self) {
319 self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsWeak as u8;
320 }
321
322 pub fn weak(mut self) -> Self {
324 self.set_weak();
325 self
326 }
327
328 pub fn is_weak(&self) -> bool {
330 (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsWeak as u8) != 0
331 }
332
333 pub fn set_callable(&mut self) {
335 self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsCallable as u8;
336 }
337
338 pub fn callable(mut self) -> Self {
340 self.set_callable();
341 self
342 }
343
344 pub fn is_callable(&self) -> bool {
346 (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsCallable as u8) != 0
347 }
348
349 pub fn set_materialization_side_effects_only(&mut self) {
351 self.generic |=
352 LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly
353 as u8;
354 }
355
356 pub fn materialization_side_effects_only(mut self) -> Self {
358 self.set_materialization_side_effects_only();
359 self
360 }
361
362 pub fn is_materialization_side_effects_only(&self) -> bool {
364 (self.generic
365 & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly
366 as u8)
367 != 0
368 }
369
370 pub fn set_generic(&mut self, flag: LLVMJITSymbolGenericFlags) {
372 self.generic |= flag as u8;
373 }
374
375 pub fn with_generic(mut self, flag: LLVMJITSymbolGenericFlags) -> Self {
377 self.set_generic(flag);
378 self
379 }
380
381 pub fn set_target(&mut self, flag: LLVMJITSymbolTargetFlags) {
383 self.target |= flag;
384 }
385
386 pub fn with_target(mut self, flag: LLVMJITSymbolTargetFlags) -> Self {
388 self.set_target(flag);
389 self
390 }
391}
392
393#[derive(Clone, Debug, PartialEq, Eq, Hash)]
395#[repr(C)]
396pub struct SymbolFlagsMapPair {
397 pub name: SymbolStringPoolEntry,
399 pub flags: SymbolFlags,
401}
402
403impl SymbolFlagsMapPair {
404 pub fn new(name: SymbolStringPoolEntry, flags: SymbolFlags) -> Self {
406 Self { name, flags }
407 }
408}
409
410#[derive(Clone, Debug, PartialEq, Eq, Hash)]
412#[repr(C)]
413pub struct SymbolMapPair {
414 pub name: SymbolStringPoolEntry,
416 pub evaluated_symbol: EvaluatedSymbol,
418}
419
420impl SymbolMapPair {
421 pub fn new(name: SymbolStringPoolEntry, evaluated_symbol: EvaluatedSymbol) -> Self {
423 Self { name, evaluated_symbol }
424 }
425}
426
427pub struct SymbolFlagsMapPairs<'a>(&'a [SymbolFlagsMapPair]);
431
432impl<'a> SymbolFlagsMapPairs<'a> {
433 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
453pub 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 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 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 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 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 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 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 pub unsafe fn absolute_symbols_raw(syms: LLVMOrcCSymbolMapPairs, len: usize) -> Self {
573 unsafe { Self::from_inner(LLVMOrcAbsoluteSymbols(syms, len)) }
574 }
575
576 pub unsafe fn from_inner(mu: LLVMOrcMaterializationUnitRef) -> Self {
580 Self { mu }
581 }
582
583 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
595pub trait CustomMaterializationUnit {
599 fn materialize(self: Box<Self>, mr: MaterializationResponsibility);
601
602 fn discard(&mut self, jd: JITDylibRef, symbol: &SymbolStringPoolEntry);
604
605 }
607
608pub struct MaterializationResponsibility {
610 mr: LLVMOrcMaterializationResponsibilityRef,
611}
612
613impl MaterializationResponsibility {
614 pub unsafe fn from_inner(mr: LLVMOrcMaterializationResponsibilityRef) -> Self {
616 Self { mr }
617 }
618
619 pub fn as_inner(&self) -> LLVMOrcMaterializationResponsibilityRef {
621 self.mr
622 }
623
624 #[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
637pub struct MaterializationResponsibilityRef<'mr> {
639 mr: LLVMOrcMaterializationResponsibilityRef,
640 _marker: PhantomData<&'mr ()>,
641}
642
643impl<'mr> MaterializationResponsibilityRef<'mr> {
644 pub unsafe fn from_inner(mr: LLVMOrcMaterializationResponsibilityRef) -> Self {
646 Self { mr, _marker: PhantomData }
647 }
648
649 pub fn as_inner(&self) -> LLVMOrcMaterializationResponsibilityRef {
651 self.mr
652 }
653
654 pub fn get_target_dylib(&self) -> JITDylibRef {
656 unsafe {
657 JITDylibRef::from_inner_unchecked(LLVMOrcMaterializationResponsibilityGetTargetDylib(
658 self.as_inner(),
659 ))
660 }
661 }
662
663 pub fn get_execution_session(&self) -> ExecutionSessionRef<'mr> {
665 unsafe {
666 ExecutionSessionRef::from_inner(
667 LLVMOrcMaterializationResponsibilityGetExecutionSession(self.as_inner()),
668 )
669 }
670 }
671
672 pub fn get_symbols(&self) -> SymbolFlagsMapPairs<'mr> {
674 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 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 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 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 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 pub fn fail_materialization(&self) {
751 unsafe { LLVMOrcMaterializationResponsibilityFailMaterialization(self.as_inner()) };
752 }
753
754 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 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
785pub 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 pub unsafe fn from_inner(rt: LLVMOrcResourceTrackerRef) -> Self {
801 Self { rt }
802 }
803
804 pub fn as_inner(&self) -> LLVMOrcResourceTrackerRef {
806 self.rt
807 }
808
809 pub fn remove(&self) -> Result<(), LLVMString> {
811 cvt(unsafe { LLVMOrcResourceTrackerRemove(self.as_inner()) })
812 }
813
814 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
827pub struct ExecutionSessionRef<'ee> {
837 es: LLVMOrcExecutionSessionRef,
838 _marker: PhantomData<&'ee ()>,
839}
840
841impl ExecutionSessionRef<'_> {
842 pub unsafe fn from_inner(es: LLVMOrcExecutionSessionRef) -> Self {
844 Self { es, _marker: PhantomData }
845 }
846
847 pub fn as_inner(&self) -> LLVMOrcExecutionSessionRef {
849 self.es
850 }
851
852 pub fn get_symbol_string_pool(&self) -> SymbolStringPoolRef {
854 unsafe {
855 SymbolStringPoolRef::from_inner(LLVMOrcExecutionSessionGetSymbolStringPool(
856 self.as_inner(),
857 ))
858 }
859 }
860
861 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 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 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 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 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 pub fn set_default_error_reporter(&self) {
927 self.set_error_reporter(|msg| error!(msg = %msg.to_string_lossy(), "LLVM error"))
928 }
929
930 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#[derive(Clone, Copy)]
950pub struct JITDylibRef {
951 dylib: NonNull<LLVMOrcOpaqueJITDylib>,
952}
953
954impl JITDylibRef {
955 pub unsafe fn from_inner(dylib: LLVMOrcJITDylibRef) -> Option<Self> {
957 NonNull::new(dylib).map(|dylib| Self { dylib })
958 }
959
960 pub unsafe fn from_inner_unchecked(dylib: LLVMOrcJITDylibRef) -> Self {
962 Self { dylib: NonNull::new_unchecked(dylib) }
963 }
964
965 pub fn as_inner(self) -> LLVMOrcJITDylibRef {
967 self.dylib.as_ptr()
968 }
969
970 pub fn create_resource_tracker(self) -> ResourceTracker {
972 unsafe {
973 ResourceTracker::from_inner(LLVMOrcJITDylibCreateResourceTracker(self.as_inner()))
974 }
975 }
976
977 pub fn get_default_resource_tracker(self) -> ResourceTracker {
979 unsafe {
980 ResourceTracker::from_inner(LLVMOrcJITDylibGetDefaultResourceTracker(self.as_inner()))
981 }
982 }
983
984 pub fn define(self, mu: MaterializationUnit) -> Result<(), (LLVMString, MaterializationUnit)> {
986 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 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 pub fn clear(self) -> Result<(), LLVMString> {
1005 cvt(unsafe { LLVMOrcJITDylibClear(self.as_inner()) })
1006 }
1007
1008 pub fn add_generator(self, dg: DefinitionGenerator) {
1010 let dg = mem::ManuallyDrop::new(dg);
1013 unsafe { LLVMOrcJITDylibAddGenerator(self.as_inner(), dg.as_inner()) };
1014 }
1015}
1016
1017pub struct DefinitionGenerator {
1019 dg: LLVMOrcDefinitionGeneratorRef,
1020}
1021
1022impl DefinitionGenerator {
1023 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 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 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 pub unsafe fn from_inner(dg: LLVMOrcDefinitionGeneratorRef) -> Self {
1092 Self { dg }
1093 }
1094
1095 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
1107pub trait CustomDefinitionGenerator {
1109 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
1175pub struct JITTargetMachineBuilder {
1177 builder: LLVMOrcJITTargetMachineBuilderRef,
1178}
1179
1180impl JITTargetMachineBuilder {
1181 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 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 pub unsafe fn from_inner(builder: LLVMOrcJITTargetMachineBuilderRef) -> Self {
1198 Self { builder }
1199 }
1200
1201 pub fn as_inner(&self) -> LLVMOrcJITTargetMachineBuilderRef {
1203 self.builder
1204 }
1205
1206 pub fn get_target_triple(&self) -> LLVMString {
1208 unsafe { llvm_string(LLVMOrcJITTargetMachineBuilderGetTargetTriple(self.as_inner())) }
1209 }
1210
1211 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#[must_use]
1225pub struct LLJITBuilder {
1226 builder: lljit::LLVMOrcLLJITBuilderRef,
1227}
1228
1229impl LLJITBuilder {
1230 pub fn new() -> Self {
1232 Self { builder: ptr::null_mut() }
1233 }
1234
1235 pub unsafe fn from_inner(builder: LLVMOrcLLJITBuilderRef) -> Self {
1237 Self { builder }
1238 }
1239
1240 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 pub fn set_target_machine(self, tm: TargetMachine) -> Self {
1254 self.set_target_machine_builder(JITTargetMachineBuilder::new(tm))
1255 }
1256
1257 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 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 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 pub fn build(self) -> Result<LLJIT, LLVMString> {
1305 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
1323pub 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 pub fn builder() -> LLJITBuilder {
1341 LLJITBuilder::new()
1342 }
1343
1344 pub fn new() -> Result<Self, LLVMString> {
1346 LLJITBuilder::new().build()
1347 }
1348
1349 pub unsafe fn from_inner(jit: LLVMOrcLLJITRef) -> Self {
1351 Self { jit }
1352 }
1353
1354 pub fn as_inner(&self) -> LLVMOrcLLJITRef {
1356 self.jit
1357 }
1358
1359 pub fn get_triple_string(&self) -> &CStr {
1361 unsafe { CStr::from_ptr(LLVMOrcLLJITGetTripleString(self.jit)) }
1363 }
1364
1365 pub fn get_data_layout_string(&self) -> &CStr {
1367 unsafe { CStr::from_ptr(LLVMOrcLLJITGetDataLayoutStr(self.jit)) }
1369 }
1370
1371 pub fn get_global_prefix(&self) -> c_char {
1373 unsafe { LLVMOrcLLJITGetGlobalPrefix(self.jit) }
1374 }
1375
1376 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 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 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 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 pub fn get_execution_session(&self) -> ExecutionSessionRef<'_> {
1423 unsafe { ExecutionSessionRef::from_inner(LLVMOrcLLJITGetExecutionSession(self.as_inner())) }
1424 }
1425
1426 pub fn get_main_jit_dylib(&self) -> JITDylibRef {
1428 unsafe { JITDylibRef::from_inner_unchecked(LLVMOrcLLJITGetMainJITDylib(self.as_inner())) }
1429 }
1430
1431 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 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 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 pub fn get_ir_transform_layer(&self) -> IRTransformLayerRef {
1472 unsafe { IRTransformLayerRef::from_inner(LLVMOrcLLJITGetIRTransformLayer(self.as_inner())) }
1473 }
1474
1475 pub fn get_obj_transform_layer(&self) -> ObjectTransformLayerRef {
1477 unsafe {
1478 ObjectTransformLayerRef::from_inner(LLVMOrcLLJITGetObjTransformLayer(self.as_inner()))
1479 }
1480 }
1481
1482 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 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 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
1529pub struct ObjectLayerRef {
1531 ptr: LLVMOrcObjectLayerRef,
1532}
1533
1534impl ObjectLayerRef {
1535 pub unsafe fn from_inner(ptr: LLVMOrcObjectLayerRef) -> Self {
1537 Self { ptr }
1538 }
1539
1540 pub fn as_inner(&self) -> LLVMOrcObjectLayerRef {
1542 self.ptr
1543 }
1544}
1545
1546type ObjTransformFn = fn(&[u8]) -> Result<Option<Vec<u8>>, String>;
1548
1549pub struct ObjectTransformLayerRef {
1554 ptr: LLVMOrcObjectTransformLayerRef,
1555}
1556
1557impl ObjectTransformLayerRef {
1558 pub unsafe fn from_inner(ptr: LLVMOrcObjectTransformLayerRef) -> Self {
1560 Self { ptr }
1561 }
1562
1563 pub fn as_inner(&self) -> LLVMOrcObjectTransformLayerRef {
1565 self.ptr
1566 }
1567
1568 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 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
1620pub struct IRTransformLayerRef {
1622 ptr: LLVMOrcIRTransformLayerRef,
1623}
1624
1625impl IRTransformLayerRef {
1626 pub unsafe fn from_inner(ptr: LLVMOrcIRTransformLayerRef) -> Self {
1628 Self { ptr }
1629 }
1630
1631 pub fn as_inner(&self) -> LLVMOrcIRTransformLayerRef {
1633 self.ptr
1634 }
1635
1636 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 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
1668unsafe 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
1706pub(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(); }
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
1740struct 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 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 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 let tsm = tscx.create_module(m);
1867 jit.add_module(tsm).unwrap();
1868
1869 let address = jit.lookup(&CString::new(fn_name).unwrap()).unwrap();
1871 eprintln!("address: {address:#x}");
1872 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 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 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 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}