llvm_plugin/
pass_manager.rs1use std::ffi::c_void;
2
3use inkwell::module::Module;
4use inkwell::values::FunctionValue;
5use inkwell_internals::llvm_versions;
6
7use super::{
8 FunctionAnalysisManager, LlvmFunctionPass, LlvmModulePass, ModuleAnalysisManager,
9 PreservedAnalyses,
10};
11
12pub struct ModulePassManager {
15 inner: *mut c_void,
16}
17
18impl ModulePassManager {
19 #[doc(hidden)]
20 pub unsafe fn from_raw(pass_manager: *mut c_void) -> Self {
21 Self {
22 inner: pass_manager,
23 }
24 }
25
26 pub fn add_pass<T>(&mut self, pass: T)
28 where
29 T: LlvmModulePass,
30 {
31 let pass = Box::new(pass);
32
33 extern "C" fn pass_deleter<T>(pass: *mut c_void) {
34 drop(unsafe { Box::<T>::from_raw(pass.cast()) })
35 }
36
37 extern "C" fn pass_entrypoint<T>(
38 pass: *mut c_void,
39 module: *mut c_void,
40 manager: *mut c_void,
41 ) -> PreservedAnalyses
42 where
43 T: LlvmModulePass,
44 {
45 let pass = unsafe { Box::<T>::from_raw(pass.cast()) };
46 let mut module = unsafe { Module::new(module.cast()) };
47 let manager = unsafe { ModuleAnalysisManager::from_raw(manager, None) };
48
49 let preserve = pass.run_pass(&mut module, &manager);
50
51 Box::into_raw(pass);
52 std::mem::forget(module);
53
54 preserve
55 }
56
57 unsafe {
58 super::modulePassManagerAddPass(
59 self.inner,
60 Box::into_raw(pass).cast(),
61 pass_deleter::<T>,
62 pass_entrypoint::<T>,
63 )
64 }
65 }
66
67 #[llvm_versions(12..)]
69 pub fn is_empty(&self) -> bool {
70 unsafe { super::modulePassManagerIsEmpty(self.inner) }
71 }
72}
73
74pub struct FunctionPassManager {
77 inner: *mut c_void,
78}
79
80impl FunctionPassManager {
81 #[doc(hidden)]
82 pub unsafe fn from_raw(pass_manager: *mut c_void) -> Self {
83 Self {
84 inner: pass_manager,
85 }
86 }
87
88 pub fn add_pass<T>(&mut self, pass: T)
90 where
91 T: LlvmFunctionPass,
92 {
93 let pass = Box::new(pass);
94
95 extern "C" fn pass_deleter<T>(pass: *mut c_void) {
96 drop(unsafe { Box::<T>::from_raw(pass.cast()) })
97 }
98
99 extern "C" fn pass_entrypoint<T>(
100 pass: *mut c_void,
101 function: *mut c_void,
102 manager: *mut c_void,
103 ) -> PreservedAnalyses
104 where
105 T: LlvmFunctionPass,
106 {
107 let pass = unsafe { Box::<T>::from_raw(pass.cast()) };
108 let mut function = unsafe { FunctionValue::new(function.cast()).unwrap() };
109 let manager = unsafe { FunctionAnalysisManager::from_raw(manager, None) };
110
111 let preserve = pass.run_pass(&mut function, &manager);
112
113 Box::into_raw(pass);
114 #[allow(forgetting_copy_types)]
115 std::mem::forget(function);
116
117 preserve
118 }
119
120 unsafe {
121 super::functionPassManagerAddPass(
122 self.inner,
123 Box::into_raw(pass).cast(),
124 pass_deleter::<T>,
125 pass_entrypoint::<T>,
126 )
127 }
128 }
129
130 #[llvm_versions(12..)]
132 pub fn is_empty(&self) -> bool {
133 unsafe { super::functionPassManagerIsEmpty(self.inner) }
134 }
135}