Skip to main content

inkwell/
passes.rs

1#[llvm_versions(..=16)]
2use llvm_sys::core::LLVMGetGlobalPassRegistry;
3use llvm_sys::core::{
4    LLVMCreateFunctionPassManagerForModule, LLVMCreatePassManager, LLVMDisposePassManager,
5    LLVMFinalizeFunctionPassManager, LLVMInitializeFunctionPassManager, LLVMRunFunctionPassManager, LLVMRunPassManager,
6};
7#[llvm_versions(..=16)]
8use llvm_sys::initialization::{
9    LLVMInitializeAnalysis, LLVMInitializeCodeGen, LLVMInitializeCore, LLVMInitializeIPA, LLVMInitializeIPO,
10    LLVMInitializeInstCombine, LLVMInitializeScalarOpts, LLVMInitializeTarget, LLVMInitializeTransformUtils,
11    LLVMInitializeVectorization,
12};
13#[llvm_versions(..=15)]
14use llvm_sys::initialization::{LLVMInitializeInstrumentation, LLVMInitializeObjCARCOpts};
15use llvm_sys::prelude::LLVMPassManagerRef;
16#[llvm_versions(..=16)]
17use llvm_sys::prelude::LLVMPassRegistryRef;
18#[llvm_versions(..=15)]
19use llvm_sys::transforms::aggressive_instcombine::LLVMAddAggressiveInstCombinerPass;
20#[llvm_versions(..=16)]
21use llvm_sys::transforms::ipo::LLVMAddMergeFunctionsPass;
22#[llvm_versions(..=15)]
23use llvm_sys::transforms::ipo::LLVMAddPruneEHPass;
24#[llvm_versions(..=16)]
25use llvm_sys::transforms::ipo::{
26    LLVMAddAlwaysInlinerPass, LLVMAddConstantMergePass, LLVMAddDeadArgEliminationPass, LLVMAddFunctionAttrsPass,
27    LLVMAddFunctionInliningPass, LLVMAddGlobalDCEPass, LLVMAddGlobalOptimizerPass, LLVMAddIPSCCPPass,
28    LLVMAddInternalizePass, LLVMAddStripDeadPrototypesPass, LLVMAddStripSymbolsPass,
29};
30#[llvm_versions(..=16)]
31use llvm_sys::transforms::pass_manager_builder::{
32    LLVMPassManagerBuilderCreate, LLVMPassManagerBuilderDispose, LLVMPassManagerBuilderPopulateFunctionPassManager,
33    LLVMPassManagerBuilderPopulateModulePassManager, LLVMPassManagerBuilderRef,
34    LLVMPassManagerBuilderSetDisableSimplifyLibCalls, LLVMPassManagerBuilderSetDisableUnitAtATime,
35    LLVMPassManagerBuilderSetDisableUnrollLoops, LLVMPassManagerBuilderSetOptLevel, LLVMPassManagerBuilderSetSizeLevel,
36    LLVMPassManagerBuilderUseInlinerWithThreshold,
37};
38#[llvm_versions(..=16)]
39use llvm_sys::transforms::scalar::{
40    LLVMAddAggressiveDCEPass, LLVMAddAlignmentFromAssumptionsPass, LLVMAddBasicAliasAnalysisPass,
41    LLVMAddBitTrackingDCEPass, LLVMAddCFGSimplificationPass, LLVMAddCorrelatedValuePropagationPass,
42    LLVMAddDeadStoreEliminationPass, LLVMAddDemoteMemoryToRegisterPass, LLVMAddEarlyCSEPass, LLVMAddGVNPass,
43    LLVMAddIndVarSimplifyPass, LLVMAddInstructionCombiningPass, LLVMAddJumpThreadingPass, LLVMAddLICMPass,
44    LLVMAddLoopDeletionPass, LLVMAddLoopIdiomPass, LLVMAddLoopRerollPass, LLVMAddLoopRotatePass, LLVMAddLoopUnrollPass,
45    LLVMAddLowerExpectIntrinsicPass, LLVMAddMemCpyOptPass, LLVMAddMergedLoadStoreMotionPass,
46    LLVMAddPartiallyInlineLibCallsPass, LLVMAddReassociatePass, LLVMAddSCCPPass, LLVMAddScalarReplAggregatesPass,
47    LLVMAddScalarReplAggregatesPassSSA, LLVMAddScalarReplAggregatesPassWithThreshold, LLVMAddScalarizerPass,
48    LLVMAddScopedNoAliasAAPass, LLVMAddSimplifyLibCallsPass, LLVMAddTailCallEliminationPass,
49    LLVMAddTypeBasedAliasAnalysisPass, LLVMAddVerifierPass,
50};
51#[llvm_versions(..=16)]
52use llvm_sys::transforms::vectorize::{LLVMAddLoopVectorizePass, LLVMAddSLPVectorizePass};
53
54// LLVM12 removes the ConstantPropagation pass
55// Users should use the InstSimplify pass instead.
56#[cfg(feature = "llvm11-0")]
57use llvm_sys::transforms::ipo::LLVMAddIPConstantPropagationPass;
58#[cfg(feature = "llvm11-0")]
59use llvm_sys::transforms::scalar::LLVMAddConstantPropagationPass;
60
61#[llvm_versions(13..)]
62use llvm_sys::transforms::pass_builder::{
63    LLVMCreatePassBuilderOptions, LLVMDisposePassBuilderOptions, LLVMPassBuilderOptionsRef,
64    LLVMPassBuilderOptionsSetCallGraphProfile, LLVMPassBuilderOptionsSetDebugLogging,
65    LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll, LLVMPassBuilderOptionsSetLicmMssaNoAccForPromotionCap,
66    LLVMPassBuilderOptionsSetLicmMssaOptCap, LLVMPassBuilderOptionsSetLoopInterleaving,
67    LLVMPassBuilderOptionsSetLoopUnrolling, LLVMPassBuilderOptionsSetLoopVectorization,
68    LLVMPassBuilderOptionsSetMergeFunctions, LLVMPassBuilderOptionsSetSLPVectorization,
69    LLVMPassBuilderOptionsSetVerifyEach,
70};
71#[llvm_versions(12..=16)]
72use llvm_sys::transforms::scalar::LLVMAddInstructionSimplifyPass;
73
74#[llvm_versions(..=16)]
75use crate::OptimizationLevel;
76use crate::module::Module;
77use crate::values::{AsValueRef, FunctionValue};
78
79use std::borrow::Borrow;
80use std::marker::PhantomData;
81
82// REVIEW: Opt Level might be identical to targets::Option<CodeGenOptLevel>
83#[llvm_versions(..=16)]
84#[derive(Debug)]
85pub struct PassManagerBuilder {
86    pass_manager_builder: LLVMPassManagerBuilderRef,
87}
88
89#[llvm_versions(..=16)]
90impl PassManagerBuilder {
91    pub unsafe fn new(pass_manager_builder: LLVMPassManagerBuilderRef) -> Self {
92        assert!(!pass_manager_builder.is_null());
93
94        PassManagerBuilder { pass_manager_builder }
95    }
96
97    /// Acquires the underlying raw pointer belonging to this `PassManagerBuilder` type.
98    pub fn as_mut_ptr(&self) -> LLVMPassManagerBuilderRef {
99        self.pass_manager_builder
100    }
101
102    pub fn create() -> Self {
103        let pass_manager_builder = unsafe { LLVMPassManagerBuilderCreate() };
104
105        unsafe { PassManagerBuilder::new(pass_manager_builder) }
106    }
107
108    pub fn set_optimization_level(&self, opt_level: OptimizationLevel) {
109        unsafe { LLVMPassManagerBuilderSetOptLevel(self.pass_manager_builder, opt_level as u32) }
110    }
111
112    // REVIEW: Valid input 0-2 according to llvmlite. Maybe better as an enum?
113    pub fn set_size_level(&self, size_level: u32) {
114        unsafe { LLVMPassManagerBuilderSetSizeLevel(self.pass_manager_builder, size_level) }
115    }
116
117    pub fn set_disable_unit_at_a_time(&self, disable: bool) {
118        unsafe { LLVMPassManagerBuilderSetDisableUnitAtATime(self.pass_manager_builder, disable as i32) }
119    }
120
121    pub fn set_disable_unroll_loops(&self, disable: bool) {
122        unsafe { LLVMPassManagerBuilderSetDisableUnrollLoops(self.pass_manager_builder, disable as i32) }
123    }
124
125    pub fn set_disable_simplify_lib_calls(&self, disable: bool) {
126        unsafe { LLVMPassManagerBuilderSetDisableSimplifyLibCalls(self.pass_manager_builder, disable as i32) }
127    }
128
129    pub fn set_inliner_with_threshold(&self, threshold: u32) {
130        unsafe { LLVMPassManagerBuilderUseInlinerWithThreshold(self.pass_manager_builder, threshold) }
131    }
132
133    /// Populates a PassManager<FunctionValue> with the expectation of function
134    /// transformations.
135    ///
136    /// # Example
137    ///
138    /// ```no_run
139    /// use inkwell::context::Context;
140    /// use inkwell::OptimizationLevel::Aggressive;
141    /// use inkwell::passes::{PassManager, PassManagerBuilder};
142    ///
143    /// let context = Context::create();
144    /// let module = context.create_module("mod");
145    /// let pass_manager_builder = PassManagerBuilder::create();
146    ///
147    /// pass_manager_builder.set_optimization_level(Aggressive);
148    ///
149    /// let fpm = PassManager::create(&module);
150    ///
151    /// pass_manager_builder.populate_function_pass_manager(&fpm);
152    /// ```
153    #[allow(deprecated)]
154    pub fn populate_function_pass_manager(&self, pass_manager: &PassManager<FunctionValue>) {
155        unsafe {
156            LLVMPassManagerBuilderPopulateFunctionPassManager(self.pass_manager_builder, pass_manager.pass_manager)
157        }
158    }
159
160    /// Populates a PassManager<Module> with the expectation of whole module
161    /// transformations.
162    ///
163    /// # Example
164    ///
165    /// ```no_run
166    /// use inkwell::OptimizationLevel::Aggressive;
167    /// use inkwell::passes::{PassManager, PassManagerBuilder};
168    /// use inkwell::targets::{InitializationConfig, Target};
169    ///
170    /// let config = InitializationConfig::default();
171    /// Target::initialize_native(&config).unwrap();
172    /// let pass_manager_builder = PassManagerBuilder::create();
173    ///
174    /// pass_manager_builder.set_optimization_level(Aggressive);
175    ///
176    /// let fpm = PassManager::create(());
177    ///
178    /// pass_manager_builder.populate_module_pass_manager(&fpm);
179    /// ```
180    #[allow(deprecated)]
181    pub fn populate_module_pass_manager(&self, pass_manager: &PassManager<Module>) {
182        unsafe { LLVMPassManagerBuilderPopulateModulePassManager(self.pass_manager_builder, pass_manager.pass_manager) }
183    }
184
185    /// Populates a PassManager<Module> with the expectation of link time
186    /// optimization transformations.
187    ///
188    /// # Example
189    ///
190    /// ```no_run
191    /// use inkwell::OptimizationLevel::Aggressive;
192    /// use inkwell::passes::{PassManager, PassManagerBuilder};
193    /// use inkwell::targets::{InitializationConfig, Target};
194    ///
195    /// let config = InitializationConfig::default();
196    /// Target::initialize_native(&config).unwrap();
197    /// let pass_manager_builder = PassManagerBuilder::create();
198    ///
199    /// pass_manager_builder.set_optimization_level(Aggressive);
200    ///
201    /// let lpm = PassManager::create(());
202    ///
203    /// pass_manager_builder.populate_lto_pass_manager(&lpm, false, false);
204    /// ```
205    #[allow(deprecated)]
206    #[llvm_versions(..=14)]
207    pub fn populate_lto_pass_manager(&self, pass_manager: &PassManager<Module>, internalize: bool, run_inliner: bool) {
208        use llvm_sys::transforms::pass_manager_builder::LLVMPassManagerBuilderPopulateLTOPassManager;
209
210        unsafe {
211            LLVMPassManagerBuilderPopulateLTOPassManager(
212                self.pass_manager_builder,
213                pass_manager.pass_manager,
214                internalize as i32,
215                run_inliner as i32,
216            )
217        }
218    }
219}
220
221#[llvm_versions(..=16)]
222impl Drop for PassManagerBuilder {
223    fn drop(&mut self) {
224        unsafe { LLVMPassManagerBuilderDispose(self.pass_manager_builder) }
225    }
226}
227
228// This is an ugly privacy hack so that PassManagerSubType can stay private
229// to this module and so that super traits using this trait will be not be
230// implementable outside this library
231pub trait PassManagerSubType {
232    type Input;
233
234    unsafe fn create<I: Borrow<Self::Input>>(input: I) -> LLVMPassManagerRef;
235    #[allow(deprecated)]
236    unsafe fn run_in_pass_manager(&self, pass_manager: &PassManager<Self>) -> bool
237    where
238        Self: Sized;
239}
240
241#[allow(deprecated)]
242impl PassManagerSubType for Module<'_> {
243    type Input = ();
244
245    unsafe fn create<I: Borrow<Self::Input>>(_: I) -> LLVMPassManagerRef {
246        unsafe { LLVMCreatePassManager() }
247    }
248
249    unsafe fn run_in_pass_manager(&self, pass_manager: &PassManager<Self>) -> bool {
250        unsafe { LLVMRunPassManager(pass_manager.pass_manager, self.module.get()) == 1 }
251    }
252}
253
254// With GATs https://github.com/rust-lang/rust/issues/44265 this could be
255// type Input<'a> = &'a Module;
256#[allow(deprecated)]
257impl<'ctx> PassManagerSubType for FunctionValue<'ctx> {
258    type Input = Module<'ctx>;
259
260    unsafe fn create<I: Borrow<Self::Input>>(input: I) -> LLVMPassManagerRef {
261        unsafe { LLVMCreateFunctionPassManagerForModule(input.borrow().module.get()) }
262    }
263
264    unsafe fn run_in_pass_manager(&self, pass_manager: &PassManager<Self>) -> bool {
265        unsafe { LLVMRunFunctionPassManager(pass_manager.pass_manager, self.as_value_ref()) == 1 }
266    }
267}
268
269// SubTypes: PassManager<Module>, PassManager<FunctionValue>
270/// A manager for running optimization and simplification passes. Much of the
271/// documentation for specific passes is directly from the [LLVM
272/// documentation](https://llvm.org/docs/Passes.html).
273#[derive(Debug)]
274#[deprecated(
275    since = "0.9.0",
276    note = "Use [`PassBuilderOptions`] with [`Module::run_passes`] instead (new pass manager). This struct will be removed once LLVM 16 support is dropped."
277)]
278pub struct PassManager<T> {
279    pub(crate) pass_manager: LLVMPassManagerRef,
280    sub_type: PhantomData<T>,
281}
282
283#[allow(deprecated)]
284impl PassManager<FunctionValue<'_>> {
285    /// Acquires the underlying raw pointer belonging to this `PassManager<T>` type.
286    pub fn as_mut_ptr(&self) -> LLVMPassManagerRef {
287        self.pass_manager
288    }
289
290    // return true means some pass modified the module, not an error occurred
291    pub fn initialize(&self) -> bool {
292        unsafe { LLVMInitializeFunctionPassManager(self.pass_manager) == 1 }
293    }
294
295    pub fn finalize(&self) -> bool {
296        unsafe { LLVMFinalizeFunctionPassManager(self.pass_manager) == 1 }
297    }
298}
299
300#[allow(deprecated)]
301impl<T: PassManagerSubType> PassManager<T> {
302    pub unsafe fn new(pass_manager: LLVMPassManagerRef) -> Self {
303        assert!(!pass_manager.is_null());
304
305        PassManager {
306            pass_manager,
307            sub_type: PhantomData,
308        }
309    }
310
311    pub fn create<I: Borrow<T::Input>>(input: I) -> PassManager<T> {
312        let pass_manager = unsafe { T::create(input) };
313
314        unsafe { PassManager::new(pass_manager) }
315    }
316
317    /// This method returns true if any of the passes modified the function or module
318    /// and false otherwise.
319    pub fn run_on(&self, input: &T) -> bool {
320        unsafe { input.run_in_pass_manager(self) }
321    }
322
323    /// This pass promotes "by reference" arguments to be "by value" arguments.
324    /// In practice, this means looking for internal functions that have pointer
325    /// arguments. If it can prove, through the use of alias analysis, that an
326    /// argument is only loaded, then it can pass the value into the function
327    /// instead of the address of the value. This can cause recursive simplification
328    /// of code and lead to the elimination of allocas (especially in C++ template
329    /// code like the STL).
330    ///
331    /// This pass also handles aggregate arguments that are passed into a function,
332    /// scalarizing them if the elements of the aggregate are only loaded. Note that
333    /// it refuses to scalarize aggregates which would require passing in more than
334    /// three operands to the function, because passing thousands of operands for a
335    /// large array or structure is unprofitable!
336    ///
337    /// Note that this transformation could also be done for arguments that are
338    /// only stored to (returning the value instead), but does not currently.
339    /// This case would be best handled when and if LLVM starts supporting multiple
340    /// return values from functions.
341    #[llvm_versions(..=14)]
342    pub fn add_argument_promotion_pass(&self) {
343        use llvm_sys::transforms::ipo::LLVMAddArgumentPromotionPass;
344
345        unsafe { LLVMAddArgumentPromotionPass(self.pass_manager) }
346    }
347
348    /// Merges duplicate global constants together into a single constant that is
349    /// shared. This is useful because some passes (i.e., TraceValues) insert a lot
350    /// of string constants into the program, regardless of whether or not an existing
351    /// string is available.
352    #[llvm_versions(..=16)]
353    pub fn add_constant_merge_pass(&self) {
354        unsafe { LLVMAddConstantMergePass(self.pass_manager) }
355    }
356
357    /// Discovers identical functions and collapses them.
358    #[llvm_versions(..=16)]
359    pub fn add_merge_functions_pass(&self) {
360        unsafe { LLVMAddMergeFunctionsPass(self.pass_manager) }
361    }
362
363    /// This pass deletes dead arguments from internal functions. Dead argument
364    /// elimination removes arguments which are directly dead, as well as arguments
365    /// only passed into function calls as dead arguments of other functions. This
366    /// pass also deletes dead arguments in a similar way.
367    ///
368    /// This pass is often useful as a cleanup pass to run after aggressive
369    /// interprocedural passes, which add possibly-dead arguments.
370    #[llvm_versions(..=16)]
371    pub fn add_dead_arg_elimination_pass(&self) {
372        unsafe { LLVMAddDeadArgEliminationPass(self.pass_manager) }
373    }
374
375    /// A simple interprocedural pass which walks the call-graph, looking for
376    /// functions which do not access or only read non-local memory, and marking
377    /// them readnone/readonly. In addition, it marks function arguments (of
378    /// pointer type) “nocapture” if a call to the function does not create
379    /// any copies of the pointer value that outlive the call. This more or
380    /// less means that the pointer is only dereferenced, and not returned
381    /// from the function or stored in a global. This pass is implemented
382    /// as a bottom-up traversal of the call-graph.
383    #[llvm_versions(..=16)]
384    pub fn add_function_attrs_pass(&self) {
385        unsafe { LLVMAddFunctionAttrsPass(self.pass_manager) }
386    }
387
388    /// Bottom-up inlining of functions into callees.
389    #[llvm_versions(..=16)]
390    pub fn add_function_inlining_pass(&self) {
391        unsafe { LLVMAddFunctionInliningPass(self.pass_manager) }
392    }
393
394    /// A custom inliner that handles only functions that are marked as “always inline”.
395    #[llvm_versions(..=16)]
396    pub fn add_always_inliner_pass(&self) {
397        unsafe { LLVMAddAlwaysInlinerPass(self.pass_manager) }
398    }
399
400    /// This transform is designed to eliminate unreachable internal
401    /// globals from the program. It uses an aggressive algorithm,
402    /// searching out globals that are known to be alive. After it
403    /// finds all of the globals which are needed, it deletes
404    /// whatever is left over. This allows it to delete recursive
405    /// chunks of the program which are unreachable.
406    #[llvm_versions(..=16)]
407    pub fn add_global_dce_pass(&self) {
408        unsafe { LLVMAddGlobalDCEPass(self.pass_manager) }
409    }
410
411    /// This pass transforms simple global variables that never have
412    /// their address taken. If obviously true, it marks read/write
413    /// globals as constant, deletes variables only stored to, etc.
414    #[llvm_versions(..=16)]
415    pub fn add_global_optimizer_pass(&self) {
416        unsafe { LLVMAddGlobalOptimizerPass(self.pass_manager) }
417    }
418
419    /// This pass implements an extremely simple interprocedural
420    /// constant propagation pass. It could certainly be improved
421    /// in many different ways, like using a worklist. This pass
422    /// makes arguments dead, but does not remove them. The existing
423    /// dead argument elimination pass should be run after this to
424    /// clean up the mess.
425    ///
426    /// In LLVM 12 and later, this instruction is replaced by the
427    /// [`add_instruction_simplify_pass`].
428    #[cfg(feature = "llvm11-0")]
429    pub fn add_ip_constant_propagation_pass(&self) {
430        unsafe { LLVMAddIPConstantPropagationPass(self.pass_manager) }
431    }
432
433    /// This file implements a simple interprocedural pass which
434    /// walks the call-graph, turning invoke instructions into
435    /// call instructions if and only if the callee cannot throw
436    /// an exception. It implements this as a bottom-up traversal
437    /// of the call-graph.
438    #[llvm_versions(..=15)]
439    pub fn add_prune_eh_pass(&self) {
440        unsafe { LLVMAddPruneEHPass(self.pass_manager) }
441    }
442
443    /// An interprocedural variant of [Sparse Conditional Constant
444    /// Propagation](https://llvm.org/docs/Passes.html#passes-sccp).
445    #[llvm_versions(..=16)]
446    pub fn add_ipsccp_pass(&self) {
447        unsafe { LLVMAddIPSCCPPass(self.pass_manager) }
448    }
449
450    /// This pass loops over all of the functions in the input module,
451    /// looking for a main function. If a main function is found, all
452    /// other functions and all global variables with initializers are
453    /// marked as internal.
454    #[llvm_versions(..=16)]
455    pub fn add_internalize_pass(&self, all_but_main: bool) {
456        unsafe { LLVMAddInternalizePass(self.pass_manager, all_but_main as u32) }
457    }
458
459    /// This pass loops over all of the functions in the input module,
460    /// looking for dead declarations and removes them. Dead declarations
461    /// are declarations of functions for which no implementation is available
462    /// (i.e., declarations for unused library functions).
463    #[llvm_versions(..=16)]
464    pub fn add_strip_dead_prototypes_pass(&self) {
465        unsafe { LLVMAddStripDeadPrototypesPass(self.pass_manager) }
466    }
467
468    /// Performs code stripping. This transformation can delete:
469    ///
470    /// * Names for virtual registers
471    /// * Symbols for internal globals and functions
472    /// * Debug information
473    ///
474    /// Note that this transformation makes code much less readable,
475    /// so it should only be used in situations where the strip utility
476    /// would be used, such as reducing code size or making it harder
477    /// to reverse engineer code.
478    #[llvm_versions(..=16)]
479    pub fn add_strip_symbol_pass(&self) {
480        unsafe { LLVMAddStripSymbolsPass(self.pass_manager) }
481    }
482
483    /// No LLVM documentation is available at this time.
484    #[llvm_versions(..=16)]
485    pub fn add_loop_vectorize_pass(&self) {
486        unsafe { LLVMAddLoopVectorizePass(self.pass_manager) }
487    }
488
489    /// No LLVM documentation is available at this time.
490    #[llvm_versions(..=16)]
491    pub fn add_slp_vectorize_pass(&self) {
492        unsafe { LLVMAddSLPVectorizePass(self.pass_manager) }
493    }
494
495    /// ADCE aggressively tries to eliminate code. This pass is similar
496    /// to [DCE](https://llvm.org/docs/Passes.html#passes-dce) but it
497    /// assumes that values are dead until proven otherwise. This is
498    /// similar to [SCCP](https://llvm.org/docs/Passes.html#passes-sccp),
499    /// except applied to the liveness of values.
500    #[llvm_versions(..=16)]
501    pub fn add_aggressive_dce_pass(&self) {
502        unsafe { LLVMAddAggressiveDCEPass(self.pass_manager) }
503    }
504
505    /// No LLVM documentation is available at this time.
506    #[llvm_versions(..=16)]
507    pub fn add_bit_tracking_dce_pass(&self) {
508        unsafe { LLVMAddBitTrackingDCEPass(self.pass_manager) }
509    }
510
511    /// No LLVM documentation is available at this time.
512    #[llvm_versions(..=16)]
513    pub fn add_alignment_from_assumptions_pass(&self) {
514        unsafe { LLVMAddAlignmentFromAssumptionsPass(self.pass_manager) }
515    }
516
517    /// Performs dead code elimination and basic block merging. Specifically:
518    ///
519    /// * Removes basic blocks with no predecessors.
520    /// * Merges a basic block into its predecessor if there is only one and the predecessor only has one successor.
521    /// * Eliminates PHI nodes for basic blocks with a single predecessor.
522    /// * Eliminates a basic block that only contains an unconditional branch.
523    #[llvm_versions(..=16)]
524    pub fn add_cfg_simplification_pass(&self) {
525        unsafe { LLVMAddCFGSimplificationPass(self.pass_manager) }
526    }
527
528    /// A trivial dead store elimination that only considers basic-block local redundant stores.
529    #[llvm_versions(..=16)]
530    pub fn add_dead_store_elimination_pass(&self) {
531        unsafe { LLVMAddDeadStoreEliminationPass(self.pass_manager) }
532    }
533
534    /// No LLVM documentation is available at this time.
535    #[llvm_versions(..=16)]
536    pub fn add_scalarizer_pass(&self) {
537        unsafe { LLVMAddScalarizerPass(self.pass_manager) }
538    }
539
540    /// No LLVM documentation is available at this time.
541    #[llvm_versions(..=16)]
542    pub fn add_merged_load_store_motion_pass(&self) {
543        unsafe { LLVMAddMergedLoadStoreMotionPass(self.pass_manager) }
544    }
545
546    /// This pass performs global value numbering to eliminate
547    /// fully and partially redundant instructions. It also
548    /// performs redundant load elimination.
549    #[llvm_versions(..=16)]
550    pub fn add_gvn_pass(&self) {
551        unsafe { LLVMAddGVNPass(self.pass_manager) }
552    }
553
554    /// This pass performs global value numbering to eliminate
555    /// fully and partially redundant instructions. It also
556    /// performs redundant load elimination.
557    // REVIEW: Is `LLVMAddGVNPass` deprecated? Should we just seamlessly replace
558    // the old one with this one in 4.0+?
559    #[llvm_versions(..=16)]
560    pub fn add_new_gvn_pass(&self) {
561        use llvm_sys::transforms::scalar::LLVMAddNewGVNPass;
562
563        unsafe { LLVMAddNewGVNPass(self.pass_manager) }
564    }
565
566    /// This transformation analyzes and transforms the induction variables (and
567    /// computations derived from them) into simpler forms suitable for subsequent
568    /// analysis and transformation.
569    ///
570    /// This transformation makes the following changes to each loop with an
571    /// identifiable induction variable:
572    ///
573    /// * All loops are transformed to have a single canonical induction variable
574    /// which starts at zero and steps by one.
575    ///
576    /// * The canonical induction variable is guaranteed to be the first PHI node
577    /// in the loop header block.
578    ///
579    /// * Any pointer arithmetic recurrences are raised to use array subscripts.
580    ///
581    /// If the trip count of a loop is computable, this pass also makes the
582    /// following changes:
583    ///
584    /// * The exit condition for the loop is canonicalized to compare the induction
585    /// value against the exit value. This turns loops like:
586    ///
587    /// ```c
588    /// for (i = 7; i*i < 1000; ++i)
589    /// ```
590    /// into
591    /// ```c
592    /// for (i = 0; i != 25; ++i)
593    /// ```
594    ///
595    /// * Any use outside of the loop of an expression derived from the indvar is
596    /// changed to compute the derived value outside of the loop, eliminating the
597    /// dependence on the exit value of the induction variable. If the only purpose
598    /// of the loop is to compute the exit value of some derived expression, this
599    /// transformation will make the loop dead.
600    ///
601    /// This transformation should be followed by strength reduction after all of
602    /// the desired loop transformations have been performed. Additionally, on
603    /// targets where it is profitable, the loop could be transformed to count
604    /// down to zero (the "do loop" optimization).
605    #[llvm_versions(..=16)]
606    pub fn add_ind_var_simplify_pass(&self) {
607        unsafe { LLVMAddIndVarSimplifyPass(self.pass_manager) }
608    }
609
610    /// Combine instructions to form fewer, simple instructions. This pass
611    /// does not modify the CFG. This pass is where algebraic simplification happens.
612    ///
613    /// This pass combines things like:
614    ///
615    /// ```c
616    /// %Y = add i32 %X, 1
617    /// %Z = add i32 %Y, 1
618    /// ```
619    /// into:
620    /// ```c
621    /// %Z = add i32 %X, 2
622    /// ```
623    ///
624    /// This is a simple worklist driven algorithm.
625    ///
626    /// This pass guarantees that the following canonicalization are performed
627    /// on the program:
628    ///
629    /// 1. If a binary operator has a constant operand, it is moved to the
630    /// right-hand side.
631    ///
632    /// 2. Bitwise operators with constant operands are always grouped so that
633    /// shifts are performed first, then ORs, then ANDs, then XORs.
634    ///
635    /// 3. Compare instructions are converted from <, >, ≤, or ≥ to = or ≠ if possible.
636    ///
637    /// 4. All cmp instructions on boolean values are replaced with logical operations.
638    ///
639    /// 5. add X, X is represented as mul X, 2 ⇒ shl X, 1
640    ///
641    /// 6. Multiplies with a constant power-of-two argument are transformed into shifts.
642    ///
643    /// 7. ... etc.
644    ///
645    /// This pass can also simplify calls to specific well-known function calls
646    /// (e.g. runtime library functions). For example, a call exit(3) that occurs within
647    /// the main() function can be transformed into simply return 3. Whether or not library
648    /// calls are simplified is controlled by the [-functionattrs](https://llvm.org/docs/Passes.html#passes-functionattrs)
649    /// pass and LLVM’s knowledge of library calls on different targets.
650    #[llvm_versions(..=16)]
651    pub fn add_instruction_combining_pass(&self) {
652        unsafe { LLVMAddInstructionCombiningPass(self.pass_manager) }
653    }
654
655    /// Jump threading tries to find distinct threads of control flow
656    /// running through a basic block. This pass looks at blocks that
657    /// have multiple predecessors and multiple successors. If one or
658    /// more of the predecessors of the block can be proven to always
659    /// cause a jump to one of the successors, we forward the edge from
660    /// the predecessor to the successor by duplicating the contents of
661    /// this block.
662    ///
663    /// An example of when this can occur is code like this:
664    ///
665    /// ```c
666    /// if () { ...
667    ///   X = 4;
668    /// }
669    /// if (X < 3) {
670    /// ```
671    ///
672    /// In this case, the unconditional branch at the end of the first
673    /// if can be revectored to the false side of the second if.
674    #[llvm_versions(..=16)]
675    pub fn add_jump_threading_pass(&self) {
676        unsafe { LLVMAddJumpThreadingPass(self.pass_manager) }
677    }
678
679    /// This pass performs loop invariant code motion,
680    /// attempting to remove as much code from the body of
681    /// a loop as possible. It does this by either hoisting
682    /// code into the preheader block, or by sinking code to
683    /// the exit blocks if it is safe. This pass also promotes
684    /// must-aliased memory locations in the loop to live in
685    /// registers, thus hoisting and sinking “invariant” loads
686    /// and stores.
687    ///
688    /// This pass uses alias analysis for two purposes:
689    ///
690    /// 1. Moving loop invariant loads and calls out of loops.
691    /// If we can determine that a load or call inside of a
692    /// loop never aliases anything stored to, we can hoist
693    /// it or sink it like any other instruction.
694    ///
695    /// 2. Scalar Promotion of Memory. If there is a store
696    /// instruction inside of the loop, we try to move the
697    /// store to happen AFTER the loop instead of inside of
698    /// the loop. This can only happen if a few conditions
699    /// are true:
700    ///
701    ///     1. The pointer stored through is loop invariant.
702    ///
703    ///     2. There are no stores or loads in the loop
704    /// which may alias the pointer. There are no calls in
705    /// the loop which mod/ref the pointer.
706    ///
707    /// If these conditions are true, we can promote the loads
708    /// and stores in the loop of the pointer to use a temporary
709    /// alloca'd variable. We then use the mem2reg functionality
710    /// to construct the appropriate SSA form for the variable.
711    #[llvm_versions(..=16)]
712    pub fn add_licm_pass(&self) {
713        unsafe { LLVMAddLICMPass(self.pass_manager) }
714    }
715
716    /// This file implements the Dead Loop Deletion Pass.
717    /// This pass is responsible for eliminating loops with
718    /// non-infinite computable trip counts that have no side
719    /// effects or volatile instructions, and do not contribute
720    /// to the computation of the function’s return value.
721    #[llvm_versions(..=16)]
722    pub fn add_loop_deletion_pass(&self) {
723        unsafe { LLVMAddLoopDeletionPass(self.pass_manager) }
724    }
725
726    /// No LLVM documentation is available at this time.
727    #[llvm_versions(..=16)]
728    pub fn add_loop_idiom_pass(&self) {
729        unsafe { LLVMAddLoopIdiomPass(self.pass_manager) }
730    }
731
732    /// A simple loop rotation transformation.
733    #[llvm_versions(..=16)]
734    pub fn add_loop_rotate_pass(&self) {
735        unsafe { LLVMAddLoopRotatePass(self.pass_manager) }
736    }
737
738    /// No LLVM documentation is available at this time.
739    #[llvm_versions(..=16)]
740    pub fn add_loop_reroll_pass(&self) {
741        unsafe { LLVMAddLoopRerollPass(self.pass_manager) }
742    }
743
744    /// This pass implements a simple loop unroller.
745    /// It works best when loops have been canonicalized
746    /// by the [indvars](https://llvm.org/docs/Passes.html#passes-indvars)
747    /// pass, allowing it to determine the trip counts
748    /// of loops easily.
749    #[llvm_versions(..=16)]
750    pub fn add_loop_unroll_pass(&self) {
751        unsafe { LLVMAddLoopUnrollPass(self.pass_manager) }
752    }
753
754    /// This pass transforms loops that contain branches on
755    /// loop-invariant conditions to have multiple loops.
756    /// For example, it turns the left into the right code:
757    ///
758    /// ```c
759    /// for (...)                  if (lic)
760    ///     A                          for (...)
761    ///     if (lic)                       A; B; C
762    ///         B                  else
763    ///     C                          for (...)
764    ///                                    A; C
765    /// ```
766    ///
767    /// This can increase the size of the code exponentially
768    /// (doubling it every time a loop is unswitched) so we
769    /// only unswitch if the resultant code will be smaller
770    /// than a threshold.
771    ///
772    /// This pass expects [LICM](https://llvm.org/docs/Passes.html#passes-licm)
773    /// to be run before it to hoist invariant conditions
774    /// out of the loop, to make the unswitching opportunity
775    /// obvious.
776    #[llvm_versions(..=14)]
777    pub fn add_loop_unswitch_pass(&self) {
778        use llvm_sys::transforms::scalar::LLVMAddLoopUnswitchPass;
779
780        unsafe { LLVMAddLoopUnswitchPass(self.pass_manager) }
781    }
782
783    /// This pass performs various transformations related
784    /// to eliminating memcpy calls, or transforming sets
785    /// of stores into memsets.
786    #[llvm_versions(..=16)]
787    pub fn add_memcpy_optimize_pass(&self) {
788        unsafe { LLVMAddMemCpyOptPass(self.pass_manager) }
789    }
790
791    /// This pass performs partial inlining, typically by inlining
792    /// an if statement that surrounds the body of the function.
793    #[llvm_versions(..=16)]
794    pub fn add_partially_inline_lib_calls_pass(&self) {
795        unsafe { LLVMAddPartiallyInlineLibCallsPass(self.pass_manager) }
796    }
797
798    /// Rewrites switch instructions with a sequence of branches,
799    /// which allows targets to get away with not implementing the
800    /// switch instruction until it is convenient.
801    #[llvm_versions(..=16)]
802    pub fn add_lower_switch_pass(&self) {
803        use llvm_sys::transforms::util::LLVMAddLowerSwitchPass;
804
805        unsafe { LLVMAddLowerSwitchPass(self.pass_manager) }
806    }
807
808    /// This file promotes memory references to be register references.
809    /// It promotes alloca instructions which only have loads and stores
810    /// as uses. An alloca is transformed by using dominator frontiers
811    /// to place phi nodes, then traversing the function in depth-first
812    /// order to rewrite loads and stores as appropriate. This is just
813    /// the standard SSA construction algorithm to construct "pruned" SSA form.
814    #[llvm_versions(..=16)]
815    pub fn add_promote_memory_to_register_pass(&self) {
816        use llvm_sys::transforms::util::LLVMAddPromoteMemoryToRegisterPass;
817
818        unsafe { LLVMAddPromoteMemoryToRegisterPass(self.pass_manager) }
819    }
820
821    /// This pass reassociates commutative expressions in an order that is designed
822    /// to promote better constant propagation, GCSE, LICM, PRE, etc.
823    ///
824    /// For example: 4 + (x + 5) ⇒ x + (4 + 5)
825    ///
826    /// In the implementation of this algorithm, constants are assigned rank = 0,
827    /// function arguments are rank = 1, and other values are assigned ranks
828    /// corresponding to the reverse post order traversal of current function
829    /// (starting at 2), which effectively gives values in deep loops higher
830    /// rank than values not in loops.
831    #[llvm_versions(..=16)]
832    pub fn add_reassociate_pass(&self) {
833        unsafe { LLVMAddReassociatePass(self.pass_manager) }
834    }
835
836    /// Sparse conditional constant propagation and merging, which can
837    /// be summarized as:
838    ///
839    /// * Assumes values are constant unless proven otherwise
840    /// * Assumes BasicBlocks are dead unless proven otherwise
841    /// * Proves values to be constant, and replaces them with constants
842    /// * Proves conditional branches to be unconditional
843    ///
844    /// Note that this pass has a habit of making definitions be dead.
845    /// It is a good idea to run a DCE pass sometime after running this pass.
846    #[llvm_versions(..=16)]
847    pub fn add_sccp_pass(&self) {
848        unsafe { LLVMAddSCCPPass(self.pass_manager) }
849    }
850
851    /// No LLVM documentation is available at this time.
852    #[llvm_versions(..=16)]
853    pub fn add_scalar_repl_aggregates_pass(&self) {
854        unsafe { LLVMAddScalarReplAggregatesPass(self.pass_manager) }
855    }
856
857    /// The well-known scalar replacement of aggregates transformation.
858    /// This transform breaks up alloca instructions of aggregate type
859    /// (structure or array) into individual alloca instructions for each
860    /// member if possible. Then, if possible, it transforms the individual
861    /// alloca instructions into nice clean scalar SSA form.
862    #[llvm_versions(..=16)]
863    pub fn add_scalar_repl_aggregates_pass_ssa(&self) {
864        unsafe { LLVMAddScalarReplAggregatesPassSSA(self.pass_manager) }
865    }
866
867    /// No LLVM documentation is available at this time.
868    #[llvm_versions(..=16)]
869    pub fn add_scalar_repl_aggregates_pass_with_threshold(&self, threshold: i32) {
870        unsafe { LLVMAddScalarReplAggregatesPassWithThreshold(self.pass_manager, threshold) }
871    }
872
873    /// No LLVM documentation is available at this time.
874    #[llvm_versions(..=16)]
875    pub fn add_simplify_lib_calls_pass(&self) {
876        unsafe { LLVMAddSimplifyLibCallsPass(self.pass_manager) }
877    }
878
879    /// This file transforms calls of the current function (self recursion) followed
880    /// by a return instruction with a branch to the entry of the function, creating
881    /// a loop. This pass also implements the following extensions to the basic algorithm:
882    ///
883    /// 1. Trivial instructions between the call and return do not prevent the
884    /// transformation from taking place, though currently the analysis cannot support
885    /// moving any really useful instructions (only dead ones).
886    ///
887    /// 2. This pass transforms functions that are prevented from being tail
888    /// recursive by an associative expression to use an accumulator variable, thus
889    /// compiling the typical naive factorial or fib implementation into efficient code.
890    ///
891    /// 3. TRE is performed if the function returns void, if the return returns
892    /// the result returned by the call, or if the function returns a run-time constant
893    /// on all exits from the function. It is possible, though unlikely, that the return
894    /// returns something else (like constant 0), and can still be TRE’d. It can be
895    /// TRE'd if all other return instructions in the function return the exact same value.
896    ///
897    /// 4. If it can prove that callees do not access their caller stack frame,
898    /// they are marked as eligible for tail call elimination (by the code generator).
899    #[llvm_versions(..=16)]
900    pub fn add_tail_call_elimination_pass(&self) {
901        unsafe { LLVMAddTailCallEliminationPass(self.pass_manager) }
902    }
903
904    /// This pass implements constant propagation and merging. It looks for instructions
905    /// involving only constant operands and replaces them with a constant value instead
906    /// of an instruction. For example:
907    ///
908    /// ```ir
909    /// add i32 1, 2
910    /// ```
911    ///
912    /// becomes
913    ///
914    /// ```ir
915    /// i32 3
916    /// ```
917    ///
918    /// NOTE: this pass has a habit of making definitions be dead. It is a good idea to
919    /// run a Dead Instruction Elimination pass sometime after running this pass.
920    ///
921    /// In LLVM 12 and later, this instruction is replaced by the
922    /// [`add_instruction_simplify_pass`].
923    #[cfg(feature = "llvm11-0")]
924    pub fn add_constant_propagation_pass(&self) {
925        unsafe { LLVMAddConstantPropagationPass(self.pass_manager) }
926    }
927
928    /// This pass implements constant propagation and merging. It looks for instructions
929    /// involving only constant operands and replaces them with a constant value instead
930    /// of an instruction. For example:
931    ///
932    /// ```ir
933    /// add i32 1, 2
934    /// ```
935    ///
936    /// becomes
937    ///
938    /// ```ir
939    /// i32 3
940    /// ```
941    ///
942    /// NOTE: this pass has a habit of making definitions be dead. It is a good idea to
943    /// run a Dead Instruction Elimination pass sometime after running this pass.
944    #[llvm_versions(12..=16)]
945    pub fn add_instruction_simplify_pass(&self) {
946        unsafe { LLVMAddInstructionSimplifyPass(self.pass_manager) }
947    }
948
949    /// This file promotes memory references to be register references.
950    /// It promotes alloca instructions which only have loads and stores
951    /// as uses. An alloca is transformed by using dominator frontiers to
952    /// place phi nodes, then traversing the function in depth-first order to
953    /// rewrite loads and stores as appropriate. This is just the standard SSA
954    /// construction algorithm to construct “pruned” SSA form.
955    #[llvm_versions(..=16)]
956    pub fn add_demote_memory_to_register_pass(&self) {
957        unsafe { LLVMAddDemoteMemoryToRegisterPass(self.pass_manager) }
958    }
959
960    /// Verifies an LLVM IR code. This is useful to run after an optimization
961    /// which is undergoing testing. Note that llvm-as verifies its input before
962    /// emitting bitcode, and also that malformed bitcode is likely to make
963    /// LLVM crash. All language front-ends are therefore encouraged to verify
964    /// their output before performing optimizing transformations.
965    ///
966    /// 1. Both of a binary operator’s parameters are of the same type.
967    ///
968    /// 2. Verify that the indices of mem access instructions match other operands.
969    ///
970    /// 3. Verify that arithmetic and other things are only performed on
971    /// first-class types. Verify that shifts and logicals only happen on
972    /// integrals f.e.
973    ///
974    /// 4. All of the constants in a switch statement are of the correct type.
975    ///
976    /// 5. The code is in valid SSA form.
977    ///
978    /// 6. It is illegal to put a label into any other type (like a structure)
979    /// or to return one.
980    ///
981    /// 7. Only phi nodes can be self referential: %x = add i32 %x, %x is invalid.
982    ///
983    /// 8. PHI nodes must have an entry for each predecessor, with no extras.
984    ///
985    /// 9. PHI nodes must be the first thing in a basic block, all grouped together.
986    ///
987    /// 10. PHI nodes must have at least one entry.
988    ///
989    /// 11. All basic blocks should only end with terminator insts, not contain them.
990    ///
991    /// 12. The entry node to a function must not have predecessors.
992    ///
993    /// 13. All Instructions must be embedded into a basic block.
994    ///
995    /// 14. Functions cannot take a void-typed parameter.
996    ///
997    /// 15. Verify that a function’s argument list agrees with its declared type.
998    ///
999    /// 16. It is illegal to specify a name for a void value.
1000    ///
1001    /// 17. It is illegal to have an internal global value with no initializer.
1002    ///
1003    /// 18. It is illegal to have a ret instruction that returns a value that does
1004    /// not agree with the function return value type.
1005    ///
1006    /// 19. Function call argument types match the function prototype.
1007    ///
1008    /// 20. All other things that are tested by asserts spread about the code.
1009    ///
1010    /// Note that this does not provide full security verification (like Java), but instead just tries to ensure that code is well-formed.
1011    #[llvm_versions(..=16)]
1012    pub fn add_verifier_pass(&self) {
1013        unsafe { LLVMAddVerifierPass(self.pass_manager) }
1014    }
1015
1016    /// No LLVM documentation is available at this time.
1017    #[llvm_versions(..=16)]
1018    pub fn add_correlated_value_propagation_pass(&self) {
1019        unsafe { LLVMAddCorrelatedValuePropagationPass(self.pass_manager) }
1020    }
1021
1022    /// No LLVM documentation is available at this time.
1023    #[llvm_versions(..=16)]
1024    pub fn add_early_cse_pass(&self) {
1025        unsafe { LLVMAddEarlyCSEPass(self.pass_manager) }
1026    }
1027
1028    #[llvm_versions(..=16)]
1029    /// No LLVM documentation is available at this time.
1030    pub fn add_early_cse_mem_ssa_pass(&self) {
1031        use llvm_sys::transforms::scalar::LLVMAddEarlyCSEMemSSAPass;
1032
1033        unsafe { LLVMAddEarlyCSEMemSSAPass(self.pass_manager) }
1034    }
1035
1036    /// No LLVM documentation is available at this time.
1037    #[llvm_versions(..=16)]
1038    pub fn add_lower_expect_intrinsic_pass(&self) {
1039        unsafe { LLVMAddLowerExpectIntrinsicPass(self.pass_manager) }
1040    }
1041
1042    /// No LLVM documentation is available at this time.
1043    #[llvm_versions(..=16)]
1044    pub fn add_type_based_alias_analysis_pass(&self) {
1045        unsafe { LLVMAddTypeBasedAliasAnalysisPass(self.pass_manager) }
1046    }
1047
1048    /// No LLVM documentation is available at this time.
1049    #[llvm_versions(..=16)]
1050    pub fn add_scoped_no_alias_aa_pass(&self) {
1051        unsafe { LLVMAddScopedNoAliasAAPass(self.pass_manager) }
1052    }
1053
1054    /// A basic alias analysis pass that implements identities
1055    /// (two different globals cannot alias, etc), but does no
1056    /// stateful analysis.
1057    #[llvm_versions(..=16)]
1058    pub fn add_basic_alias_analysis_pass(&self) {
1059        unsafe { LLVMAddBasicAliasAnalysisPass(self.pass_manager) }
1060    }
1061
1062    #[llvm_versions(..=15)]
1063    pub fn add_aggressive_inst_combiner_pass(&self) {
1064        unsafe { LLVMAddAggressiveInstCombinerPass(self.pass_manager) }
1065    }
1066
1067    #[llvm_versions(..=16)]
1068    pub fn add_loop_unroll_and_jam_pass(&self) {
1069        use llvm_sys::transforms::scalar::LLVMAddLoopUnrollAndJamPass;
1070
1071        unsafe { LLVMAddLoopUnrollAndJamPass(self.pass_manager) }
1072    }
1073
1074    #[llvm_versions(..15)]
1075    pub fn add_coroutine_early_pass(&self) {
1076        use llvm_sys::transforms::coroutines::LLVMAddCoroEarlyPass;
1077
1078        unsafe { LLVMAddCoroEarlyPass(self.pass_manager) }
1079    }
1080
1081    #[llvm_versions(..15)]
1082    pub fn add_coroutine_split_pass(&self) {
1083        use llvm_sys::transforms::coroutines::LLVMAddCoroSplitPass;
1084
1085        unsafe { LLVMAddCoroSplitPass(self.pass_manager) }
1086    }
1087
1088    #[llvm_versions(..15)]
1089    pub fn add_coroutine_elide_pass(&self) {
1090        use llvm_sys::transforms::coroutines::LLVMAddCoroElidePass;
1091
1092        unsafe { LLVMAddCoroElidePass(self.pass_manager) }
1093    }
1094
1095    #[llvm_versions(..15)]
1096    pub fn add_coroutine_cleanup_pass(&self) {
1097        use llvm_sys::transforms::coroutines::LLVMAddCoroCleanupPass;
1098
1099        unsafe { LLVMAddCoroCleanupPass(self.pass_manager) }
1100    }
1101}
1102
1103#[allow(deprecated)]
1104impl<T> Drop for PassManager<T> {
1105    fn drop(&mut self) {
1106        unsafe { LLVMDisposePassManager(self.pass_manager) }
1107    }
1108}
1109
1110#[llvm_versions(..=16)]
1111#[derive(Debug)]
1112pub struct PassRegistry {
1113    pass_registry: LLVMPassRegistryRef,
1114}
1115
1116#[llvm_versions(..=16)]
1117impl PassRegistry {
1118    pub unsafe fn new(pass_registry: LLVMPassRegistryRef) -> PassRegistry {
1119        assert!(!pass_registry.is_null());
1120
1121        PassRegistry { pass_registry }
1122    }
1123
1124    /// Acquires the underlying raw pointer belonging to this `PassRegistry` type.
1125    pub fn as_mut_ptr(&self) -> LLVMPassRegistryRef {
1126        self.pass_registry
1127    }
1128
1129    pub fn get_global() -> PassRegistry {
1130        let pass_registry = unsafe { LLVMGetGlobalPassRegistry() };
1131
1132        unsafe { PassRegistry::new(pass_registry) }
1133    }
1134
1135    pub fn initialize_core(&self) {
1136        unsafe { LLVMInitializeCore(self.pass_registry) }
1137    }
1138
1139    pub fn initialize_transform_utils(&self) {
1140        unsafe { LLVMInitializeTransformUtils(self.pass_registry) }
1141    }
1142
1143    pub fn initialize_scalar_opts(&self) {
1144        unsafe { LLVMInitializeScalarOpts(self.pass_registry) }
1145    }
1146
1147    #[llvm_versions(..=15)]
1148    pub fn initialize_obj_carc_opts(&self) {
1149        unsafe { LLVMInitializeObjCARCOpts(self.pass_registry) }
1150    }
1151
1152    pub fn initialize_vectorization(&self) {
1153        unsafe { LLVMInitializeVectorization(self.pass_registry) }
1154    }
1155
1156    pub fn initialize_inst_combine(&self) {
1157        unsafe { LLVMInitializeInstCombine(self.pass_registry) }
1158    }
1159
1160    // Let us begin our initial public offering
1161    pub fn initialize_ipo(&self) {
1162        unsafe { LLVMInitializeIPO(self.pass_registry) }
1163    }
1164
1165    #[llvm_versions(..=15)]
1166    pub fn initialize_instrumentation(&self) {
1167        unsafe { LLVMInitializeInstrumentation(self.pass_registry) }
1168    }
1169
1170    pub fn initialize_analysis(&self) {
1171        unsafe { LLVMInitializeAnalysis(self.pass_registry) }
1172    }
1173
1174    pub fn initialize_ipa(&self) {
1175        unsafe { LLVMInitializeIPA(self.pass_registry) }
1176    }
1177
1178    pub fn initialize_codegen(&self) {
1179        unsafe { LLVMInitializeCodeGen(self.pass_registry) }
1180    }
1181
1182    pub fn initialize_target(&self) {
1183        unsafe { LLVMInitializeTarget(self.pass_registry) }
1184    }
1185
1186    #[llvm_versions(..=15)]
1187    pub fn initialize_aggressive_inst_combiner(&self) {
1188        use llvm_sys::initialization::LLVMInitializeAggressiveInstCombiner;
1189
1190        unsafe { LLVMInitializeAggressiveInstCombiner(self.pass_registry) }
1191    }
1192}
1193
1194#[llvm_versions(13..)]
1195#[derive(Debug)]
1196pub struct PassBuilderOptions {
1197    pub(crate) options_ref: LLVMPassBuilderOptionsRef,
1198}
1199
1200#[llvm_versions(13..)]
1201impl PassBuilderOptions {
1202    /// Create a new set of options for a PassBuilder
1203    pub fn create() -> Self {
1204        unsafe {
1205            PassBuilderOptions {
1206                options_ref: LLVMCreatePassBuilderOptions(),
1207            }
1208        }
1209    }
1210
1211    /// Acquires the underlying raw pointer belonging to this `PassBuilderOptions` type.
1212    pub fn as_mut_ptr(&self) -> LLVMPassBuilderOptionsRef {
1213        self.options_ref
1214    }
1215
1216    ///Toggle adding the VerifierPass for the PassBuilder, ensuring all functions inside the module is valid.
1217    pub fn set_verify_each(&self, value: bool) {
1218        unsafe {
1219            LLVMPassBuilderOptionsSetVerifyEach(self.options_ref, value as i32);
1220        }
1221    }
1222
1223    ///Toggle debug logging when running the PassBuilder.
1224    pub fn set_debug_logging(&self, value: bool) {
1225        unsafe {
1226            LLVMPassBuilderOptionsSetDebugLogging(self.options_ref, value as i32);
1227        }
1228    }
1229
1230    pub fn set_loop_interleaving(&self, value: bool) {
1231        unsafe {
1232            LLVMPassBuilderOptionsSetLoopInterleaving(self.options_ref, value as i32);
1233        }
1234    }
1235
1236    pub fn set_loop_vectorization(&self, value: bool) {
1237        unsafe {
1238            LLVMPassBuilderOptionsSetLoopVectorization(self.options_ref, value as i32);
1239        }
1240    }
1241
1242    pub fn set_loop_slp_vectorization(&self, value: bool) {
1243        unsafe {
1244            LLVMPassBuilderOptionsSetSLPVectorization(self.options_ref, value as i32);
1245        }
1246    }
1247
1248    pub fn set_loop_unrolling(&self, value: bool) {
1249        unsafe {
1250            LLVMPassBuilderOptionsSetLoopUnrolling(self.options_ref, value as i32);
1251        }
1252    }
1253
1254    pub fn set_forget_all_scev_in_loop_unroll(&self, value: bool) {
1255        unsafe {
1256            LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll(self.options_ref, value as i32);
1257        }
1258    }
1259
1260    pub fn set_licm_mssa_opt_cap(&self, value: u32) {
1261        unsafe {
1262            LLVMPassBuilderOptionsSetLicmMssaOptCap(self.options_ref, value);
1263        }
1264    }
1265
1266    pub fn set_licm_mssa_no_acc_for_promotion_cap(&self, value: u32) {
1267        unsafe {
1268            LLVMPassBuilderOptionsSetLicmMssaNoAccForPromotionCap(self.options_ref, value);
1269        }
1270    }
1271
1272    pub fn set_call_graph_profile(&self, value: bool) {
1273        unsafe {
1274            LLVMPassBuilderOptionsSetCallGraphProfile(self.options_ref, value as i32);
1275        }
1276    }
1277
1278    pub fn set_merge_functions(&self, value: bool) {
1279        unsafe {
1280            LLVMPassBuilderOptionsSetMergeFunctions(self.options_ref, value as i32);
1281        }
1282    }
1283}
1284
1285#[llvm_versions(13..)]
1286impl Drop for PassBuilderOptions {
1287    fn drop(&mut self) {
1288        unsafe {
1289            LLVMDisposePassBuilderOptions(self.options_ref);
1290        }
1291    }
1292}