Expand description

githubcrates-io


This crate gives the ability to safely implement passes for the new LLVM pass manager, by leveraging the strongly typed interface provided by Inkwell.

If you have never developed LLVM passes before, perhaps you should take a look at this LLVM guide before carrying on. It will give you a simple overview of the C++ API wrapped by this crate.

If you want a deeper understanding of the many concepts surrounding the new LLVM pass manager, you should read the official LLVM documentation.

Example

A simple LLVM plugin which defines two passes, one being a transformation pass that queries the result of a second pass, an analysis one:

// Define an LLVM plugin (a name and a version is required). Only cdylib crates
// should define plugins, and only one definition should be done per crate.
#[llvm_plugin::plugin(name = "plugin_name", version = "0.1")]
mod plugin {
    use llvm_plugin::{
        LlvmModuleAnalysis, LlvmModulePass, ModuleAnalysisManager, PreservedAnalyses,
    };
    use llvm_plugin::inkwell::module::Module;

    // Must implement the `Default` trait.
    #[derive(Default)]
    struct Pass1;

    // Define a transformation pass (a name is required). Such pass is allowed to
    // mutate the LLVM IR. If it does, it should return `PreservedAnalysis::None`
    // to notify the pass manager that all analyses are now invalidated.
    #[pass(name = "pass_name")]
    impl LlvmModulePass for Pass1 {
        fn run_pass(
            &self,
            module: &mut Module,
            manager: &ModuleAnalysisManager,
        ) -> PreservedAnalyses {
            // Ask the pass manager for the result of the analysis pass `Analysis1`
            // defined further below. If the result is not in cache, the pass
            // manager will call `Analysis1::run_analysis`.
            let result = manager.get_result::<Analysis1>(module);

            assert_eq!(result, "Hello World!");

            // no modification was made on the module, so the pass manager doesn't have
            // to recompute any analysis
            PreservedAnalyses::All
        }
    }

    // Must implement the `Default` trait.
    #[derive(Default)]
    struct Analysis1;

    // Define an analysis pass. Such pass is not allowed to mutate the LLVM IR. It should
    // be used only for inspection of the LLVM IR, and can return some result that will be
    // efficiently cached by the pass manager (to prevent recomputing the same analysis
    // every time its result is needed).
    #[analysis]
    impl LlvmModuleAnalysis for Analysis1 {
        fn run_analysis(
            &self,
            module: &Module,
            manager: &ModuleAnalysisManager,
        ) -> String {
            // .. inspect the LLVM IR of the module ..

            "Hello World!".to_owned()
        }
    }
}

Re-exports

pub use inkwell;

Modules

Utilities.

Structs

Struct allowing to query the pass manager for the result of analyses on function IR.

Struct allowing to make queries to the pass manager about function-level analyses.

Struct allowing to query the pass manager for the result of analyses on module IR.

Enums

Enum specifying whether analyses on an IR unit are not preserved due to the modification of such unit by a transformation pass.

Traits

Trait to use for implementing an analysis pass on an LLVM function.

Trait to use for implementing a transformation pass on an LLVM function.

Trait to use for implementing an analysis pass on an LLVM module.

Trait to use for implementing a transformation pass on an LLVM module.

Attribute Macros

Macro for defining a new LLVM plugin.