llvm_plugin/
pass_manager.rs

1use 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
12/// Struct allowing to add passes on LLVM IR modules to the pass manager
13/// pipeline.
14pub 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    /// Adds a pass to this pass manager.
27    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    /// Returns if the pass manager contains any passes.
68    #[llvm_versions(12..)]
69    pub fn is_empty(&self) -> bool {
70        unsafe { super::modulePassManagerIsEmpty(self.inner) }
71    }
72}
73
74/// Struct allowing to add passes on LLVM IR functions to the pass manager
75/// pipeline.
76pub 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    /// Adds a pass to this pass manager.
89    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    /// Returns if the pass manager contains any passes.
131    #[llvm_versions(12..)]
132    pub fn is_empty(&self) -> bool {
133        unsafe { super::functionPassManagerIsEmpty(self.inner) }
134    }
135}