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