{"id":13667961,"url":"https://github.com/jamesmth/llvm-plugin-rs","last_synced_at":"2025-04-08T15:02:24.547Z","repository":{"id":58807549,"uuid":"522055643","full_name":"jamesmth/llvm-plugin-rs","owner":"jamesmth","description":"Out-of-tree LLVM passes in Rust","archived":false,"fork":false,"pushed_at":"2025-01-18T13:19:00.000Z","size":146,"stargazers_count":180,"open_issues_count":4,"forks_count":13,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-01T14:01:42.669Z","etag":null,"topics":["ffi","llvm-pass","rust","safe"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jamesmth.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-06T21:16:59.000Z","updated_at":"2025-03-25T01:18:21.000Z","dependencies_parsed_at":"2024-01-14T16:14:57.174Z","dependency_job_id":"b0b8e220-290e-4fd8-ac2d-59d0e3ea0716","html_url":"https://github.com/jamesmth/llvm-plugin-rs","commit_stats":{"total_commits":57,"total_committers":2,"mean_commits":28.5,"dds":0.01754385964912286,"last_synced_commit":"6d414fa93a4f8cb14182f1f38ba6da9bef9c7c01"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmth%2Fllvm-plugin-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmth%2Fllvm-plugin-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmth%2Fllvm-plugin-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmth%2Fllvm-plugin-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jamesmth","download_url":"https://codeload.github.com/jamesmth/llvm-plugin-rs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247866071,"owners_count":21009239,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ffi","llvm-pass","rust","safe"],"created_at":"2024-08-02T07:00:56.201Z","updated_at":"2025-04-08T15:02:24.517Z","avatar_url":"https://github.com/jamesmth.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"llvm-plugin-rs \n==============\n\n[\u003cimg alt=\"version\" src=\"https://img.shields.io/crates/v/llvm-plugin.svg?style=for-the-badge\u0026color=fc8d62\u0026logo=rust\" height=\"20\"\u003e](https://crates.io/crates/llvm-plugin)\n[\u003cimg alt=\"doc\" src=\"https://img.shields.io/badge/docs.rs-llvm--plugin-66c2a5?style=for-the-badge\u0026labelColor=555555\u0026logo=docs.rs\" height=\"20\"\u003e](https://docs.rs/llvm-plugin)\n[\u003cimg alt=\"linux\" src=\"https://img.shields.io/github/actions/workflow/status/jamesmth/llvm-plugin-rs/linux.yml?branch=master\u0026label=linux\u0026style=for-the-badge\u0026logo=linux\" height=\"20\"\u003e](https://github.com/jamesmth/llvm-plugin-rs/actions/workflows/linux.yml?query=branch%3Amaster)\n[\u003cimg alt=\"windows\" src=\"https://img.shields.io/github/actions/workflow/status/jamesmth/llvm-plugin-rs/windows.yml?branch=master\u0026label=windows\u0026style=for-the-badge\u0026logo=windows\" height=\"20\"\u003e](https://github.com/jamesmth/llvm-plugin-rs/actions/workflows/windows.yml?query=branch%3Amaster)\n[\u003cimg alt=\"macos\" src=\"https://img.shields.io/github/actions/workflow/status/jamesmth/llvm-plugin-rs/macos.yml?branch=master\u0026label=macos\u0026style=for-the-badge\u0026logo=apple\" height=\"20\"\u003e](https://github.com/jamesmth/llvm-plugin-rs/actions/workflows/macos.yml?query=branch%3Amaster)\n\nThis crate gives the ability to safely implement passes for the [new LLVM pass manager], by leveraging the strongly typed interface\nprovided by [Inkwell].\n\nIf you have never developed LLVM passes before, you can take a look at the available [examples]. They will (hopefully) give you a\nbetter idea of how to use this crate.\n\nIf you want a deeper understanding of the many concepts surrounding the new LLVM pass manager, you should read the [official LLVM\ndocumentation].\n\n[Inkwell]: https://github.com/TheDan64/inkwell\n[new LLVM pass manager]: https://blog.llvm.org/posts/2021-03-26-the-new-pass-manager/\n[examples]: https://github.com/jamesmth/llvm-plugin-rs/tree/master/examples\n[official LLVM documentation]: https://llvm.org/docs/NewPassManager.html\n\n## Usage\n\nWhen importing this crate in your `Cargo.toml`, you will need to specify the LLVM version to use with a corresponding feature flag:\n\n```toml\n[dependencies]\nllvm-plugin = { version = \"0.6\", features = [\"llvm18-1\"] }\n```\n\nSupported versions: LLVM 10-18 mapping to a cargo feature flag `llvmX-Y` where `X` and `Y` are the LLVM major and minor versions.\n\n## Getting Started\n\nAn LLVM plugin is merely a dylib that is given a [PassBuilder] by the LLVM tool (e.g. [opt], [lld])\nloading it.\nTherefore, you must add the following line in your `Cargo.toml`:\n\n```toml\n[lib]\ncrate-type = [\"cdylib\"]\n```\n\nA [PassBuilder] allows registering callbacks on specific actions being performed by the LLVM tool.\n\nFor instance, the `--passes` parameter of [opt] allows specifying a custom pass pipeline to be run on a given IR module. A plugin\ncould therefore register a callback for parsing an element of the given pipeline (e.g. a pass name), in order to insert a custom\npass to run by [opt].\n\nThe following code illustrates the idea:\n\n```rust\nuse llvm_plugin::inkwell::module::Module;\nuse llvm_plugin::{\n    LlvmModulePass, ModuleAnalysisManager, PassBuilder, PipelineParsing, PreservedAnalyses,\n};\n\n// A name and version is required.\n#[llvm_plugin::plugin(name = \"plugin_name\", version = \"0.1\")]\nfn plugin_registrar(builder: \u0026mut PassBuilder) {\n    // Add a callback to parse a name from the textual representation of\n    // the pipeline to be run.\n    builder.add_module_pipeline_parsing_callback(|name, manager| {\n        if name == \"custom-pass\" {\n            // the input pipeline contains the name \"custom-pass\",\n            // so we add our custom pass to the pass manager\n            manager.add_pass(CustomPass);\n\n            // we notify the caller that we were able to parse\n            // the given name\n            PipelineParsing::Parsed\n        } else {\n            // in any other cases, we notify the caller that our\n            // callback wasn't able to parse the given name\n            PipelineParsing::NotParsed\n        }\n    });\n}\n\nstruct CustomPass;\nimpl LlvmModulePass for CustomPass {\n    fn run_pass(\n        \u0026self,\n        module: \u0026mut Module,\n        manager: \u0026ModuleAnalysisManager\n    ) -\u003e PreservedAnalyses {\n        // transform the IR\n        todo!()\n    }\n}\n```\n\nNow, executing this command would run our custom pass on some input `module.bc`:\n\n```bash\nopt --load-pass-plugin=libplugin.so --passes=custom-pass module.bc -disable-output\n```\n\nHowever, executing this command would not (`custom-pass2` cannot be parsed by our plugin):\n\n```bash\nopt --load-pass-plugin=libplugin.so --passes=custom-pass2 module.bc -disable-output\n```\n\nMore callbacks are available, read the [documentation] for more details.\n\nTo learn more about how to sequentially apply more than one pass, read this [opt guide].\n\n[opt]: https://www.llvm.org/docs/CommandGuide/opt.html\n[lld]: https://lld.llvm.org/\n[PassBuilder]: https://docs.rs/llvm-plugin/latest/llvm_plugin/struct.PassBuilder.html\n[documentation]: https://docs.rs/llvm-plugin\n[opt guide]: https://llvm.org/docs/NewPassManager.html#invoking-opt\n\n## Linux \u0026 MacOS Requirements\n\nYour LLVM toolchain should dynamically link the LLVM library. Fortunately, this is the case for toolchains\ndistributed on `apt` and `homebrew` registeries.\n\n\u003cdetails\u003e\n \u003csummary\u003e\u003cem\u003eInstall LLVM-14 with apt\u003c/em\u003e\u003c/summary\u003e\n\n ```shell\n $ apt install llvm-14\n ```\n\n \u003c/details\u003e\n\n\u003cdetails\u003e\n \u003csummary\u003e\u003cem\u003eInstall LLVM-14 with homebrew\u003c/em\u003e\u003c/summary\u003e\n\n ```shell\n $ brew install llvm@14\n ```\n\n \u003c/details\u003e\n\nIf you don't use any of these package managers, you can download a compatible LLVM toolchain from\nthis [LLVM fork] instead. In this case, don't forget to update your `PATH` environment variable with\nyour LLVM toolchain path, or use the `LLVM_SYS_XXX_PREFIX` environment variable to locate your toolchain.\n\nFor instance, if your LLVM-14 toolchain is located at `~/llvm`, you should set either of the following:\n- `PATH=$PATH;$HOME/llvm/bin`\n- `LLVM_SYS_140_PREFIX=$HOME/llvm`\n\n## Windows Requirements\n\nThe official LLVM toolchain for Windows was not built with plugin support. However, compatible toolchains can be found\n[here](https://github.com/jamesmth/llvm-project/releases).\n\nDon't forget to update your `PATH` environment variable with your LLVM toolchain path, or use the `LLVM_SYS_XXX_PREFIX`\nenvironment variable to locate your toolchain.\n\nFor instance, if your LLVM-14 toolchain is located at `C:\\llvm`, you should set either of the following:\n- `PATH=$PATH;C:\\llvm\\bin`\n- `LLVM_SYS_140_PREFIX=C:\\llvm`\n\n## Compiling Rust/C++ code with custom LLVM plugins\n\nThis [LLVM fork] explains how to do so, and provides LLVM toolchains that will make the process easier.\n\n[LLVM fork]: https://github.com/jamesmth/llvm-project\n\n## Missing Features\n\n- Support for loop passes (`Inkwell` doesn't currently provide safe wrappers)\n- Support for CGSCC passes (`Inkwell` doesn't currently provide safe wrappers)\n- FFI over the full manager proxy API (only a subset is currently implemented)\n- FFI over the full analysis invalidation API (only a subset is currently implemented)\n- FFI over builtin LLVM analyses (e.g. dominator tree)\n\nContributions are very welcome, make sure to check out the [Contributing Guide] first!\n\n[Contributing Guide]: ./.github/CONTRIBUTING.md\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesmth%2Fllvm-plugin-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjamesmth%2Fllvm-plugin-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesmth%2Fllvm-plugin-rs/lists"}