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, ContextRef},
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 ThreadSafeContext {
54 pub fn new() -> Self {
56 unsafe { Self::from_inner(LLVMOrcCreateNewThreadSafeContext()) }
57 }
58
59 pub fn from_context(ctx: Context) -> Self {
61 let ctx = mem::ManuallyDrop::new(ctx);
62 unsafe { Self::from_inner(LLVMOrcCreateNewThreadSafeContextFromLLVMContext(ctx.raw())) }
63 }
64
65 pub unsafe fn from_inner(ctx: LLVMOrcThreadSafeContextRef) -> Self {
67 Self { ctx }
68 }
69
70 pub fn as_inner(&self) -> LLVMOrcThreadSafeContextRef {
72 self.ctx
73 }
74
75 pub fn get_context(&self) -> ContextRef<'_> {
77 unsafe { ContextRef::new(LLVMOrcThreadSafeContextGetContext(self.ctx)) }
78 }
79
80 pub fn create_module<'ctx>(&'ctx self, module: Module<'ctx>) -> ThreadSafeModule {
82 ThreadSafeModule::create_in_context(module, self)
83 }
84}
85
86unsafe impl Send for ThreadSafeContext {}
87
88impl Drop for ThreadSafeContext {
89 fn drop(&mut self) {
90 unsafe { LLVMOrcDisposeThreadSafeContext(self.ctx) };
91 }
92}
93
94pub struct ThreadSafeModule {
102 ptr: LLVMOrcThreadSafeModuleRef,
103}
104
105impl ThreadSafeModule {
106 pub fn create(name: &str) -> Self {
110 let name_cstr = CString::new(name).unwrap();
111 unsafe {
112 let ctx = LLVMContextCreate();
113 let module = LLVMModuleCreateWithNameInContext(name_cstr.as_ptr(), ctx);
114 let tsc = LLVMOrcCreateNewThreadSafeContextFromLLVMContext(ctx);
115 let ptr = LLVMOrcCreateNewThreadSafeModule(module, tsc);
116 LLVMOrcDisposeThreadSafeContext(tsc);
117 Self { ptr }
118 }
119 }
120
121 pub fn create_in_context<'ctx>(module: Module<'ctx>, ctx: &'ctx ThreadSafeContext) -> Self {
123 let module = mem::ManuallyDrop::new(module);
124 let ptr = unsafe { LLVMOrcCreateNewThreadSafeModule(module.as_mut_ptr(), ctx.as_inner()) };
125 Self { ptr }
126 }
127
128 pub unsafe fn from_inner(ptr: LLVMOrcThreadSafeModuleRef) -> Self {
130 Self { ptr }
131 }
132
133 pub fn as_inner(&self) -> LLVMOrcThreadSafeModuleRef {
135 self.ptr
136 }
137
138 pub fn with_module<'tsm>(
142 &'tsm self,
143 mut f: impl FnMut(&Module<'tsm>) -> Result<(), String>,
144 ) -> Result<(), LLVMString> {
145 extern "C" fn shim(ctx: *mut c_void, m: LLVMModuleRef) -> LLVMErrorRef {
146 let f = ctx.cast::<&mut dyn FnMut(&Module<'_>) -> Result<(), String>>();
147 let m = mem::ManuallyDrop::new(unsafe { Module::new(m) });
148 let res = std::panic::catch_unwind(AssertUnwindSafe(|| unsafe { (*f)(&m) }));
149 cvt_cb_res(res)
150 }
151
152 let mut f = &mut f as &mut dyn FnMut(&Module<'tsm>) -> Result<(), String>;
153 let ctx = &mut f as *mut _ as *mut c_void;
154 cvt(unsafe { LLVMOrcThreadSafeModuleWithModuleDo(self.as_inner(), shim, ctx) })
155 }
156}
157
158unsafe impl Send for ThreadSafeModule {}
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 SymbolFlags {
290 pub fn none() -> Self {
292 Self { generic: LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsNone as u8, target: 0 }
293 }
294
295 pub fn set_exported(&mut self) {
297 self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsExported as u8;
298 }
299
300 pub fn with_exported(mut self) -> Self {
302 self.set_exported();
303 self
304 }
305
306 pub fn is_exported(&self) -> bool {
308 (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsExported as u8) != 0
309 }
310
311 pub fn set_weak(&mut self) {
313 self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsWeak as u8;
314 }
315
316 pub fn weak(mut self) -> Self {
318 self.set_weak();
319 self
320 }
321
322 pub fn is_weak(&self) -> bool {
324 (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsWeak as u8) != 0
325 }
326
327 pub fn set_callable(&mut self) {
329 self.generic |= LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsCallable as u8;
330 }
331
332 pub fn callable(mut self) -> Self {
334 self.set_callable();
335 self
336 }
337
338 pub fn is_callable(&self) -> bool {
340 (self.generic & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsCallable as u8) != 0
341 }
342
343 pub fn set_materialization_side_effects_only(&mut self) {
345 self.generic |=
346 LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly
347 as u8;
348 }
349
350 pub fn materialization_side_effects_only(mut self) -> Self {
352 self.set_materialization_side_effects_only();
353 self
354 }
355
356 pub fn is_materialization_side_effects_only(&self) -> bool {
358 (self.generic
359 & LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly
360 as u8)
361 != 0
362 }
363
364 pub fn set_generic(&mut self, flag: LLVMJITSymbolGenericFlags) {
366 self.generic |= flag as u8;
367 }
368
369 pub fn with_generic(mut self, flag: LLVMJITSymbolGenericFlags) -> Self {
371 self.set_generic(flag);
372 self
373 }
374
375 pub fn set_target(&mut self, flag: LLVMJITSymbolTargetFlags) {
377 self.target |= flag;
378 }
379
380 pub fn with_target(mut self, flag: LLVMJITSymbolTargetFlags) -> Self {
382 self.set_target(flag);
383 self
384 }
385}
386
387#[derive(Clone, Debug, PartialEq, Eq, Hash)]
389#[repr(C)]
390pub struct SymbolFlagsMapPair {
391 pub name: SymbolStringPoolEntry,
393 pub flags: SymbolFlags,
395}
396
397impl SymbolFlagsMapPair {
398 pub fn new(name: SymbolStringPoolEntry, flags: SymbolFlags) -> Self {
400 Self { name, flags }
401 }
402}
403
404#[derive(Clone, Debug, PartialEq, Eq, Hash)]
406#[repr(C)]
407pub struct SymbolMapPair {
408 pub name: SymbolStringPoolEntry,
410 pub evaluated_symbol: EvaluatedSymbol,
412}
413
414impl SymbolMapPair {
415 pub fn new(name: SymbolStringPoolEntry, evaluated_symbol: EvaluatedSymbol) -> Self {
417 Self { name, evaluated_symbol }
418 }
419}
420
421pub struct SymbolFlagsMapPairs<'a>(&'a [SymbolFlagsMapPair]);
425
426impl<'a> SymbolFlagsMapPairs<'a> {
427 pub fn as_slice(&self) -> &'a [SymbolFlagsMapPair] {
429 self.0
430 }
431}
432
433impl std::ops::Deref for SymbolFlagsMapPairs<'_> {
434 type Target = [SymbolFlagsMapPair];
435
436 fn deref(&self) -> &Self::Target {
437 self.0
438 }
439}
440
441impl Drop for SymbolFlagsMapPairs<'_> {
442 fn drop(&mut self) {
443 unsafe { LLVMOrcDisposeCSymbolFlagsMap(self.0.as_ptr().cast_mut().cast()) };
444 }
445}
446
447pub struct MaterializationUnit {
449 mu: LLVMOrcMaterializationUnitRef,
450}
451
452impl MaterializationUnit {
453 pub fn new_custom(
455 name: &CStr,
456 syms: Vec<SymbolFlagsMapPair>,
457 init_sym: Option<SymbolStringPoolEntry>,
458 mu: Box<dyn CustomMaterializationUnit>,
459 ) -> Self {
460 extern "C" fn materialize(ctx: *mut c_void, mr: LLVMOrcMaterializationResponsibilityRef) {
461 let ctx = unsafe { Box::from_raw(ctx.cast::<Box<dyn CustomMaterializationUnit>>()) };
467 let mr = unsafe { MaterializationResponsibility::from_inner(mr) };
468 let res = std::panic::catch_unwind(AssertUnwindSafe(move || ctx.materialize(mr)));
469 if let Err(e) = res {
470 error!(msg=?panic_payload(&e), "materialize callback panicked");
471 }
472 }
473
474 extern "C" fn discard(
475 ctx: *mut c_void,
476 jd: LLVMOrcJITDylibRef,
477 symbol: LLVMOrcSymbolStringPoolEntryRef,
478 ) {
479 let ctx = unsafe { &mut **ctx.cast::<Box<dyn CustomMaterializationUnit>>() };
482 let jd = unsafe { JITDylibRef::from_inner_unchecked(jd) };
483 let symbol = mem::ManuallyDrop::new(unsafe {
484 SymbolStringPoolEntry::from_inner_unchecked(symbol)
485 });
486 let res = std::panic::catch_unwind(AssertUnwindSafe(|| ctx.discard(jd, &symbol)));
487 if let Err(e) = res {
488 error!(msg=?panic_payload(&e), "discard callback panicked");
489 }
490 }
491
492 extern "C" fn destroy(ctx: *mut c_void) {
493 let ctx = unsafe { Box::from_raw(ctx.cast::<Box<dyn CustomMaterializationUnit>>()) };
497 let res = std::panic::catch_unwind(AssertUnwindSafe(|| drop(ctx)));
498 if let Err(e) = res {
499 error!(msg=?panic_payload(&e), "destroy callback panicked");
500 }
501 }
502
503 let ctx = Box::into_raw(Box::new(mu)).cast();
504 let init_sym = if let Some(init_sym) = init_sym {
505 mem::ManuallyDrop::new(init_sym).as_inner()
506 } else {
507 ptr::null_mut()
508 };
509 let syms = ManuallyDropElements::new(syms);
510 unsafe {
511 Self::new_custom_raw(
512 name,
513 ctx,
514 syms.as_ptr().cast_mut().cast(),
515 syms.len(),
516 init_sym,
517 materialize,
518 discard,
519 destroy,
520 )
521 }
522 }
523
524 pub unsafe fn new_custom_raw(
528 name: &CStr,
529 ctx: *mut c_void,
530 syms: LLVMOrcCSymbolFlagsMapPairs,
531 num_syms: usize,
532 init_sym: LLVMOrcSymbolStringPoolEntryRef,
533 materialize: LLVMOrcMaterializationUnitMaterializeFunction,
534 discard: LLVMOrcMaterializationUnitDiscardFunction,
535 destroy: LLVMOrcMaterializationUnitDestroyFunction,
536 ) -> Self {
537 Self::from_inner(LLVMOrcCreateCustomMaterializationUnit(
538 name.as_ptr(),
539 ctx,
540 syms,
541 num_syms,
542 init_sym,
543 materialize,
544 discard,
545 destroy,
546 ))
547 }
548
549 pub fn absolute_symbols(syms: Vec<SymbolMapPair>) -> Self {
552 let syms = ManuallyDropElements::new(syms);
553 unsafe { Self::absolute_symbols_raw(syms.as_ptr().cast_mut().cast(), syms.len()) }
554 }
555
556 pub unsafe fn absolute_symbols_raw(syms: LLVMOrcCSymbolMapPairs, len: usize) -> Self {
561 unsafe { Self::from_inner(LLVMOrcAbsoluteSymbols(syms, len)) }
562 }
563
564 pub unsafe fn from_inner(mu: LLVMOrcMaterializationUnitRef) -> Self {
568 Self { mu }
569 }
570
571 pub fn as_inner(&self) -> LLVMOrcMaterializationUnitRef {
573 self.mu
574 }
575}
576
577impl Drop for MaterializationUnit {
578 fn drop(&mut self) {
579 unsafe { LLVMOrcDisposeMaterializationUnit(self.as_inner()) };
580 }
581}
582
583pub trait CustomMaterializationUnit {
587 fn materialize(self: Box<Self>, mr: MaterializationResponsibility);
589
590 fn discard(&mut self, jd: JITDylibRef, symbol: &SymbolStringPoolEntry);
592
593 }
595
596pub struct MaterializationResponsibility {
598 mr: LLVMOrcMaterializationResponsibilityRef,
599}
600
601impl MaterializationResponsibility {
602 pub unsafe fn from_inner(mr: LLVMOrcMaterializationResponsibilityRef) -> Self {
604 Self { mr }
605 }
606
607 pub fn as_inner(&self) -> LLVMOrcMaterializationResponsibilityRef {
609 self.mr
610 }
611
612 #[inline]
614 pub fn as_ref(&self) -> MaterializationResponsibilityRef<'_> {
615 unsafe { MaterializationResponsibilityRef::from_inner(self.as_inner()) }
616 }
617}
618
619impl Drop for MaterializationResponsibility {
620 fn drop(&mut self) {
621 unsafe { LLVMOrcDisposeMaterializationResponsibility(self.as_inner()) };
622 }
623}
624
625pub struct MaterializationResponsibilityRef<'mr> {
627 mr: LLVMOrcMaterializationResponsibilityRef,
628 _marker: PhantomData<&'mr ()>,
629}
630
631impl<'mr> MaterializationResponsibilityRef<'mr> {
632 pub unsafe fn from_inner(mr: LLVMOrcMaterializationResponsibilityRef) -> Self {
634 Self { mr, _marker: PhantomData }
635 }
636
637 pub fn as_inner(&self) -> LLVMOrcMaterializationResponsibilityRef {
639 self.mr
640 }
641
642 pub fn get_target_dylib(&self) -> JITDylibRef {
644 unsafe {
645 JITDylibRef::from_inner_unchecked(LLVMOrcMaterializationResponsibilityGetTargetDylib(
646 self.as_inner(),
647 ))
648 }
649 }
650
651 pub fn get_execution_session(&self) -> ExecutionSessionRef<'mr> {
653 unsafe {
654 ExecutionSessionRef::from_inner(
655 LLVMOrcMaterializationResponsibilityGetExecutionSession(self.as_inner()),
656 )
657 }
658 }
659
660 pub fn get_symbols(&self) -> SymbolFlagsMapPairs<'mr> {
662 let mut len = MaybeUninit::uninit();
671 let data = unsafe {
672 LLVMOrcMaterializationResponsibilityGetSymbols(self.as_inner(), len.as_mut_ptr())
673 };
674 SymbolFlagsMapPairs(unsafe { std::slice::from_raw_parts(data.cast(), len.assume_init()) })
675 }
676
677 pub fn get_initializer_symbol(&self) -> Option<SymbolStringPoolEntry> {
682 let ptr =
683 unsafe { LLVMOrcMaterializationResponsibilityGetInitializerSymbol(self.as_inner()) };
684 unsafe { SymbolStringPoolEntry::from_inner(ptr) }
685 }
686
687 pub fn get_requested_symbols(&self) -> &[SymbolStringPoolEntry] {
693 let mut len = MaybeUninit::uninit();
694 let ptr = unsafe {
695 LLVMOrcMaterializationResponsibilityGetRequestedSymbols(
696 self.as_inner(),
697 len.as_mut_ptr(),
698 )
699 };
700 unsafe { std::slice::from_raw_parts(ptr.cast(), len.assume_init()) }
701 }
702
703 pub fn notify_resolved(&self, syms: &[SymbolFlagsMapPair]) -> Result<(), LLVMString> {
705 cvt(unsafe {
706 LLVMOrcMaterializationResponsibilityNotifyResolved(
707 self.as_inner(),
708 syms.as_ptr().cast_mut().cast(),
709 syms.len(),
710 )
711 })
712 }
713
714 pub fn notify_emitted(
721 &self,
722 symbol_dep_groups: &mut [LLVMOrcCSymbolDependenceGroup],
723 ) -> Result<(), LLVMString> {
724 cvt(unsafe {
725 LLVMOrcMaterializationResponsibilityNotifyEmitted(
726 self.as_inner(),
727 symbol_dep_groups.as_mut_ptr(),
728 symbol_dep_groups.len(),
729 )
730 })
731 }
732
733 pub fn fail_materialization(&self) {
739 unsafe { LLVMOrcMaterializationResponsibilityFailMaterialization(self.as_inner()) };
740 }
741
742 pub fn replace(&self, mu: MaterializationUnit) -> Result<(), LLVMString> {
749 let mu = mem::ManuallyDrop::new(mu);
750 cvt(unsafe { LLVMOrcMaterializationResponsibilityReplace(self.as_inner(), mu.as_inner()) })
751 }
752
753 pub fn delegate(&self, syms: &[SymbolStringPoolEntry]) -> Result<Self, LLVMString> {
760 let mut res = MaybeUninit::uninit();
761 cvt(unsafe {
762 LLVMOrcMaterializationResponsibilityDelegate(
763 self.as_inner(),
764 syms.as_ptr().cast_mut().cast(),
765 syms.len(),
766 res.as_mut_ptr(),
767 )
768 })?;
769 Ok(unsafe { Self::from_inner(res.assume_init()) })
770 }
771}
772
773pub struct ResourceTracker {
777 rt: LLVMOrcResourceTrackerRef,
778}
779
780impl ResourceTracker {
781 pub unsafe fn from_inner(rt: LLVMOrcResourceTrackerRef) -> Self {
783 Self { rt }
784 }
785
786 pub fn as_inner(&self) -> LLVMOrcResourceTrackerRef {
788 self.rt
789 }
790
791 pub fn remove(&self) -> Result<(), LLVMString> {
793 cvt(unsafe { LLVMOrcResourceTrackerRemove(self.as_inner()) })
794 }
795
796 pub fn transfer_to(&self, rt: &Self) {
799 unsafe { LLVMOrcResourceTrackerTransferTo(self.as_inner(), rt.as_inner()) };
800 }
801}
802
803impl Drop for ResourceTracker {
804 fn drop(&mut self) {
805 unsafe { LLVMOrcReleaseResourceTracker(self.as_inner()) };
806 }
807}
808
809pub struct ExecutionSessionRef<'ee> {
819 es: LLVMOrcExecutionSessionRef,
820 _marker: PhantomData<&'ee ()>,
821}
822
823impl ExecutionSessionRef<'_> {
824 pub unsafe fn from_inner(es: LLVMOrcExecutionSessionRef) -> Self {
826 Self { es, _marker: PhantomData }
827 }
828
829 pub fn as_inner(&self) -> LLVMOrcExecutionSessionRef {
831 self.es
832 }
833
834 pub fn intern(&self, name: &CStr) -> SymbolStringPoolEntry {
836 unsafe {
837 SymbolStringPoolEntry::from_inner_unchecked(LLVMOrcExecutionSessionIntern(
838 self.as_inner(),
839 name.as_ptr(),
840 ))
841 }
842 }
843
844 pub fn get_dylib_by_name(&self, name: &CStr) -> Option<JITDylibRef> {
846 unsafe {
847 let dylib = LLVMOrcExecutionSessionGetJITDylibByName(self.as_inner(), name.as_ptr());
848 JITDylibRef::from_inner(dylib)
849 }
850 }
851
852 pub fn create_bare_jit_dylib(&self, name: &CStr) -> JITDylibRef {
859 debug_assert!(self.get_dylib_by_name(name).is_none());
860 unsafe {
861 JITDylibRef::from_inner_unchecked(LLVMOrcExecutionSessionCreateBareJITDylib(
862 self.as_inner(),
863 name.as_ptr(),
864 ))
865 }
866 }
867
868 pub fn create_jit_dylib(&self, name: &CStr) -> Result<JITDylibRef, LLVMString> {
877 debug_assert!(self.get_dylib_by_name(name).is_none());
878 let mut res = MaybeUninit::uninit();
879 cvt(unsafe {
880 LLVMOrcExecutionSessionCreateJITDylib(self.as_inner(), res.as_mut_ptr(), name.as_ptr())
881 })?;
882 Ok(unsafe { JITDylibRef::from_inner_unchecked(res.assume_init()) })
883 }
884
885 pub fn set_default_error_reporter(&self) {
889 self.set_error_reporter(|msg| error!(msg = %msg.to_string_lossy(), "LLVM error"))
890 }
891
892 pub fn set_error_reporter(&self, f: fn(&CStr)) {
894 extern "C" fn shim(ctx: *mut c_void, err: LLVMErrorRef) {
895 let f = ctx as *mut fn(&CStr);
896 let Err(e) = cvt(err) else { return };
897 let res = std::panic::catch_unwind(AssertUnwindSafe(|| unsafe { (*f)(&e) }));
898 if let Err(e) = res {
899 error!(msg=?panic_payload(&e), "error reporter closure panicked");
900 }
901 }
902
903 let ctx = f as *mut c_void;
904 unsafe { LLVMOrcExecutionSessionSetErrorReporter(self.as_inner(), shim, ctx) };
905 }
906}
907
908pub struct JITDylibRef {
912 dylib: NonNull<LLVMOrcOpaqueJITDylib>,
913}
914
915impl JITDylibRef {
916 pub unsafe fn from_inner(dylib: LLVMOrcJITDylibRef) -> Option<Self> {
918 NonNull::new(dylib).map(|dylib| Self { dylib })
919 }
920
921 pub unsafe fn from_inner_unchecked(dylib: LLVMOrcJITDylibRef) -> Self {
923 Self { dylib: NonNull::new_unchecked(dylib) }
924 }
925
926 pub fn as_inner(&self) -> LLVMOrcJITDylibRef {
928 self.dylib.as_ptr()
929 }
930
931 pub fn create_resource_tracker(&self) -> ResourceTracker {
933 unsafe {
934 ResourceTracker::from_inner(LLVMOrcJITDylibCreateResourceTracker(self.as_inner()))
935 }
936 }
937
938 pub fn get_default_resource_tracker(&self) -> ResourceTracker {
940 unsafe {
941 ResourceTracker::from_inner(LLVMOrcJITDylibGetDefaultResourceTracker(self.as_inner()))
942 }
943 }
944
945 pub fn define(&self, mu: MaterializationUnit) -> Result<(), (LLVMString, MaterializationUnit)> {
947 cvt(unsafe { LLVMOrcJITDylibDefine(self.as_inner(), mu.as_inner()) }).map_err(|e| (e, mu))
951 }
952
953 pub fn clear(&self) -> Result<(), LLVMString> {
955 cvt(unsafe { LLVMOrcJITDylibClear(self.as_inner()) })
956 }
957
958 pub fn add_generator(&self, dg: DefinitionGenerator) {
960 let dg = mem::ManuallyDrop::new(dg);
963 unsafe { LLVMOrcJITDylibAddGenerator(self.as_inner(), dg.as_inner()) };
964 }
965}
966
967pub struct DefinitionGenerator {
969 dg: LLVMOrcDefinitionGeneratorRef,
970}
971
972impl DefinitionGenerator {
973 pub fn for_current_process(global_prefix: c_char) -> Result<Self, LLVMString> {
975 let mut generator = MaybeUninit::uninit();
976 cvt(unsafe {
977 LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(
978 generator.as_mut_ptr(),
979 global_prefix,
980 None,
981 ptr::null_mut(),
982 )
983 })?;
984 Ok(unsafe { Self::from_inner(generator.assume_init()) })
985 }
986
987 pub fn new_custom(generator: Box<dyn CustomDefinitionGenerator>) -> Self {
989 extern "C" fn try_to_generate(
990 generator_obj: LLVMOrcDefinitionGeneratorRef,
991 ctx: *mut c_void,
992 lookup_state: *mut LLVMOrcLookupStateRef,
993 kind: LLVMOrcLookupKind,
994 jd: LLVMOrcJITDylibRef,
995 jd_lookup_flags: LLVMOrcJITDylibLookupFlags,
996 lookup_set: LLVMOrcCLookupSet,
997 lookup_set_size: usize,
998 ) -> LLVMErrorRef {
999 let generator = unsafe { &mut **ctx.cast::<Box<dyn CustomDefinitionGenerator>>() };
1000 let lookup_state = unsafe { &mut *lookup_state };
1001 let jd = unsafe { JITDylibRef::from_inner_unchecked(jd) };
1002 let lookup_set = unsafe { std::slice::from_raw_parts(lookup_set, lookup_set_size) };
1003 let res = std::panic::catch_unwind(AssertUnwindSafe(|| {
1004 generator.try_to_generate(
1005 generator_obj,
1006 lookup_state,
1007 kind,
1008 jd,
1009 jd_lookup_flags,
1010 lookup_set,
1011 )
1012 }));
1013 cvt_cb_res(res)
1014 }
1015
1016 extern "C" fn dispose(ctx: *mut c_void) {
1017 let generator =
1018 unsafe { Box::from_raw(ctx.cast::<Box<dyn CustomDefinitionGenerator>>()) };
1019 let res = std::panic::catch_unwind(AssertUnwindSafe(|| drop(generator)));
1020 if let Err(e) = res {
1021 error!(msg=?panic_payload(&e), "dispose callback panicked");
1022 }
1023 }
1024
1025 let ctx = Box::into_raw(Box::new(generator)).cast();
1026 unsafe { Self::new_custom_raw(try_to_generate, ctx, dispose) }
1027 }
1028
1029 pub unsafe fn new_custom_raw(
1033 f: LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction,
1034 ctx: *mut c_void,
1035 dispose: LLVMOrcDisposeCAPIDefinitionGeneratorFunction,
1036 ) -> Self {
1037 Self::from_inner(LLVMOrcCreateCustomCAPIDefinitionGenerator(f, ctx, dispose))
1038 }
1039
1040 pub unsafe fn from_inner(dg: LLVMOrcDefinitionGeneratorRef) -> Self {
1042 Self { dg }
1043 }
1044
1045 pub fn as_inner(&self) -> LLVMOrcDefinitionGeneratorRef {
1047 self.dg
1048 }
1049}
1050
1051impl Drop for DefinitionGenerator {
1052 fn drop(&mut self) {
1053 unsafe { LLVMOrcDisposeDefinitionGenerator(self.as_inner()) };
1054 }
1055}
1056
1057pub trait CustomDefinitionGenerator {
1059 fn try_to_generate(
1090 &mut self,
1091 generator_obj: LLVMOrcDefinitionGeneratorRef,
1092 lookup_state: &mut LLVMOrcLookupStateRef,
1093 kind: LLVMOrcLookupKind,
1094 jd: JITDylibRef,
1095 jd_lookup_flags: LLVMOrcJITDylibLookupFlags,
1096 lookup_set: &[LLVMOrcCLookupSetElement],
1097 ) -> Result<(), String>;
1098}
1099
1100impl<T> CustomDefinitionGenerator for T
1101where
1102 T: FnMut(
1103 LLVMOrcDefinitionGeneratorRef,
1104 &mut LLVMOrcLookupStateRef,
1105 LLVMOrcLookupKind,
1106 JITDylibRef,
1107 LLVMOrcJITDylibLookupFlags,
1108 &[LLVMOrcCLookupSetElement],
1109 ) -> Result<(), String>,
1110{
1111 #[inline]
1112 fn try_to_generate(
1113 &mut self,
1114 generator_obj: LLVMOrcDefinitionGeneratorRef,
1115 lookup_state: &mut LLVMOrcLookupStateRef,
1116 kind: LLVMOrcLookupKind,
1117 jd: JITDylibRef,
1118 jd_lookup_flags: LLVMOrcJITDylibLookupFlags,
1119 lookup_set: &[LLVMOrcCLookupSetElement],
1120 ) -> Result<(), String> {
1121 self(generator_obj, lookup_state, kind, jd, jd_lookup_flags, lookup_set)
1122 }
1123}
1124
1125pub struct JITTargetMachineBuilder {
1127 builder: LLVMOrcJITTargetMachineBuilderRef,
1128}
1129
1130impl JITTargetMachineBuilder {
1131 pub fn new(tm: TargetMachine) -> Self {
1133 let tm = mem::ManuallyDrop::new(tm);
1134 unsafe {
1135 Self::from_inner(LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm.as_mut_ptr()))
1136 }
1137 }
1138
1139 pub fn detect_host() -> Result<Self, LLVMString> {
1141 let mut res = MaybeUninit::uninit();
1142 cvt(unsafe { LLVMOrcJITTargetMachineBuilderDetectHost(res.as_mut_ptr()) })?;
1143 Ok(Self { builder: unsafe { res.assume_init() } })
1144 }
1145
1146 pub unsafe fn from_inner(builder: LLVMOrcJITTargetMachineBuilderRef) -> Self {
1148 Self { builder }
1149 }
1150
1151 pub fn as_inner(&self) -> LLVMOrcJITTargetMachineBuilderRef {
1153 self.builder
1154 }
1155
1156 pub fn get_target_triple(&self) -> LLVMString {
1158 unsafe { llvm_string(LLVMOrcJITTargetMachineBuilderGetTargetTriple(self.as_inner())) }
1159 }
1160
1161 pub fn set_target_triple(&self, triple: &CStr) {
1163 unsafe { LLVMOrcJITTargetMachineBuilderSetTargetTriple(self.as_inner(), triple.as_ptr()) }
1164 }
1165}
1166
1167impl Drop for JITTargetMachineBuilder {
1168 fn drop(&mut self) {
1169 unsafe { LLVMOrcDisposeJITTargetMachineBuilder(self.builder) }
1170 }
1171}
1172
1173#[must_use]
1175pub struct LLJITBuilder {
1176 builder: lljit::LLVMOrcLLJITBuilderRef,
1177}
1178
1179impl LLJITBuilder {
1180 pub fn new() -> Self {
1182 Self { builder: ptr::null_mut() }
1183 }
1184
1185 pub unsafe fn from_inner(builder: LLVMOrcLLJITBuilderRef) -> Self {
1187 Self { builder }
1188 }
1189
1190 pub fn as_inner(&self) -> LLVMOrcLLJITBuilderRef {
1192 self.builder
1193 }
1194
1195 fn as_inner_init(&mut self) -> LLVMOrcLLJITBuilderRef {
1196 if self.builder.is_null() {
1197 self.builder = unsafe { LLVMOrcCreateLLJITBuilder() };
1198 }
1199 self.builder
1200 }
1201
1202 pub fn set_target_machine(self, tm: TargetMachine) -> Self {
1204 self.set_target_machine_builder(JITTargetMachineBuilder::new(tm))
1205 }
1206
1207 pub fn set_target_machine_from_host(self) -> Result<Self, LLVMString> {
1209 JITTargetMachineBuilder::detect_host().map(|jtmb| self.set_target_machine_builder(jtmb))
1210 }
1211
1212 pub fn set_target_machine_builder(mut self, jtmb: JITTargetMachineBuilder) -> Self {
1214 let jtmb = mem::ManuallyDrop::new(jtmb);
1215 unsafe {
1216 LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(self.as_inner_init(), jtmb.as_inner())
1217 };
1218 self
1219 }
1220
1221 pub fn build(self) -> Result<LLJIT, LLVMString> {
1242 let builder = mem::ManuallyDrop::new(self);
1246 let mut res = MaybeUninit::uninit();
1247 cvt(unsafe { LLVMOrcCreateLLJIT(res.as_mut_ptr(), builder.as_inner()) })?;
1248 Ok(unsafe { LLJIT::from_inner(res.assume_init()) })
1249 }
1250}
1251
1252impl Drop for LLJITBuilder {
1253 fn drop(&mut self) {
1254 unsafe { LLVMOrcDisposeLLJITBuilder(self.builder) };
1255 }
1256}
1257
1258pub struct LLJIT {
1264 jit: LLVMOrcLLJITRef,
1265}
1266
1267impl LLJIT {
1268 pub fn builder() -> LLJITBuilder {
1270 LLJITBuilder::new()
1271 }
1272
1273 pub fn new() -> Result<Self, LLVMString> {
1275 LLJITBuilder::new().set_target_machine_from_host()?.build()
1276 }
1277
1278 pub fn new_empty() -> Result<Self, LLVMString> {
1280 LLJITBuilder::new().build()
1281 }
1282
1283 pub unsafe fn from_inner(jit: LLVMOrcLLJITRef) -> Self {
1285 Self { jit }
1286 }
1287
1288 pub fn as_inner(&self) -> LLVMOrcLLJITRef {
1290 self.jit
1291 }
1292
1293 pub fn get_triple_string(&self) -> &CStr {
1295 unsafe { CStr::from_ptr(LLVMOrcLLJITGetTripleString(self.jit)) }
1297 }
1298
1299 pub fn get_data_layout_string(&self) -> &CStr {
1301 unsafe { CStr::from_ptr(LLVMOrcLLJITGetDataLayoutStr(self.jit)) }
1303 }
1304
1305 pub fn get_global_prefix(&self) -> c_char {
1307 unsafe { LLVMOrcLLJITGetGlobalPrefix(self.jit) }
1308 }
1309
1310 pub fn add_module(&self, tsm: ThreadSafeModule) -> Result<(), LLVMString> {
1312 let jd = self.get_main_jit_dylib();
1313 self.add_module_with_dylib(tsm, jd)
1314 }
1315
1316 pub fn add_module_with_dylib(
1318 &self,
1319 tsm: ThreadSafeModule,
1320 jd: JITDylibRef,
1321 ) -> Result<(), LLVMString> {
1322 let tsm = mem::ManuallyDrop::new(tsm);
1323 cvt(unsafe { LLVMOrcLLJITAddLLVMIRModule(self.as_inner(), jd.as_inner(), tsm.as_inner()) })
1324 }
1325
1326 pub fn add_module_with_rt(
1328 &self,
1329 tsm: ThreadSafeModule,
1330 jd: ResourceTracker,
1331 ) -> Result<(), LLVMString> {
1332 let tsm = mem::ManuallyDrop::new(tsm);
1333 cvt(unsafe {
1334 LLVMOrcLLJITAddLLVMIRModuleWithRT(self.as_inner(), jd.as_inner(), tsm.as_inner())
1335 })
1336 }
1337
1338 pub fn get_execution_session(&self) -> ExecutionSessionRef<'_> {
1340 unsafe { ExecutionSessionRef::from_inner(LLVMOrcLLJITGetExecutionSession(self.as_inner())) }
1341 }
1342
1343 pub fn get_main_jit_dylib(&self) -> JITDylibRef {
1345 unsafe { JITDylibRef::from_inner_unchecked(LLVMOrcLLJITGetMainJITDylib(self.as_inner())) }
1346 }
1347
1348 pub fn mangle_and_intern(&self, unmangled_name: &CStr) -> SymbolStringPoolEntry {
1351 unsafe {
1352 SymbolStringPoolEntry::from_inner_unchecked(LLVMOrcLLJITMangleAndIntern(
1353 self.as_inner(),
1354 unmangled_name.as_ptr(),
1355 ))
1356 }
1357 }
1358
1359 pub fn lookup(&self, name: &CStr) -> Result<usize, LLVMString> {
1361 self.lookup_unmangled(&self.mangle_and_intern(name))
1362 }
1363
1364 pub fn lookup_unmangled(&self, unmangled_name: &CStr) -> Result<usize, LLVMString> {
1368 let mut res = MaybeUninit::uninit();
1369 cvt(unsafe {
1370 LLVMOrcLLJITLookup(self.as_inner(), res.as_mut_ptr(), unmangled_name.as_ptr())
1371 })?;
1372 Ok(unsafe { res.assume_init() }.try_into().unwrap())
1373 }
1374
1375 pub fn get_ir_transform_layer(&self) -> IRTransformLayerRef {
1377 unsafe { IRTransformLayerRef::from_inner(LLVMOrcLLJITGetIRTransformLayer(self.as_inner())) }
1378 }
1379
1380 }
1391
1392impl Drop for LLJIT {
1393 fn drop(&mut self) {
1394 if let Err(e) = cvt(unsafe { LLVMOrcDisposeLLJIT(self.jit) }) {
1395 error!("Failed to dispose JIT: {e}");
1396 }
1397 }
1398}
1399
1400pub struct IRTransformLayerRef {
1436 ptr: LLVMOrcIRTransformLayerRef,
1437}
1438
1439impl IRTransformLayerRef {
1440 pub unsafe fn from_inner(ptr: LLVMOrcIRTransformLayerRef) -> Self {
1442 Self { ptr }
1443 }
1444
1445 pub fn as_inner(&self) -> LLVMOrcIRTransformLayerRef {
1447 self.ptr
1448 }
1449
1450 pub fn emit(&self, mr: MaterializationResponsibility, tsm: ThreadSafeModule) {
1452 let mr = mem::ManuallyDrop::new(mr);
1453 let tsm = mem::ManuallyDrop::new(tsm);
1454 unsafe { LLVMOrcIRTransformLayerEmit(self.as_inner(), mr.as_inner(), tsm.as_inner()) };
1455 }
1456
1457 pub fn set_transform(&self, f: fn(&ThreadSafeModule) -> Result<(), String>) {
1459 extern "C" fn shim(
1460 ctx: *mut c_void,
1461 m: *mut LLVMOrcThreadSafeModuleRef,
1462 _mr: LLVMOrcMaterializationResponsibilityRef,
1463 ) -> LLVMErrorRef {
1464 let f = ctx as *mut fn(&ThreadSafeModule) -> Result<(), String>;
1465 let m = mem::ManuallyDrop::new(unsafe { ThreadSafeModule::from_inner(*m) });
1466 let res = std::panic::catch_unwind(AssertUnwindSafe(|| unsafe { (*f)(&m) }));
1467 cvt_cb_res(res)
1468 }
1469
1470 let ctx = f as *mut c_void;
1471 unsafe { LLVMOrcIRTransformLayerSetTransform(self.as_inner(), shim, ctx) };
1472 }
1473}
1474
1475pub(crate) fn cvt(ptr: LLVMErrorRef) -> Result<(), LLVMString> {
1477 if ptr.is_null() { Ok(()) } else { Err(unsafe { llvm_string(LLVMGetErrorMessage(ptr)) }) }
1478}
1479
1480fn cvt_cb_res(res: Result<Result<(), String>, Box<dyn std::any::Any + Send>>) -> LLVMErrorRef {
1481 let msg = match res {
1482 Ok(Ok(())) => return ptr::null_mut(), Ok(Err(e)) => e,
1484 Err(e) => format!("callback panicked, payload: {:?}", panic_payload(&e)),
1485 };
1486 unsafe { LLVMCreateStringError(CString::new(msg).unwrap_or_default().as_ptr()) }
1487}
1488
1489fn panic_payload(any: &dyn std::any::Any) -> Option<&str> {
1490 if let Some(s) = any.downcast_ref::<&str>() {
1491 Some(*s)
1492 } else if let Some(s) = any.downcast_ref::<String>() {
1493 Some(s.as_str())
1494 } else {
1495 None
1496 }
1497}
1498
1499struct ManuallyDropElements<T> {
1520 vec: Vec<T>,
1521}
1522
1523impl<T> ManuallyDropElements<T> {
1524 #[inline(always)]
1525 fn new(vec: Vec<T>) -> Self {
1526 Self { vec }
1527 }
1528}
1529
1530impl<T> std::ops::Deref for ManuallyDropElements<T> {
1531 type Target = Vec<T>;
1532
1533 #[inline(always)]
1534 fn deref(&self) -> &Vec<T> {
1535 &self.vec
1536 }
1537}
1538
1539impl<T> std::ops::DerefMut for ManuallyDropElements<T> {
1540 #[inline(always)]
1541 fn deref_mut(&mut self) -> &mut Vec<T> {
1542 &mut self.vec
1543 }
1544}
1545
1546impl<T> Drop for ManuallyDropElements<T> {
1547 #[inline(always)]
1548 fn drop(&mut self) {
1549 unsafe { self.vec.set_len(0) };
1550 }
1551}
1552
1553#[cfg(test)]
1554mod tests {
1555 use super::*;
1556 use inkwell::{passes::PassBuilderOptions, targets::Target};
1557
1558 #[test]
1559 #[ignore = "ci fails idk"]
1560 fn e2e() {
1561 let tsm = ThreadSafeModule::create("test");
1562 let fn_name = "my_fn";
1563 tsm.with_module(|m| {
1564 let cx = m.get_context();
1565 let bcx = cx.create_builder();
1566 let ty = cx.i64_type().fn_type(&[], false);
1567
1568 let f = m.add_function(fn_name, ty, Some(inkwell::module::Linkage::External));
1569 let bb = cx.append_basic_block(f, "entry");
1570 bcx.position_at_end(bb);
1571 bcx.build_int_compare(
1572 inkwell::IntPredicate::EQ,
1573 cx.i64_type().const_zero(),
1574 cx.i64_type().const_all_ones(),
1575 "a",
1576 )
1577 .unwrap();
1578 bcx.build_return(Some(&cx.i64_type().const_int(69, false))).unwrap();
1579
1580 eprintln!("--before--");
1581 eprintln!("{}", m.print_to_string().to_string_lossy());
1582
1583 m.verify().map_err(|e| e.to_string())?;
1584
1585 Target::initialize_native(&Default::default()).unwrap();
1586 let triple = TargetMachine::get_default_triple();
1587 let cpu = TargetMachine::get_host_cpu_name();
1588 let features = TargetMachine::get_host_cpu_features();
1589 let target = Target::from_triple(&triple).map_err(|e| e.to_string())?;
1590 let machine = target
1591 .create_target_machine(
1592 &triple,
1593 &cpu.to_string_lossy(),
1594 &features.to_string_lossy(),
1595 Default::default(),
1596 inkwell::targets::RelocMode::Default,
1597 inkwell::targets::CodeModel::Default,
1598 )
1599 .ok_or_else(|| String::from("failed to create target machine"))?;
1600
1601 m.run_passes("default<O3>", &machine, PassBuilderOptions::create()).unwrap();
1602
1603 eprintln!("--after--");
1604 eprintln!("{}", m.print_to_string().to_string_lossy());
1605
1606 Ok(())
1607 })
1608 .unwrap();
1609
1610 let jit = LLJIT::new_empty().unwrap();
1611 jit.add_module(tsm).unwrap();
1612 let address =
1613 jit.lookup_unmangled(&jit.mangle_and_intern(&CString::new(fn_name).unwrap())).unwrap();
1614 eprintln!("address: {address:#x}");
1615 let f = unsafe { std::mem::transmute::<usize, extern "C" fn() -> u64>(address) };
1616 let r = f();
1617 assert_eq!(r, 69);
1618 }
1619}