Code Monkey home page Code Monkey logo

llvm-plugin-rs's Introduction

llvm-plugin-rs

version doc linux windows macos

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, you can take a look at the available examples. They will (hopefully) give you a better idea of how to use 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.

Usage

When importing this crate in your Cargo.toml, you will need to specify the LLVM version to use with a corresponding feature flag:

[dependencies]
llvm-plugin = { version = "0.3", features = ["llvm10-0"] }

Supported versions:

LLVM Version Cargo Feature Flag Linux Windows MacOS
10.0.x llvm10-0
11.0.x llvm11-0
12.0.x llvm12-0
13.0.x llvm13-0
14.0.x llvm14-0
15.0.x llvm15-0

Getting Started

An LLVM plugin is merely a dylib that is given a PassBuilder by the LLVM tool (e.g. opt, lld) loading it. Therefore, you must add the following line in your Cargo.toml:

[lib]
crate-type = ["cdylib"]

A PassBuilder allows registering callbacks on specific actions being performed by the LLVM tool.

For instance, the --passes parameter of opt allows specifying a custom pass pipeline to be run on a given IR module. A plugin could therefore register a callback for parsing an element of the given pipeline (e.g. a pass name), in order to insert a custom pass to run by opt.

The following code illustrates the idea:

use llvm_plugin::inkwell::module::Module;
use llvm_plugin::{
    LlvmModulePass, ModuleAnalysisManager, PassBuilder, PipelineParsing, PreservedAnalyses,
};

// A name and version is required.
#[llvm_plugin::plugin(name = "plugin_name", version = "0.1")]
fn plugin_registrar(builder: &mut PassBuilder) {
    // Add a callback to parse a name from the textual representation of
    // the pipeline to be run.
    builder.add_module_pipeline_parsing_callback(|name, manager| {
        if name == "custom-pass" {
            // the input pipeline contains the name "custom-pass",
            // so we add our custom pass to the pass manager
            manager.add_pass(CustomPass);

            // we notify the caller that we were able to parse
            // the given name
            PipelineParsing::Parsed
        } else {
            // in any other cases, we notify the caller that our
            // callback wasn't able to parse the given name
            PipelineParsing::NotParsed
        }
    });
}

struct CustomPass;
impl LlvmModulePass for CustomPass {
    fn run_pass(
        &self,
        module: &mut Module,
        manager: &ModuleAnalysisManager
    ) -> PreservedAnalyses {
        // transform the IR
        todo!()
    }
}

Now, executing this command would run our custom pass on some input module.bc:

opt --load-pass-plugin=libplugin.so --passes=custom-pass module.bc -disable-output

However, executing this command would not (custom-pass2 cannot be parsed by our plugin):

opt --load-pass-plugin=libplugin.so --passes=custom-pass2 module.bc -disable-output

More callbacks are available, read the documentation for more details.

To learn more about how to sequentially apply more than one pass, read this opt guide.

Linux & MacOS Requirements

Your LLVM toolchain should dynamically link the LLVM library. Fortunately, this is the case for toolchains distributed on apt and homebrew registeries.

Install LLVM-14 with apt
$ apt install llvm-14
Install LLVM-14 with homebrew
$ brew install llvm@14

If you don't use any of these package managers, you can download a compatible LLVM toolchain from this LLVM fork instead. In this case, don't forget to update your PATH environment variable with your LLVM toolchain path, or use the LLVM_SYS_XXX_PREFIX environment variable to locate your toolchain.

For instance, if your LLVM-14 toolchain is located at ~/llvm, you should set either of the following:

  • PATH=$PATH;$HOME/llvm/bin
  • LLVM_SYS_140_PREFIX=$HOME/llvm

Windows Requirements

The official LLVM toolchain for Windows was not built with plugin support. However, compatible toolchains can be found here.

Don't forget to update your PATH environment variable with your LLVM toolchain path, or use the LLVM_SYS_XXX_PREFIX environment variable to locate your toolchain.

For instance, if your LLVM-14 toolchain is located at C:\llvm, you should set either of the following:

  • PATH=$PATH;C:\llvm\bin
  • LLVM_SYS_140_PREFIX=C:\llvm

Compiling Rust/C++ code with custom LLVM plugins

This LLVM fork explains how to do so, and provides LLVM toolchains that will make the process easier.

Missing Features

  • Support for loop passes (Inkwell doesn't currently provide safe wrappers)
  • Support for CGSCC passes (Inkwell doesn't currently provide safe wrappers)
  • FFI over the full manager proxy API (only a subset is currently implemented)
  • FFI over the full analysis invalidation API (only a subset is currently implemented)
  • FFI over builtin LLVM analyses (e.g. dominator tree)

Contributions are very welcome, make sure to check out the Contributing Guide first!

llvm-plugin-rs's People

Contributors

jamesmth avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.