llvm_plugin_inkwell/
passes.rs

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