1use std::ffi::c_void;
2
3use inkwell_internals::llvm_versions;
4
5use super::{
6 FunctionAnalysisManager, FunctionPassManager, ModuleAnalysisManager, ModulePassManager,
7};
8
9pub struct PassBuilder {
11 inner: *mut c_void,
12}
13
14impl PassBuilder {
15 #[doc(hidden)]
16 pub unsafe fn from_raw(pass_builder: *mut c_void) -> Self {
17 Self {
18 inner: pass_builder,
19 }
20 }
21
22 pub fn add_module_pipeline_parsing_callback<T>(&mut self, cb: T)
27 where
28 T: Fn(&str, &mut ModulePassManager) -> PipelineParsing + 'static,
29 {
30 let cb = Box::new(cb);
31
32 extern "C" fn callback_deleter<T>(cb: *const c_void) {
33 drop(unsafe { Box::<T>::from_raw(cb as *mut _) })
34 }
35
36 extern "C" fn callback_entrypoint<T>(
37 cb: *const c_void,
38 name_ptr: *const u8,
39 name_len: usize,
40 manager: *mut c_void,
41 ) -> bool
42 where
43 T: Fn(&str, &mut ModulePassManager) -> PipelineParsing + 'static,
44 {
45 let cb = unsafe { Box::<T>::from_raw(cb as *mut _) };
46 let name = unsafe { std::slice::from_raw_parts(name_ptr, name_len) };
47 let name = unsafe { std::str::from_utf8_unchecked(name) };
48 let mut manager = unsafe { ModulePassManager::from_raw(manager) };
49
50 let res = cb(name, &mut manager);
51
52 Box::into_raw(cb);
53 matches!(res, PipelineParsing::Parsed)
54 }
55
56 unsafe {
57 super::passBuilderAddModulePipelineParsingCallback(
58 self.inner,
59 Box::into_raw(cb).cast(),
60 callback_deleter::<T>,
61 callback_entrypoint::<T>,
62 )
63 }
64 }
65
66 pub fn add_function_pipeline_parsing_callback<T>(&mut self, cb: T)
71 where
72 T: Fn(&str, &mut FunctionPassManager) -> PipelineParsing + 'static,
73 {
74 let cb = Box::new(cb);
75
76 extern "C" fn callback_deleter<T>(cb: *const c_void) {
77 drop(unsafe { Box::<T>::from_raw(cb as *mut _) })
78 }
79
80 extern "C" fn callback_entrypoint<T>(
81 cb: *const c_void,
82 name_ptr: *const u8,
83 name_len: usize,
84 manager: *mut c_void,
85 ) -> bool
86 where
87 T: Fn(&str, &mut FunctionPassManager) -> PipelineParsing + 'static,
88 {
89 let cb = unsafe { Box::<T>::from_raw(cb as *mut _) };
90 let name = unsafe { std::slice::from_raw_parts(name_ptr, name_len) };
91 let name = unsafe { std::str::from_utf8_unchecked(name) };
92 let mut manager = unsafe { FunctionPassManager::from_raw(manager) };
93
94 let res = cb(name, &mut manager);
95
96 Box::into_raw(cb);
97 matches!(res, PipelineParsing::Parsed)
98 }
99
100 unsafe {
101 super::passBuilderAddFunctionPipelineParsingCallback(
102 self.inner,
103 Box::into_raw(cb).cast(),
104 callback_deleter::<T>,
105 callback_entrypoint::<T>,
106 )
107 }
108 }
109
110 pub fn add_module_analysis_registration_callback<T>(&mut self, cb: T)
115 where
116 T: Fn(&mut ModuleAnalysisManager) + 'static,
117 {
118 let cb = Box::new(cb);
119
120 extern "C" fn callback_deleter<T>(cb: *const c_void) {
121 drop(unsafe { Box::<T>::from_raw(cb as *mut _) })
122 }
123
124 extern "C" fn callback_entrypoint<T>(cb: *const c_void, manager: *mut c_void)
125 where
126 T: Fn(&mut ModuleAnalysisManager) + 'static,
127 {
128 let cb = unsafe { Box::<T>::from_raw(cb as *mut _) };
129 let mut manager = unsafe { ModuleAnalysisManager::from_raw(manager, None) };
130
131 cb(&mut manager);
132
133 Box::into_raw(cb);
134 }
135
136 unsafe {
137 super::passBuilderAddModuleAnalysisRegistrationCallback(
138 self.inner,
139 Box::into_raw(cb).cast(),
140 callback_deleter::<T>,
141 callback_entrypoint::<T>,
142 )
143 }
144 }
145
146 pub fn add_function_analysis_registration_callback<T>(&mut self, cb: T)
151 where
152 T: Fn(&mut FunctionAnalysisManager) + 'static,
153 {
154 let cb = Box::new(cb);
155
156 extern "C" fn callback_deleter<T>(cb: *const c_void) {
157 drop(unsafe { Box::<T>::from_raw(cb as *mut _) })
158 }
159
160 extern "C" fn callback_entrypoint<T>(cb: *const c_void, manager: *mut c_void)
161 where
162 T: Fn(&mut FunctionAnalysisManager) + 'static,
163 {
164 let cb = unsafe { Box::<T>::from_raw(cb as *mut _) };
165 let mut manager = unsafe { FunctionAnalysisManager::from_raw(manager, None) };
166
167 cb(&mut manager);
168
169 Box::into_raw(cb);
170 }
171
172 unsafe {
173 super::passBuilderAddFunctionAnalysisRegistrationCallback(
174 self.inner,
175 Box::into_raw(cb).cast(),
176 callback_deleter::<T>,
177 callback_entrypoint::<T>,
178 )
179 }
180 }
181
182 pub fn add_peephole_ep_callback<T>(&mut self, cb: T)
193 where
194 T: Fn(&mut FunctionPassManager, OptimizationLevel) + 'static,
195 {
196 let cb = Box::new(cb);
197
198 extern "C" fn callback_deleter<T>(cb: *const c_void) {
199 drop(unsafe { Box::<T>::from_raw(cb as *mut _) })
200 }
201
202 extern "C" fn callback_entrypoint<T>(
203 cb: *const c_void,
204 manager: *mut c_void,
205 opt: OptimizationLevel,
206 ) where
207 T: Fn(&mut FunctionPassManager, OptimizationLevel) + 'static,
208 {
209 let cb = unsafe { Box::<T>::from_raw(cb as *mut _) };
210 let mut manager = unsafe { FunctionPassManager::from_raw(manager) };
211
212 cb(&mut manager, opt);
213
214 Box::into_raw(cb);
215 }
216
217 unsafe {
218 super::passBuilderAddPeepholeEPCallback(
219 self.inner,
220 Box::into_raw(cb).cast(),
221 callback_deleter::<T>,
222 callback_entrypoint::<T>,
223 )
224 }
225 }
226
227 pub fn add_scalar_optimizer_late_ep_callback<T>(&mut self, cb: T)
236 where
237 T: Fn(&mut FunctionPassManager, OptimizationLevel) + 'static,
238 {
239 let cb = Box::new(cb);
240
241 extern "C" fn callback_deleter<T>(cb: *const c_void) {
242 drop(unsafe { Box::<T>::from_raw(cb as *mut _) })
243 }
244
245 extern "C" fn callback_entrypoint<T>(
246 cb: *const c_void,
247 manager: *mut c_void,
248 opt: OptimizationLevel,
249 ) where
250 T: Fn(&mut FunctionPassManager, OptimizationLevel) + 'static,
251 {
252 let cb = unsafe { Box::<T>::from_raw(cb as *mut _) };
253 let mut manager = unsafe { FunctionPassManager::from_raw(manager) };
254
255 cb(&mut manager, opt);
256
257 Box::into_raw(cb);
258 }
259
260 unsafe {
261 super::passBuilderAddScalarOptimizerLateEPCallback(
262 self.inner,
263 Box::into_raw(cb).cast(),
264 callback_deleter::<T>,
265 callback_entrypoint::<T>,
266 )
267 }
268 }
269
270 pub fn add_vectorizer_start_ep_callback<T>(&mut self, cb: T)
279 where
280 T: Fn(&mut FunctionPassManager, OptimizationLevel) + 'static,
281 {
282 let cb = Box::new(cb);
283
284 extern "C" fn callback_deleter<T>(cb: *const c_void) {
285 drop(unsafe { Box::<T>::from_raw(cb as *mut _) })
286 }
287
288 extern "C" fn callback_entrypoint<T>(
289 cb: *const c_void,
290 manager: *mut c_void,
291 opt: OptimizationLevel,
292 ) where
293 T: Fn(&mut FunctionPassManager, OptimizationLevel) + 'static,
294 {
295 let cb = unsafe { Box::<T>::from_raw(cb as *mut _) };
296 let mut manager = unsafe { FunctionPassManager::from_raw(manager) };
297
298 cb(&mut manager, opt);
299
300 Box::into_raw(cb);
301 }
302
303 unsafe {
304 super::passBuilderAddVectorizerStartEPCallback(
305 self.inner,
306 Box::into_raw(cb).cast(),
307 callback_deleter::<T>,
308 callback_entrypoint::<T>,
309 )
310 }
311 }
312
313 #[llvm_versions(12..)]
322 pub fn add_pipeline_start_ep_callback<T>(&mut self, cb: T)
323 where
324 T: Fn(&mut ModulePassManager, OptimizationLevel) + 'static,
325 {
326 let cb = Box::new(cb);
327
328 extern "C" fn callback_deleter<T>(cb: *const c_void) {
329 drop(unsafe { Box::<T>::from_raw(cb as *mut _) })
330 }
331
332 extern "C" fn callback_entrypoint<T>(
333 cb: *const c_void,
334 manager: *mut c_void,
335 opt: OptimizationLevel,
336 ) where
337 T: Fn(&mut ModulePassManager, OptimizationLevel) + 'static,
338 {
339 let cb = unsafe { Box::<T>::from_raw(cb as *mut _) };
340 let mut manager = unsafe { ModulePassManager::from_raw(manager) };
341
342 cb(&mut manager, opt);
343
344 Box::into_raw(cb);
345 }
346
347 unsafe {
348 super::passBuilderAddPipelineStartEPCallback(
349 self.inner,
350 Box::into_raw(cb).cast(),
351 callback_deleter::<T>,
352 callback_entrypoint::<T>,
353 )
354 }
355 }
356
357 #[llvm_versions(12..)]
365 pub fn add_pipeline_early_simplification_ep_callback<T>(&mut self, cb: T)
366 where
367 T: Fn(&mut ModulePassManager, OptimizationLevel) + 'static,
368 {
369 let cb = Box::new(cb);
370
371 extern "C" fn callback_deleter<T>(cb: *const c_void) {
372 drop(unsafe { Box::<T>::from_raw(cb as *mut _) })
373 }
374
375 extern "C" fn callback_entrypoint<T>(
376 cb: *const c_void,
377 manager: *mut c_void,
378 opt: OptimizationLevel,
379 ) where
380 T: Fn(&mut ModulePassManager, OptimizationLevel) + 'static,
381 {
382 let cb = unsafe { Box::<T>::from_raw(cb as *mut _) };
383 let mut manager = unsafe { ModulePassManager::from_raw(manager) };
384
385 cb(&mut manager, opt);
386
387 Box::into_raw(cb);
388 }
389
390 unsafe {
391 super::passBuilderAddPipelineEarlySimplificationEPCallback(
392 self.inner,
393 Box::into_raw(cb).cast(),
394 callback_deleter::<T>,
395 callback_entrypoint::<T>,
396 )
397 }
398 }
399
400 #[llvm_versions(11..)]
408 pub fn add_optimizer_last_ep_callback<T>(&mut self, cb: T)
409 where
410 T: Fn(&mut ModulePassManager, OptimizationLevel) + 'static,
411 {
412 let cb = Box::new(cb);
413
414 extern "C" fn callback_deleter<T>(cb: *const c_void) {
415 drop(unsafe { Box::<T>::from_raw(cb as *mut _) })
416 }
417
418 extern "C" fn callback_entrypoint<T>(
419 cb: *const c_void,
420 manager: *mut c_void,
421 opt: OptimizationLevel,
422 ) where
423 T: Fn(&mut ModulePassManager, OptimizationLevel) + 'static,
424 {
425 let cb = unsafe { Box::<T>::from_raw(cb as *mut _) };
426 let mut manager = unsafe { ModulePassManager::from_raw(manager) };
427
428 cb(&mut manager, opt);
429
430 Box::into_raw(cb);
431 }
432
433 unsafe {
434 super::passBuilderAddOptimizerLastEPCallback(
435 self.inner,
436 Box::into_raw(cb).cast(),
437 callback_deleter::<T>,
438 callback_entrypoint::<T>,
439 )
440 }
441 }
442
443 #[llvm_versions(15..)]
451 pub fn add_full_lto_early_ep_callback<T>(&mut self, cb: T)
452 where
453 T: Fn(&mut ModulePassManager, OptimizationLevel) + 'static,
454 {
455 let cb = Box::new(cb);
456
457 extern "C" fn callback_deleter<T>(cb: *const c_void) {
458 drop(unsafe { Box::<T>::from_raw(cb as *mut _) })
459 }
460
461 extern "C" fn callback_entrypoint<T>(
462 cb: *const c_void,
463 manager: *mut c_void,
464 opt: OptimizationLevel,
465 ) where
466 T: Fn(&mut ModulePassManager, OptimizationLevel) + 'static,
467 {
468 let cb = unsafe { Box::<T>::from_raw(cb as *mut _) };
469 let mut manager = unsafe { ModulePassManager::from_raw(manager) };
470
471 cb(&mut manager, opt);
472
473 Box::into_raw(cb);
474 }
475
476 unsafe {
477 super::passBuilderAddFullLinkTimeOptimizationEarlyEPCallback(
478 self.inner,
479 Box::into_raw(cb).cast(),
480 callback_deleter::<T>,
481 callback_entrypoint::<T>,
482 )
483 }
484 }
485
486 #[llvm_versions(15..)]
494 pub fn add_full_lto_last_ep_callback<T>(&mut self, cb: T)
495 where
496 T: Fn(&mut ModulePassManager, OptimizationLevel) + 'static,
497 {
498 let cb = Box::new(cb);
499
500 extern "C" fn callback_deleter<T>(cb: *const c_void) {
501 drop(unsafe { Box::<T>::from_raw(cb as *mut _) })
502 }
503
504 extern "C" fn callback_entrypoint<T>(
505 cb: *const c_void,
506 manager: *mut c_void,
507 opt: OptimizationLevel,
508 ) where
509 T: Fn(&mut ModulePassManager, OptimizationLevel) + 'static,
510 {
511 let cb = unsafe { Box::<T>::from_raw(cb as *mut _) };
512 let mut manager = unsafe { ModulePassManager::from_raw(manager) };
513
514 cb(&mut manager, opt);
515
516 Box::into_raw(cb);
517 }
518
519 unsafe {
520 super::passBuilderAddFullLinkTimeOptimizationLastEPCallback(
521 self.inner,
522 Box::into_raw(cb).cast(),
523 callback_deleter::<T>,
524 callback_entrypoint::<T>,
525 )
526 }
527 }
528
529 #[llvm_versions(15..)]
537 pub fn add_optimizer_early_ep_callback<T>(&mut self, cb: T)
538 where
539 T: Fn(&mut ModulePassManager, OptimizationLevel) + 'static,
540 {
541 let cb = Box::new(cb);
542
543 extern "C" fn callback_deleter<T>(cb: *const c_void) {
544 drop(unsafe { Box::<T>::from_raw(cb as *mut _) })
545 }
546
547 extern "C" fn callback_entrypoint<T>(
548 cb: *const c_void,
549 manager: *mut c_void,
550 opt: OptimizationLevel,
551 ) where
552 T: Fn(&mut ModulePassManager, OptimizationLevel) + 'static,
553 {
554 let cb = unsafe { Box::<T>::from_raw(cb as *mut _) };
555 let mut manager = unsafe { ModulePassManager::from_raw(manager) };
556
557 cb(&mut manager, opt);
558
559 Box::into_raw(cb);
560 }
561
562 unsafe {
563 super::passBuilderAddOptimizerEarlyEPCallback(
564 self.inner,
565 Box::into_raw(cb).cast(),
566 callback_deleter::<T>,
567 callback_entrypoint::<T>,
568 )
569 }
570 }
571}
572
573#[derive(Clone, Copy)]
576pub enum PipelineParsing {
577 Parsed,
579
580 NotParsed,
582}
583
584#[repr(C)]
588#[derive(Clone, Copy, Debug)]
589pub enum OptimizationLevel {
590 O0,
592
593 O1,
595
596 O2,
600
601 O3,
603
604 Os,
608
609 Oz,
611}