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 llvm_sys::{
19 core::{LLVMContextCreate, LLVMModuleCreateWithNameInContext},
20 error::*,
21 orc2::{lljit::*, *},
22 prelude::*,
23 },
24 module::Module,
25 support::LLVMString,
26 targets::TargetMachine,
27};
28use std::{
29 ffi::{c_char, c_void, CStr, CString},
30 fmt,
31 marker::PhantomData,
32 mem::{self, MaybeUninit},
33 panic::AssertUnwindSafe,
34 ptr::{self, NonNull},
35};
36
37pub struct ThreadSafeContext {
43 ctx: LLVMOrcThreadSafeContextRef,
44}
45
46impl ThreadSafeContext {
47 pub fn new() -> Self {
49 unsafe { Self::from_inner(LLVMOrcCreateNewThreadSafeContext()) }
50 }
51
52 pub unsafe fn from_inner(ctx: LLVMOrcThreadSafeContextRef) -> Self {
54 Self { ctx }
55 }
56
57 pub fn as_inner(&self) -> LLVMOrcThreadSafeContextRef {
59 self.ctx
60 }
61
62 pub fn create_module<'ctx>(&'ctx self, module: Module<'ctx>) -> ThreadSafeModule {
64 ThreadSafeModule::create_in_context(module, self)
65 }
66}
67
68unsafe impl Send for ThreadSafeContext {}
69
70impl Drop for ThreadSafeContext {
71 fn drop(&mut self) {
72 unsafe { LLVMOrcDisposeThreadSafeContext(self.ctx) };
73 }
74}
75
76pub struct ThreadSafeModule {
84 ptr: LLVMOrcThreadSafeModuleRef,
85}
86
87extern "C" {
88 fn LLVMOrcCreateNewThreadSafeContextFromLLVMContext(
89 Ctx: LLVMContextRef,
90 ) -> LLVMOrcThreadSafeContextRef;
91}
92
93impl ThreadSafeModule {
94 pub fn create(name: &str) -> Self {
98 let name_cstr = CString::new(name).unwrap();
99 unsafe {
100 let ctx = LLVMContextCreate();
101 let module = LLVMModuleCreateWithNameInContext(name_cstr.as_ptr(), ctx);
102 let tsc = LLVMOrcCreateNewThreadSafeContextFromLLVMContext(ctx);
103 let ptr = LLVMOrcCreateNewThreadSafeModule(module, tsc);
104 LLVMOrcDisposeThreadSafeContext(tsc);
105 Self { ptr }
106 }
107 }
108
109 pub fn create_in_context<'ctx>(module: Module<'ctx>, ctx: &'ctx ThreadSafeContext) -> Self {
111 let module = mem::ManuallyDrop::new(module);
112 let ptr = unsafe { LLVMOrcCreateNewThreadSafeModule(module.as_mut_ptr(), ctx.as_inner()) };
113 Self { ptr }
114 }
115
116 pub unsafe fn from_inner(ptr: LLVMOrcThreadSafeModuleRef) -> Self {
118 Self { ptr }
119 }
120
121 pub fn as_inner(&self) -> LLVMOrcThreadSafeModuleRef {
123 self.ptr
124 }
125
126 pub fn with_module<'tsm>(
130 &'tsm self,
131 mut f: impl FnMut(&Module<'tsm>) -> Result<(), String>,
132 ) -> Result<(), LLVMString> {
133 extern "C" fn shim(ctx: *mut c_void, m: LLVMModuleRef) -> LLVMErrorRef {
134 let f = ctx.cast::<&mut dyn FnMut(&Module<'_>) -> Result<(), String>>();
135 let m = mem::ManuallyDrop::new(unsafe { Module::new(m) });
136 let res = std::panic::catch_unwind(AssertUnwindSafe(|| unsafe { (*f)(&m) }));
137 cvt_cb_res(res)
138 }
139
140 let mut f = &mut f as &mut dyn FnMut(&Module<'tsm>) -> Result<(), String>;
141 let ctx = &mut f as *mut _ as *mut c_void;
142 cvt(unsafe { LLVMOrcThreadSafeModuleWithModuleDo(self.as_inner(), shim, ctx) })
143 }
144}
145
146unsafe impl Send for ThreadSafeModule {}
147
148impl Drop for ThreadSafeModule {
149 fn drop(&mut self) {
150 unsafe { LLVMOrcDisposeThreadSafeModule(self.ptr) };
151 }
152}
153
154#[repr(C)]
156pub struct SymbolStringPoolRef {
157 ptr: LLVMOrcSymbolStringPoolRef,
158}
159
160impl SymbolStringPoolRef {
161 pub unsafe fn from_inner(ptr: LLVMOrcSymbolStringPoolRef) -> Self {
163 Self { ptr }
164 }
165
166 pub fn as_inner(&self) -> LLVMOrcSymbolStringPoolRef {
168 self.ptr
169 }
170
171 pub fn clear_dead_entries(&self) {
180 unsafe { LLVMOrcSymbolStringPoolClearDeadEntries(self.as_inner()) };
181 }
182}
183
184#[derive(PartialEq, Eq, Hash)]
186#[repr(C)]
187pub struct SymbolStringPoolEntry {
188 ptr: NonNull<LLVMOrcOpaqueSymbolStringPoolEntry>,
189}
190
191impl Clone for SymbolStringPoolEntry {
192 fn clone(&self) -> Self {
193 unsafe { LLVMOrcRetainSymbolStringPoolEntry(self.as_inner()) };
194 Self { ..*self }
195 }
196}
197
198impl fmt::Debug for SymbolStringPoolEntry {
199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200 self.as_cstr().fmt(f)
201 }
202}
203
204impl std::ops::Deref for SymbolStringPoolEntry {
205 type Target = CStr;
206
207 fn deref(&self) -> &Self::Target {
208 self.as_cstr()
209 }
210}
211
212impl SymbolStringPoolEntry {
213 pub unsafe fn from_inner(ptr: LLVMOrcSymbolStringPoolEntryRef) -> Option<Self> {
215 NonNull::new(ptr).map(|ptr| Self { ptr })
216 }
217
218 pub unsafe fn from_inner_unchecked(ptr: LLVMOrcSymbolStringPoolEntryRef) -> Self {
220 Self { ptr: NonNull::new_unchecked(ptr) }
221 }
222
223 pub fn as_inner(&self) -> LLVMOrcSymbolStringPoolEntryRef {
225 self.ptr.as_ptr()
226 }
227
228 pub fn as_cstr(&self) -> &CStr {
230 unsafe { CStr::from_ptr(LLVMOrcSymbolStringPoolEntryStr(self.as_inner())) }
231 }
232}
233
234impl Drop for SymbolStringPoolEntry {
235 fn drop(&mut self) {
236 unsafe { LLVMOrcReleaseSymbolStringPoolEntry(self.as_inner()) }
237 }
238}
239
240#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
242#[repr(C)]
243pub struct EvaluatedSymbol {
244 pub address: u64,
246 pub flags: SymbolFlags,
248}
249
250impl EvaluatedSymbol {
251 pub fn new(address: u64, flags: SymbolFlags) -> Self {
253 Self { address, flags }
254 }
255
256 pub fn from_flags(flags: SymbolFlags) -> Self {
258 Self { address: 0, flags }
259 }
260
261 pub fn from_address(address: usize) -> Self {
263 Self { address: address as u64, flags: SymbolFlags::none() }
264 }
265}
266
267#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
269#[repr(C)]
270pub struct SymbolFlags {
271 pub generic: u8,
273 pub target: u8,
275}
276
277impl SymbolFlags {
278 pub fn none() -> Self {
280 Self { generic: LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsNone as u8, target: 0 }
281 }
282
283 pub fn set_exported(&mut self) {
285 self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsExported as u8;
286 }
287
288 pub fn with_exported(mut self) -> Self {
290 self.set_exported();
291 self
292 }
293
294 pub fn is_exported(&self) -> bool {
296 (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsExported as u8) != 0
297 }
298
299 pub fn set_weak(&mut self) {
301 self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsWeak as u8;
302 }
303
304 pub fn weak(mut self) -> Self {
306 self.set_weak();
307 self
308 }
309
310 pub fn is_weak(&self) -> bool {
312 (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsWeak as u8) != 0
313 }
314
315 pub fn set_callable(&mut self) {
317 self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsCallable as u8;
318 }
319
320 pub fn callable(mut self) -> Self {
322 self.set_callable();
323 self
324 }
325
326 pub fn is_callable(&self) -> bool {
328 (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsCallable as u8) != 0
329 }
330
331 pub fn set_materialization_side_effects_only(&mut self) {
333 self.generic |=
334 LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly
335 as u8;
336 }
337
338 pub fn materialization_side_effects_only(mut self) -> Self {
340 self.set_materialization_side_effects_only();
341 self
342 }
343
344 pub fn is_materialization_side_effects_only(&self) -> bool {
346 (self.generic
347 & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly
348 as u8)
349 != 0
350 }
351
352 pub fn set_generic(&mut self, flag: LLVMJITSymbolGenericFlags) {
354 self.generic |= flag as u8;
355 }
356
357 pub fn with_generic(mut self, flag: LLVMJITSymbolGenericFlags) -> Self {
359 self.set_generic(flag);
360 self
361 }
362
363 pub fn set_target(&mut self, flag: LLVMJITSymbolTargetFlags) {
365 self.target |= flag;
366 }
367
368 pub fn with_target(mut self, flag: LLVMJITSymbolTargetFlags) -> Self {
370 self.set_target(flag);
371 self
372 }
373}
374
375#[derive(Clone, Debug, PartialEq, Eq, Hash)]
377#[repr(C)]
378pub struct SymbolFlagsMapPair {
379 pub name: SymbolStringPoolEntry,
381 pub flags: SymbolFlags,
383}
384
385impl SymbolFlagsMapPair {
386 pub fn new(name: SymbolStringPoolEntry, flags: SymbolFlags) -> Self {
388 Self { name, flags }
389 }
390}
391
392#[derive(Clone, Debug, PartialEq, Eq, Hash)]
394#[repr(C)]
395pub struct SymbolMapPair {
396 pub name: SymbolStringPoolEntry,
398 pub evaluated_symbol: EvaluatedSymbol,
400}
401
402impl SymbolMapPair {
403 pub fn new(name: SymbolStringPoolEntry, evaluated_symbol: EvaluatedSymbol) -> Self {
405 Self { name, evaluated_symbol }
406 }
407}
408
409pub struct SymbolFlagsMapPairs<'a>(&'a [SymbolFlagsMapPair]);
413
414impl<'a> SymbolFlagsMapPairs<'a> {
415 pub fn as_slice(&self) -> &'a [SymbolFlagsMapPair] {
417 self.0
418 }
419}
420
421impl std::ops::Deref for SymbolFlagsMapPairs<'_> {
422 type Target = [SymbolFlagsMapPair];
423
424 fn deref(&self) -> &Self::Target {
425 self.0
426 }
427}
428
429impl Drop for SymbolFlagsMapPairs<'_> {
430 fn drop(&mut self) {
431 unsafe { LLVMOrcDisposeCSymbolFlagsMap(self.0.as_ptr().cast_mut().cast()) };
432 }
433}
434
435pub struct MaterializationUnit {
437 mu: LLVMOrcMaterializationUnitRef,
438}
439
440impl MaterializationUnit {
441 pub fn new_custom(
443 name: &CStr,
444 syms: Vec<SymbolFlagsMapPair>,
445 init_sym: Option<SymbolStringPoolEntry>,
446 mu: Box<dyn CustomMaterializationUnit>,
447 ) -> Self {
448 extern "C" fn materialize(ctx: *mut c_void, mr: LLVMOrcMaterializationResponsibilityRef) {
449 let ctx = unsafe { Box::from_raw(ctx.cast::<Box<dyn CustomMaterializationUnit>>()) };
455 let mr = unsafe { MaterializationResponsibility::from_inner(mr) };
456 let res = std::panic::catch_unwind(AssertUnwindSafe(move || ctx.materialize(mr)));
457 if let Err(e) = res {
458 error!(msg=?panic_payload(&e), "materialize callback panicked");
459 }
460 }
461
462 extern "C" fn discard(
463 ctx: *mut c_void,
464 jd: LLVMOrcJITDylibRef,
465 symbol: LLVMOrcSymbolStringPoolEntryRef,
466 ) {
467 let ctx = unsafe { &mut **ctx.cast::<Box<dyn CustomMaterializationUnit>>() };
470 let jd = unsafe { JITDylibRef::from_inner_unchecked(jd) };
471 let symbol = mem::ManuallyDrop::new(unsafe {
472 SymbolStringPoolEntry::from_inner_unchecked(symbol)
473 });
474 let res = std::panic::catch_unwind(AssertUnwindSafe(|| ctx.discard(jd, &symbol)));
475 if let Err(e) = res {
476 error!(msg=?panic_payload(&e), "discard callback panicked");
477 }
478 }
479
480 extern "C" fn destroy(ctx: *mut c_void) {
481 let ctx = unsafe { Box::from_raw(ctx.cast::<Box<dyn CustomMaterializationUnit>>()) };
485 let res = std::panic::catch_unwind(AssertUnwindSafe(|| drop(ctx)));
486 if let Err(e) = res {
487 error!(msg=?panic_payload(&e), "destroy callback panicked");
488 }
489 }
490
491 let ctx = Box::into_raw(Box::new(mu)).cast();
492 let init_sym = if let Some(init_sym) = init_sym {
493 mem::ManuallyDrop::new(init_sym).as_inner()
494 } else {
495 ptr::null_mut()
496 };
497 let syms = ManuallyDropElements::new(syms);
498 unsafe {
499 Self::new_custom_raw(
500 name,
501 ctx,
502 syms.as_ptr().cast_mut().cast(),
503 syms.len(),
504 init_sym,
505 materialize,
506 discard,
507 destroy,
508 )
509 }
510 }
511
512 pub unsafe fn new_custom_raw(
516 name: &CStr,
517 ctx: *mut c_void,
518 syms: LLVMOrcCSymbolFlagsMapPairs,
519 num_syms: usize,
520 init_sym: LLVMOrcSymbolStringPoolEntryRef,
521 materialize: LLVMOrcMaterializationUnitMaterializeFunction,
522 discard: LLVMOrcMaterializationUnitDiscardFunction,
523 destroy: LLVMOrcMaterializationUnitDestroyFunction,
524 ) -> Self {
525 Self::from_inner(LLVMOrcCreateCustomMaterializationUnit(
526 name.as_ptr(),
527 ctx,
528 syms,
529 num_syms,
530 init_sym,
531 materialize,
532 discard,
533 destroy,
534 ))
535 }
536
537 pub fn absolute_symbols(syms: Vec<SymbolMapPair>) -> Self {
540 let syms = ManuallyDropElements::new(syms);
541 unsafe { Self::absolute_symbols_raw(syms.as_ptr().cast_mut().cast(), syms.len()) }
542 }
543
544 pub unsafe fn absolute_symbols_raw(syms: LLVMOrcCSymbolMapPairs, len: usize) -> Self {
549 unsafe { Self::from_inner(LLVMOrcAbsoluteSymbols(syms, len)) }
550 }
551
552 pub unsafe fn from_inner(mu: LLVMOrcMaterializationUnitRef) -> Self {
556 Self { mu }
557 }
558
559 pub fn as_inner(&self) -> LLVMOrcMaterializationUnitRef {
561 self.mu
562 }
563}
564
565impl Drop for MaterializationUnit {
566 fn drop(&mut self) {
567 unsafe { LLVMOrcDisposeMaterializationUnit(self.as_inner()) };
568 }
569}
570
571pub trait CustomMaterializationUnit {
575 fn materialize(self: Box<Self>, mr: MaterializationResponsibility);
577
578 fn discard(&mut self, jd: JITDylibRef, symbol: &SymbolStringPoolEntry);
580
581 }
583
584pub struct MaterializationResponsibility {
586 mr: LLVMOrcMaterializationResponsibilityRef,
587}
588
589impl MaterializationResponsibility {
590 pub unsafe fn from_inner(mr: LLVMOrcMaterializationResponsibilityRef) -> Self {
592 Self { mr }
593 }
594
595 pub fn as_inner(&self) -> LLVMOrcMaterializationResponsibilityRef {
597 self.mr
598 }
599
600 #[inline]
602 pub fn as_ref(&self) -> MaterializationResponsibilityRef<'_> {
603 unsafe { MaterializationResponsibilityRef::from_inner(self.as_inner()) }
604 }
605}
606
607impl Drop for MaterializationResponsibility {
608 fn drop(&mut self) {
609 unsafe { LLVMOrcDisposeMaterializationResponsibility(self.as_inner()) };
610 }
611}
612
613pub struct MaterializationResponsibilityRef<'mr> {
615 mr: LLVMOrcMaterializationResponsibilityRef,
616 _marker: PhantomData<&'mr ()>,
617}
618
619impl<'mr> MaterializationResponsibilityRef<'mr> {
620 pub unsafe fn from_inner(mr: LLVMOrcMaterializationResponsibilityRef) -> Self {
622 Self { mr, _marker: PhantomData }
623 }
624
625 pub fn as_inner(&self) -> LLVMOrcMaterializationResponsibilityRef {
627 self.mr
628 }
629
630 pub fn get_target_dylib(&self) -> JITDylibRef {
632 unsafe {
633 JITDylibRef::from_inner_unchecked(LLVMOrcMaterializationResponsibilityGetTargetDylib(
634 self.as_inner(),
635 ))
636 }
637 }
638
639 pub fn get_execution_session(&self) -> ExecutionSessionRef<'mr> {
641 unsafe {
642 ExecutionSessionRef::from_inner(
643 LLVMOrcMaterializationResponsibilityGetExecutionSession(self.as_inner()),
644 )
645 }
646 }
647
648 pub fn get_symbols(&self) -> SymbolFlagsMapPairs<'mr> {
650 let mut len = MaybeUninit::uninit();
659 let data = unsafe {
660 LLVMOrcMaterializationResponsibilityGetSymbols(self.as_inner(), len.as_mut_ptr())
661 };
662 SymbolFlagsMapPairs(unsafe { std::slice::from_raw_parts(data.cast(), len.assume_init()) })
663 }
664
665 pub fn get_initializer_symbol(&self) -> Option<SymbolStringPoolEntry> {
670 let ptr =
671 unsafe { LLVMOrcMaterializationResponsibilityGetInitializerSymbol(self.as_inner()) };
672 unsafe { SymbolStringPoolEntry::from_inner(ptr) }
673 }
674
675 pub fn get_requested_symbols(&self) -> &[SymbolStringPoolEntry] {
681 let mut len = MaybeUninit::uninit();
682 let ptr = unsafe {
683 LLVMOrcMaterializationResponsibilityGetRequestedSymbols(
684 self.as_inner(),
685 len.as_mut_ptr(),
686 )
687 };
688 unsafe { std::slice::from_raw_parts(ptr.cast(), len.assume_init()) }
689 }
690
691 pub fn notify_resolved(&self, syms: &[SymbolFlagsMapPair]) -> Result<(), LLVMString> {
693 cvt(unsafe {
694 LLVMOrcMaterializationResponsibilityNotifyResolved(
695 self.as_inner(),
696 syms.as_ptr().cast_mut().cast(),
697 syms.len(),
698 )
699 })
700 }
701
702 pub fn notify_emitted(
709 &self,
710 symbol_dep_groups: &mut [LLVMOrcCSymbolDependenceGroup],
711 ) -> Result<(), LLVMString> {
712 cvt(unsafe {
713 LLVMOrcMaterializationResponsibilityNotifyEmitted(
714 self.as_inner(),
715 symbol_dep_groups.as_mut_ptr(),
716 symbol_dep_groups.len(),
717 )
718 })
719 }
720
721 pub fn fail_materialization(&self) {
727 unsafe { LLVMOrcMaterializationResponsibilityFailMaterialization(self.as_inner()) };
728 }
729
730 pub fn replace(&self, mu: MaterializationUnit) -> Result<(), LLVMString> {
737 let mu = mem::ManuallyDrop::new(mu);
738 cvt(unsafe { LLVMOrcMaterializationResponsibilityReplace(self.as_inner(), mu.as_inner()) })
739 }
740
741 pub fn delegate(&self, syms: &[SymbolStringPoolEntry]) -> Result<Self, LLVMString> {
748 let mut res = MaybeUninit::uninit();
749 cvt(unsafe {
750 LLVMOrcMaterializationResponsibilityDelegate(
751 self.as_inner(),
752 syms.as_ptr().cast_mut().cast(),
753 syms.len(),
754 res.as_mut_ptr(),
755 )
756 })?;
757 Ok(unsafe { Self::from_inner(res.assume_init()) })
758 }
759}
760
761pub struct ResourceTracker {
765 rt: LLVMOrcResourceTrackerRef,
766}
767
768impl ResourceTracker {
769 pub unsafe fn from_inner(rt: LLVMOrcResourceTrackerRef) -> Self {
771 Self { rt }
772 }
773
774 pub fn as_inner(&self) -> LLVMOrcResourceTrackerRef {
776 self.rt
777 }
778
779 pub fn remove(&self) -> Result<(), LLVMString> {
781 cvt(unsafe { LLVMOrcResourceTrackerRemove(self.as_inner()) })
782 }
783
784 pub fn transfer_to(&self, rt: &Self) {
787 unsafe { LLVMOrcResourceTrackerTransferTo(self.as_inner(), rt.as_inner()) };
788 }
789}
790
791impl Drop for ResourceTracker {
792 fn drop(&mut self) {
793 unsafe { LLVMOrcReleaseResourceTracker(self.as_inner()) };
794 }
795}
796
797pub struct ExecutionSessionRef<'ee> {
807 es: LLVMOrcExecutionSessionRef,
808 _marker: PhantomData<&'ee ()>,
809}
810
811impl ExecutionSessionRef<'_> {
812 pub unsafe fn from_inner(es: LLVMOrcExecutionSessionRef) -> Self {
814 Self { es, _marker: PhantomData }
815 }
816
817 pub fn as_inner(&self) -> LLVMOrcExecutionSessionRef {
819 self.es
820 }
821
822 pub fn intern(&self, name: &CStr) -> SymbolStringPoolEntry {
824 unsafe {
825 SymbolStringPoolEntry::from_inner_unchecked(LLVMOrcExecutionSessionIntern(
826 self.as_inner(),
827 name.as_ptr(),
828 ))
829 }
830 }
831
832 pub fn get_dylib_by_name(&self, name: &CStr) -> Option<JITDylibRef> {
834 unsafe {
835 let dylib = LLVMOrcExecutionSessionGetJITDylibByName(self.as_inner(), name.as_ptr());
836 JITDylibRef::from_inner(dylib)
837 }
838 }
839
840 pub fn create_bare_jit_dylib(&self, name: &CStr) -> JITDylibRef {
847 debug_assert!(self.get_dylib_by_name(name).is_none());
848 unsafe {
849 JITDylibRef::from_inner_unchecked(LLVMOrcExecutionSessionCreateBareJITDylib(
850 self.as_inner(),
851 name.as_ptr(),
852 ))
853 }
854 }
855
856 pub fn create_jit_dylib(&self, name: &CStr) -> Result<JITDylibRef, LLVMString> {
865 debug_assert!(self.get_dylib_by_name(name).is_none());
866 let mut res = MaybeUninit::uninit();
867 cvt(unsafe {
868 LLVMOrcExecutionSessionCreateJITDylib(self.as_inner(), res.as_mut_ptr(), name.as_ptr())
869 })?;
870 Ok(unsafe { JITDylibRef::from_inner_unchecked(res.assume_init()) })
871 }
872
873 pub fn set_default_error_reporter(&self) {
877 self.set_error_reporter(|msg| error!(msg = %msg.to_string_lossy(), "LLVM error"))
878 }
879
880 pub fn set_error_reporter(&self, f: fn(&CStr)) {
882 extern "C" fn shim(ctx: *mut c_void, err: LLVMErrorRef) {
883 let f = ctx as *mut fn(&CStr);
884 let Err(e) = cvt(err) else { return };
885 let res = std::panic::catch_unwind(AssertUnwindSafe(|| unsafe { (*f)(&e) }));
886 if let Err(e) = res {
887 error!(msg=?panic_payload(&e), "error reporter closure panicked");
888 }
889 }
890
891 let ctx = f as *mut c_void;
892 unsafe { LLVMOrcExecutionSessionSetErrorReporter(self.as_inner(), shim, ctx) };
893 }
894}
895
896pub struct JITDylibRef {
900 dylib: NonNull<LLVMOrcOpaqueJITDylib>,
901}
902
903impl JITDylibRef {
904 pub unsafe fn from_inner(dylib: LLVMOrcJITDylibRef) -> Option<Self> {
906 NonNull::new(dylib).map(|dylib| Self { dylib })
907 }
908
909 pub unsafe fn from_inner_unchecked(dylib: LLVMOrcJITDylibRef) -> Self {
911 Self { dylib: NonNull::new_unchecked(dylib) }
912 }
913
914 pub fn as_inner(&self) -> LLVMOrcJITDylibRef {
916 self.dylib.as_ptr()
917 }
918
919 pub fn create_resource_tracker(&self) -> ResourceTracker {
921 unsafe {
922 ResourceTracker::from_inner(LLVMOrcJITDylibCreateResourceTracker(self.as_inner()))
923 }
924 }
925
926 pub fn get_default_resource_tracker(&self) -> ResourceTracker {
928 unsafe {
929 ResourceTracker::from_inner(LLVMOrcJITDylibGetDefaultResourceTracker(self.as_inner()))
930 }
931 }
932
933 pub fn define(&self, mu: MaterializationUnit) -> Result<(), (LLVMString, MaterializationUnit)> {
935 cvt(unsafe { LLVMOrcJITDylibDefine(self.as_inner(), mu.as_inner()) }).map_err(|e| (e, mu))
939 }
940
941 pub fn clear(&self) -> Result<(), LLVMString> {
943 cvt(unsafe { LLVMOrcJITDylibClear(self.as_inner()) })
944 }
945
946 pub fn add_generator(&self, dg: DefinitionGenerator) {
948 let dg = mem::ManuallyDrop::new(dg);
951 unsafe { LLVMOrcJITDylibAddGenerator(self.as_inner(), dg.as_inner()) };
952 }
953}
954
955pub struct DefinitionGenerator {
957 dg: LLVMOrcDefinitionGeneratorRef,
958}
959
960impl DefinitionGenerator {
961 pub fn new_custom(generator: Box<dyn CustomDefinitionGenerator>) -> Self {
963 extern "C" fn try_to_generate(
964 generator_obj: LLVMOrcDefinitionGeneratorRef,
965 ctx: *mut c_void,
966 lookup_state: *mut LLVMOrcLookupStateRef,
967 kind: LLVMOrcLookupKind,
968 jd: LLVMOrcJITDylibRef,
969 jd_lookup_flags: LLVMOrcJITDylibLookupFlags,
970 lookup_set: LLVMOrcCLookupSet,
971 lookup_set_size: usize,
972 ) -> LLVMErrorRef {
973 let generator = unsafe { &mut **ctx.cast::<Box<dyn CustomDefinitionGenerator>>() };
974 let lookup_state = unsafe { &mut *lookup_state };
975 let jd = unsafe { JITDylibRef::from_inner_unchecked(jd) };
976 let lookup_set = unsafe { std::slice::from_raw_parts(lookup_set, lookup_set_size) };
977 let res = std::panic::catch_unwind(AssertUnwindSafe(|| {
978 generator.try_to_generate(
979 generator_obj,
980 lookup_state,
981 kind,
982 jd,
983 jd_lookup_flags,
984 lookup_set,
985 )
986 }));
987 cvt_cb_res(res)
988 }
989
990 extern "C" fn dispose(ctx: *mut c_void) {
991 let generator =
992 unsafe { Box::from_raw(ctx.cast::<Box<dyn CustomDefinitionGenerator>>()) };
993 let res = std::panic::catch_unwind(AssertUnwindSafe(|| drop(generator)));
994 if let Err(e) = res {
995 error!(msg=?panic_payload(&e), "dispose callback panicked");
996 }
997 }
998
999 let ctx = Box::into_raw(Box::new(generator)).cast();
1000 unsafe { Self::new_custom_raw(try_to_generate, ctx, dispose) }
1001 }
1002
1003 pub unsafe fn new_custom_raw(
1007 f: LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction,
1008 ctx: *mut c_void,
1009 dispose: LLVMOrcDisposeCAPIDefinitionGeneratorFunction,
1010 ) -> Self {
1011 Self::from_inner(LLVMOrcCreateCustomCAPIDefinitionGenerator(f, ctx, dispose))
1012 }
1013
1014 pub unsafe fn from_inner(dg: LLVMOrcDefinitionGeneratorRef) -> Self {
1016 Self { dg }
1017 }
1018
1019 pub fn as_inner(&self) -> LLVMOrcDefinitionGeneratorRef {
1021 self.dg
1022 }
1023}
1024
1025impl Drop for DefinitionGenerator {
1026 fn drop(&mut self) {
1027 unsafe { LLVMOrcDisposeDefinitionGenerator(self.as_inner()) };
1028 }
1029}
1030
1031pub trait CustomDefinitionGenerator {
1033 fn try_to_generate(
1064 &mut self,
1065 generator_obj: LLVMOrcDefinitionGeneratorRef,
1066 lookup_state: &mut LLVMOrcLookupStateRef,
1067 kind: LLVMOrcLookupKind,
1068 jd: JITDylibRef,
1069 jd_lookup_flags: LLVMOrcJITDylibLookupFlags,
1070 lookup_set: &[LLVMOrcCLookupSetElement],
1071 ) -> Result<(), String>;
1072}
1073
1074impl<T> CustomDefinitionGenerator for T
1075where
1076 T: FnMut(
1077 LLVMOrcDefinitionGeneratorRef,
1078 &mut LLVMOrcLookupStateRef,
1079 LLVMOrcLookupKind,
1080 JITDylibRef,
1081 LLVMOrcJITDylibLookupFlags,
1082 &[LLVMOrcCLookupSetElement],
1083 ) -> Result<(), String>,
1084{
1085 #[inline]
1086 fn try_to_generate(
1087 &mut self,
1088 generator_obj: LLVMOrcDefinitionGeneratorRef,
1089 lookup_state: &mut LLVMOrcLookupStateRef,
1090 kind: LLVMOrcLookupKind,
1091 jd: JITDylibRef,
1092 jd_lookup_flags: LLVMOrcJITDylibLookupFlags,
1093 lookup_set: &[LLVMOrcCLookupSetElement],
1094 ) -> Result<(), String> {
1095 self(generator_obj, lookup_state, kind, jd, jd_lookup_flags, lookup_set)
1096 }
1097}
1098
1099pub struct JITTargetMachineBuilder {
1101 builder: LLVMOrcJITTargetMachineBuilderRef,
1102}
1103
1104impl JITTargetMachineBuilder {
1105 pub fn new(tm: TargetMachine) -> Self {
1107 let tm = mem::ManuallyDrop::new(tm);
1108 unsafe {
1109 Self::from_inner(LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm.as_mut_ptr()))
1110 }
1111 }
1112
1113 pub fn detect_host() -> Result<Self, LLVMString> {
1115 let mut res = MaybeUninit::uninit();
1116 cvt(unsafe { LLVMOrcJITTargetMachineBuilderDetectHost(res.as_mut_ptr()) })?;
1117 Ok(Self { builder: unsafe { res.assume_init() } })
1118 }
1119
1120 pub unsafe fn from_inner(builder: LLVMOrcJITTargetMachineBuilderRef) -> Self {
1122 Self { builder }
1123 }
1124
1125 pub fn as_inner(&self) -> LLVMOrcJITTargetMachineBuilderRef {
1127 self.builder
1128 }
1129
1130 pub fn get_target_triple(&self) -> LLVMString {
1132 unsafe { llvm_string(LLVMOrcJITTargetMachineBuilderGetTargetTriple(self.as_inner())) }
1133 }
1134
1135 pub fn set_target_triple(&self, triple: &CStr) {
1137 unsafe { LLVMOrcJITTargetMachineBuilderSetTargetTriple(self.as_inner(), triple.as_ptr()) }
1138 }
1139}
1140
1141impl Drop for JITTargetMachineBuilder {
1142 fn drop(&mut self) {
1143 unsafe { LLVMOrcDisposeJITTargetMachineBuilder(self.builder) }
1144 }
1145}
1146
1147#[must_use]
1149pub struct LLJITBuilder {
1150 builder: lljit::LLVMOrcLLJITBuilderRef,
1151}
1152
1153impl LLJITBuilder {
1154 pub fn new() -> Self {
1156 Self { builder: ptr::null_mut() }
1157 }
1158
1159 pub unsafe fn from_inner(builder: LLVMOrcLLJITBuilderRef) -> Self {
1161 Self { builder }
1162 }
1163
1164 pub fn as_inner(&self) -> LLVMOrcLLJITBuilderRef {
1166 self.builder
1167 }
1168
1169 fn as_inner_init(&mut self) -> LLVMOrcLLJITBuilderRef {
1170 if self.builder.is_null() {
1171 self.builder = unsafe { LLVMOrcCreateLLJITBuilder() };
1172 }
1173 self.builder
1174 }
1175
1176 pub fn set_target_machine(self, tm: TargetMachine) -> Self {
1178 self.set_target_machine_builder(JITTargetMachineBuilder::new(tm))
1179 }
1180
1181 pub fn set_target_machine_from_host(self) -> Result<Self, LLVMString> {
1183 JITTargetMachineBuilder::detect_host().map(|jtmb| self.set_target_machine_builder(jtmb))
1184 }
1185
1186 pub fn set_target_machine_builder(mut self, jtmb: JITTargetMachineBuilder) -> Self {
1188 let jtmb = mem::ManuallyDrop::new(jtmb);
1189 unsafe {
1190 LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(self.as_inner_init(), jtmb.as_inner())
1191 };
1192 self
1193 }
1194
1195 pub fn build(self) -> Result<LLJIT, LLVMString> {
1216 let builder = mem::ManuallyDrop::new(self);
1220 let mut res = MaybeUninit::uninit();
1221 cvt(unsafe { LLVMOrcCreateLLJIT(res.as_mut_ptr(), builder.as_inner()) })?;
1222 Ok(unsafe { LLJIT::from_inner(res.assume_init()) })
1223 }
1224}
1225
1226impl Drop for LLJITBuilder {
1227 fn drop(&mut self) {
1228 unsafe { LLVMOrcDisposeLLJITBuilder(self.builder) };
1229 }
1230}
1231
1232pub struct LLJIT {
1238 jit: LLVMOrcLLJITRef,
1239}
1240
1241impl LLJIT {
1242 pub fn builder() -> LLJITBuilder {
1244 LLJITBuilder::new()
1245 }
1246
1247 pub fn new() -> Result<Self, LLVMString> {
1249 LLJITBuilder::new().set_target_machine_from_host()?.build()
1250 }
1251
1252 pub fn new_empty() -> Result<Self, LLVMString> {
1254 LLJITBuilder::new().build()
1255 }
1256
1257 pub unsafe fn from_inner(jit: LLVMOrcLLJITRef) -> Self {
1259 Self { jit }
1260 }
1261
1262 pub fn as_inner(&self) -> LLVMOrcLLJITRef {
1264 self.jit
1265 }
1266
1267 pub fn get_triple_string(&self) -> &CStr {
1269 unsafe { CStr::from_ptr(LLVMOrcLLJITGetTripleString(self.jit)) }
1271 }
1272
1273 pub fn get_data_layout_string(&self) -> &CStr {
1275 unsafe { CStr::from_ptr(LLVMOrcLLJITGetDataLayoutStr(self.jit)) }
1277 }
1278
1279 pub fn get_global_prefix(&self) -> c_char {
1281 unsafe { LLVMOrcLLJITGetGlobalPrefix(self.jit) }
1282 }
1283
1284 pub fn add_module(&self, tsm: ThreadSafeModule) -> Result<(), LLVMString> {
1286 let jd = self.get_main_jit_dylib();
1287 self.add_module_with_dylib(tsm, jd)
1288 }
1289
1290 pub fn add_module_with_dylib(
1292 &self,
1293 tsm: ThreadSafeModule,
1294 jd: JITDylibRef,
1295 ) -> Result<(), LLVMString> {
1296 let tsm = mem::ManuallyDrop::new(tsm);
1297 cvt(unsafe { LLVMOrcLLJITAddLLVMIRModule(self.as_inner(), jd.as_inner(), tsm.as_inner()) })
1298 }
1299
1300 pub fn add_module_with_rt(
1302 &self,
1303 tsm: ThreadSafeModule,
1304 jd: ResourceTracker,
1305 ) -> Result<(), LLVMString> {
1306 let tsm = mem::ManuallyDrop::new(tsm);
1307 cvt(unsafe {
1308 LLVMOrcLLJITAddLLVMIRModuleWithRT(self.as_inner(), jd.as_inner(), tsm.as_inner())
1309 })
1310 }
1311
1312 pub fn get_execution_session(&self) -> ExecutionSessionRef<'_> {
1314 unsafe { ExecutionSessionRef::from_inner(LLVMOrcLLJITGetExecutionSession(self.as_inner())) }
1315 }
1316
1317 pub fn get_main_jit_dylib(&self) -> JITDylibRef {
1319 unsafe { JITDylibRef::from_inner_unchecked(LLVMOrcLLJITGetMainJITDylib(self.as_inner())) }
1320 }
1321
1322 pub fn mangle_and_intern(&self, unmangled_name: &CStr) -> SymbolStringPoolEntry {
1325 unsafe {
1326 SymbolStringPoolEntry::from_inner_unchecked(LLVMOrcLLJITMangleAndIntern(
1327 self.as_inner(),
1328 unmangled_name.as_ptr(),
1329 ))
1330 }
1331 }
1332
1333 pub fn lookup(&self, name: &CStr) -> Result<usize, LLVMString> {
1335 self.lookup_unmangled(&self.mangle_and_intern(name))
1336 }
1337
1338 pub fn lookup_unmangled(&self, unmangled_name: &CStr) -> Result<usize, LLVMString> {
1342 let mut res = MaybeUninit::uninit();
1343 cvt(unsafe {
1344 LLVMOrcLLJITLookup(self.as_inner(), res.as_mut_ptr(), unmangled_name.as_ptr())
1345 })?;
1346 Ok(unsafe { res.assume_init() }.try_into().unwrap())
1347 }
1348
1349 pub fn get_ir_transform_layer(&self) -> IRTransformLayerRef {
1351 unsafe { IRTransformLayerRef::from_inner(LLVMOrcLLJITGetIRTransformLayer(self.as_inner())) }
1352 }
1353
1354 }
1365
1366impl Drop for LLJIT {
1367 fn drop(&mut self) {
1368 if let Err(e) = cvt(unsafe { LLVMOrcDisposeLLJIT(self.jit) }) {
1369 error!("Failed to dispose JIT: {e}");
1370 }
1371 }
1372}
1373
1374pub struct IRTransformLayerRef {
1410 ptr: LLVMOrcIRTransformLayerRef,
1411}
1412
1413impl IRTransformLayerRef {
1414 pub unsafe fn from_inner(ptr: LLVMOrcIRTransformLayerRef) -> Self {
1416 Self { ptr }
1417 }
1418
1419 pub fn as_inner(&self) -> LLVMOrcIRTransformLayerRef {
1421 self.ptr
1422 }
1423
1424 pub fn emit(&self, mr: MaterializationResponsibility, tsm: ThreadSafeModule) {
1426 let mr = mem::ManuallyDrop::new(mr);
1427 let tsm = mem::ManuallyDrop::new(tsm);
1428 unsafe { LLVMOrcIRTransformLayerEmit(self.as_inner(), mr.as_inner(), tsm.as_inner()) };
1429 }
1430
1431 pub fn set_transform(&self, f: fn(&ThreadSafeModule) -> Result<(), String>) {
1433 extern "C" fn shim(
1434 ctx: *mut c_void,
1435 m: *mut LLVMOrcThreadSafeModuleRef,
1436 _mr: LLVMOrcMaterializationResponsibilityRef,
1437 ) -> LLVMErrorRef {
1438 let f = ctx as *mut fn(&ThreadSafeModule) -> Result<(), String>;
1439 let m = mem::ManuallyDrop::new(unsafe { ThreadSafeModule::from_inner(*m) });
1440 let res = std::panic::catch_unwind(AssertUnwindSafe(|| unsafe { (*f)(&m) }));
1441 cvt_cb_res(res)
1442 }
1443
1444 let ctx = f as *mut c_void;
1445 unsafe { LLVMOrcIRTransformLayerSetTransform(self.as_inner(), shim, ctx) };
1446 }
1447}
1448
1449fn cvt(ptr: LLVMErrorRef) -> Result<(), LLVMString> {
1451 if ptr.is_null() {
1452 Ok(())
1453 } else {
1454 Err(unsafe { llvm_string(LLVMGetErrorMessage(ptr)) })
1455 }
1456}
1457
1458fn cvt_cb_res(res: Result<Result<(), String>, Box<dyn std::any::Any + Send>>) -> LLVMErrorRef {
1459 let msg = match res {
1460 Ok(Ok(())) => return ptr::null_mut(), Ok(Err(e)) => e,
1462 Err(e) => format!("callback panicked, payload: {:?}", panic_payload(&e)),
1463 };
1464 unsafe { LLVMCreateStringError(CString::new(msg).unwrap_or_default().as_ptr()) }
1465}
1466
1467fn panic_payload(any: &dyn std::any::Any) -> Option<&str> {
1468 if let Some(s) = any.downcast_ref::<&str>() {
1469 Some(*s)
1470 } else if let Some(s) = any.downcast_ref::<String>() {
1471 Some(s.as_str())
1472 } else {
1473 None
1474 }
1475}
1476
1477struct ManuallyDropElements<T> {
1498 vec: Vec<T>,
1499}
1500
1501impl<T> ManuallyDropElements<T> {
1502 #[inline(always)]
1503 fn new(vec: Vec<T>) -> Self {
1504 Self { vec }
1505 }
1506}
1507
1508impl<T> std::ops::Deref for ManuallyDropElements<T> {
1509 type Target = Vec<T>;
1510
1511 #[inline(always)]
1512 fn deref(&self) -> &Vec<T> {
1513 &self.vec
1514 }
1515}
1516
1517impl<T> std::ops::DerefMut for ManuallyDropElements<T> {
1518 #[inline(always)]
1519 fn deref_mut(&mut self) -> &mut Vec<T> {
1520 &mut self.vec
1521 }
1522}
1523
1524impl<T> Drop for ManuallyDropElements<T> {
1525 #[inline(always)]
1526 fn drop(&mut self) {
1527 unsafe { self.vec.set_len(0) };
1528 }
1529}
1530
1531#[cfg(test)]
1532mod tests {
1533 use super::*;
1534 use inkwell::{passes::PassBuilderOptions, targets::Target};
1535
1536 #[test]
1537 #[ignore = "ci fails idk"]
1538 fn e2e() {
1539 let tsm = ThreadSafeModule::create("test");
1540 let fn_name = "my_fn";
1541 tsm.with_module(|m| {
1542 let cx = m.get_context();
1543 let bcx = cx.create_builder();
1544 let ty = cx.i64_type().fn_type(&[], false);
1545
1546 let f = m.add_function(fn_name, ty, Some(inkwell::module::Linkage::External));
1547 let bb = cx.append_basic_block(f, "entry");
1548 bcx.position_at_end(bb);
1549 bcx.build_int_compare(
1550 inkwell::IntPredicate::EQ,
1551 cx.i64_type().const_zero(),
1552 cx.i64_type().const_all_ones(),
1553 "a",
1554 )
1555 .unwrap();
1556 bcx.build_return(Some(&cx.i64_type().const_int(69, false))).unwrap();
1557
1558 eprintln!("--before--");
1559 eprintln!("{}", m.print_to_string().to_string_lossy());
1560
1561 m.verify().map_err(|e| e.to_string())?;
1562
1563 Target::initialize_native(&Default::default()).unwrap();
1564 let triple = TargetMachine::get_default_triple();
1565 let cpu = TargetMachine::get_host_cpu_name();
1566 let features = TargetMachine::get_host_cpu_features();
1567 let target = Target::from_triple(&triple).map_err(|e| e.to_string())?;
1568 let machine = target
1569 .create_target_machine(
1570 &triple,
1571 &cpu.to_string_lossy(),
1572 &features.to_string_lossy(),
1573 Default::default(),
1574 inkwell::targets::RelocMode::Default,
1575 inkwell::targets::CodeModel::Default,
1576 )
1577 .ok_or_else(|| String::from("failed to create target machine"))?;
1578
1579 m.run_passes("default<O3>", &machine, PassBuilderOptions::create()).unwrap();
1580
1581 eprintln!("--after--");
1582 eprintln!("{}", m.print_to_string().to_string_lossy());
1583
1584 Ok(())
1585 })
1586 .unwrap();
1587
1588 let jit = LLJIT::new_empty().unwrap();
1589 jit.add_module(tsm).unwrap();
1590 let address =
1591 jit.lookup_unmangled(&jit.mangle_and_intern(&CString::new(fn_name).unwrap())).unwrap();
1592 eprintln!("address: {address:#x}");
1593 let f = unsafe { std::mem::transmute::<usize, extern "C" fn() -> u64>(address) };
1594 let r = f();
1595 assert_eq!(r, 69);
1596 }
1597}