1use std::ffi::c_void;
2
3use inkwell::module::Module;
4use inkwell::values::{AsValueRef, FunctionValue};
5
6use crate::{LlvmFunctionAnalysis, LlvmModuleAnalysis};
7
8pub struct FunctionAnalysisManager {
11 inner: *mut c_void,
12 from_analysis_id: Option<crate::AnalysisKey>,
13}
14
15impl FunctionAnalysisManager {
16 #[doc(hidden)]
17 pub unsafe fn from_raw(
18 inner: *mut c_void,
19 from_analysis_id: Option<crate::AnalysisKey>,
20 ) -> Self {
21 Self {
22 inner,
23 from_analysis_id,
24 }
25 }
26
27 pub fn get_result<A>(&self, function: &FunctionValue<'_>) -> &A::Result
37 where
38 A: crate::LlvmFunctionAnalysis,
39 {
40 let id = A::id();
41 assert!(
42 !matches!(self.from_analysis_id, Some(n) if id == n),
43 "Analysis cannot request its own result"
44 );
45
46 unsafe {
47 let res =
48 crate::get_function_analysis_result(self.inner, id, function.as_value_ref().cast());
49 Box::leak(Box::from_raw(res.cast()))
50 }
51 }
52
53 pub fn get_cached_result<A>(&self, function: &FunctionValue<'_>) -> Option<&A::Result>
65 where
66 A: crate::LlvmFunctionAnalysis,
67 {
68 let id = A::id();
69 assert!(
70 !matches!(self.from_analysis_id, Some(n) if id == n),
71 "Analysis cannot request its own result"
72 );
73
74 let res = crate::get_function_analysis_cached_result(
75 self.inner,
76 id,
77 function.as_value_ref().cast(),
78 );
79
80 if !res.is_null() {
81 let res = unsafe { Box::leak(Box::from_raw(res.cast())) };
82 Some(res)
83 } else {
84 None
85 }
86 }
87
88 pub fn register_pass<T>(&mut self, pass: T)
94 where
95 T: LlvmFunctionAnalysis,
96 {
97 let pass = Box::new(pass);
98
99 extern "C" fn result_deleter<T>(data: *mut c_void)
100 where
101 T: LlvmFunctionAnalysis,
102 {
103 drop(unsafe { Box::<<T as LlvmFunctionAnalysis>::Result>::from_raw(data.cast()) })
104 }
105
106 extern "C" fn pass_deleter<T>(pass: *mut c_void) {
107 drop(unsafe { Box::<T>::from_raw(pass.cast()) })
108 }
109
110 extern "C" fn pass_entrypoint<T>(
111 pass: *mut c_void,
112 function: *mut c_void,
113 manager: *mut c_void,
114 res: *mut *mut c_void,
115 res_deleter: *mut extern "C" fn(*mut c_void),
116 ) where
117 T: LlvmFunctionAnalysis,
118 {
119 let pass = unsafe { Box::<T>::from_raw(pass.cast()) };
120 let function = unsafe { FunctionValue::new(function.cast()).unwrap() };
121 let manager = unsafe { FunctionAnalysisManager::from_raw(manager, Some(T::id())) };
122
123 let data = pass.run_analysis(&function, &manager);
124
125 let data = Box::new(data);
126 unsafe {
127 *res = Box::<<T as LlvmFunctionAnalysis>::Result>::into_raw(data).cast();
128 *res_deleter = result_deleter::<T>;
129 }
130
131 Box::into_raw(pass);
132 #[allow(forgetting_copy_types)]
133 std::mem::forget(function);
134 }
135
136 let success = unsafe {
137 super::functionAnalysisManagerRegisterPass(
138 self.inner,
139 Box::into_raw(pass).cast(),
140 pass_deleter::<T>,
141 pass_entrypoint::<T>,
142 T::id(),
143 )
144 };
145
146 assert!(success, "analysis already registered");
147 }
148}
149
150pub struct ModuleAnalysisManager {
153 inner: *mut c_void,
154 from_analysis_id: Option<crate::AnalysisKey>,
155}
156
157impl ModuleAnalysisManager {
158 #[doc(hidden)]
159 pub unsafe fn from_raw(
160 inner: *mut c_void,
161 from_analysis_id: Option<crate::AnalysisKey>,
162 ) -> Self {
163 Self {
164 inner,
165 from_analysis_id,
166 }
167 }
168
169 pub fn get_result<A>(&self, module: &Module<'_>) -> &A::Result
179 where
180 A: crate::LlvmModuleAnalysis,
181 {
182 let id = A::id();
183 assert!(
184 !matches!(self.from_analysis_id, Some(n) if id == n),
185 "Analysis cannot request its own result"
186 );
187
188 let res =
189 crate::get_module_analysis_result(self.inner, A::id(), module.as_mut_ptr().cast());
190
191 unsafe { Box::leak(Box::from_raw(res.cast())) }
192 }
193
194 pub fn get_cached_result<A>(&self, module: &Module<'_>) -> Option<&A::Result>
206 where
207 A: crate::LlvmModuleAnalysis,
208 {
209 let id = A::id();
210 assert!(
211 !matches!(self.from_analysis_id, Some(n) if id == n),
212 "Analysis cannot request its own result"
213 );
214
215 let res = crate::get_module_analysis_cached_result(
216 self.inner,
217 A::id(),
218 module.as_mut_ptr().cast(),
219 );
220
221 if !res.is_null() {
222 let res = unsafe { Box::leak(Box::from_raw(res.cast())) };
223 Some(res)
224 } else {
225 None
226 }
227 }
228
229 pub fn get_function_analysis_manager_proxy(
232 &self,
233 module: &Module<'_>,
234 ) -> FunctionAnalysisManagerProxy {
235 let proxy = crate::get_function_analysis_manager_module_proxy(
236 self.inner,
237 module.as_mut_ptr().cast(),
238 );
239 FunctionAnalysisManagerProxy { inner: proxy }
240 }
241
242 pub fn register_pass<T>(&mut self, pass: T)
248 where
249 T: LlvmModuleAnalysis,
250 {
251 let pass = Box::new(pass);
252
253 extern "C" fn result_deleter<T>(data: *mut c_void)
254 where
255 T: LlvmModuleAnalysis,
256 {
257 drop(unsafe { Box::<<T as LlvmModuleAnalysis>::Result>::from_raw(data.cast()) })
258 }
259
260 extern "C" fn pass_deleter<T>(pass: *mut c_void) {
261 drop(unsafe { Box::<T>::from_raw(pass.cast()) })
262 }
263
264 extern "C" fn pass_entrypoint<T>(
265 pass: *mut c_void,
266 module: *mut c_void,
267 manager: *mut c_void,
268 res: *mut *mut c_void,
269 res_deleter: *mut extern "C" fn(*mut c_void),
270 ) where
271 T: LlvmModuleAnalysis,
272 {
273 let pass = unsafe { Box::<T>::from_raw(pass.cast()) };
274 let module = unsafe { Module::new(module.cast()) };
275 let manager = unsafe { ModuleAnalysisManager::from_raw(manager, Some(T::id())) };
276
277 let data = pass.run_analysis(&module, &manager);
278
279 let data = Box::new(data);
280 unsafe {
281 *res = Box::<<T as LlvmModuleAnalysis>::Result>::into_raw(data).cast();
282 *res_deleter = result_deleter::<T>;
283 }
284
285 Box::into_raw(pass);
286 std::mem::forget(module);
287 }
288
289 let success = unsafe {
290 super::moduleAnalysisManagerRegisterPass(
291 self.inner,
292 Box::into_raw(pass).cast(),
293 pass_deleter::<T>,
294 pass_entrypoint::<T>,
295 T::id(),
296 )
297 };
298
299 assert!(success, "analysis already registered");
300 }
301}
302
303pub struct FunctionAnalysisManagerProxy {
355 inner: *mut c_void,
356}
357
358impl FunctionAnalysisManagerProxy {
359 pub fn get_manager(&self) -> FunctionAnalysisManager {
361 let manager = crate::get_function_analysis_manager(self.inner);
362 FunctionAnalysisManager {
363 inner: manager,
364 from_analysis_id: None,
365 }
366 }
367}