| # Updating LLVM | |
| Rust supports building against multiple LLVM versions: | |
| * Tip-of-tree for the current LLVM development branch is usually supported within a few days. | |
| PRs for such fixes are tagged with `llvm-main`. | |
| * The latest released major version is always supported. | |
| * The one or two preceding major versions are usually supported in the sense that they are expected | |
| to build successfully and pass most tests. | |
| However, fixes for miscompilations often do not get | |
| backported to past LLVM versions, so using rustc with older versions of LLVM comes with an | |
| increased risk of soundness bugs. | |
| We strongly recommend using the latest version of LLVM. | |
| By default, Rust uses its own fork in the [rust-lang/llvm-project repository]. | |
| This fork is based on a `release/$N.x` branch of the upstream project, where | |
| `$N` is either the latest released major version, or the current major version | |
| in release candidate phase. | |
| The fork is never based on the `main` development branch. | |
| Our LLVM fork only accepts: | |
| * Backports of changes that have already landed upstream. | |
| * Workarounds for build issues affecting our CI environment. | |
| With the exception of one grandfathered-in patch for SGX enablement, we do not | |
| accept functional patches that have not been upstreamed first. | |
| There are three types of LLVM updates, with different procedures: | |
| * Backports while the current major LLVM version is supported. | |
| * Backports while the current major LLVM version is no longer supported (or | |
| the change is not eligible for upstream backport). | |
| * Update to a new major LLVM version. | |
| ## Backports (upstream supported) | |
| While the current major LLVM version is supported upstream, fixes should be | |
| backported upstream first, and the release branch then merged back into the Rust fork. | |
| 1. Make sure the bugfix is in upstream LLVM. | |
| 2. If this hasn't happened already, request a backport to the upstream release branch. | |
| If you have LLVM commit access, follow the [backport process]. | |
| Otherwise, open an issue requesting the backport. | |
| Continue once the backport has been approved and merged. | |
| 3. Identify the branch that rustc is currently using. | |
| The `src/llvm-project` submodule is always pinned to a branch of the | |
| [rust-lang/llvm-project repository]. | |
| 4. Fork the rust-lang/llvm-project repository. | |
| 5. Check out the appropriate branch (typically named `rustc/a.b-yyyy-mm-dd`). | |
| 6. Add a remote for the upstream repository using | |
| `git remote add upstream https://github.com/llvm/llvm-project.git` and | |
| fetch it using `git fetch upstream`. | |
| 7. Merge the `upstream/release/$N.x` branch. | |
| 8. Push this branch to your fork. | |
| 9. Send a Pull Request to rust-lang/llvm-project to the same branch as before. | |
| Be sure to reference the Rust and/or LLVM issue that you're fixing in the PR description. | |
| 10. Wait for the PR to be merged. | |
| 11. Send a PR to rust-lang/rust updating the `src/llvm-project` submodule with your bugfix. | |
| This can be done locally with `git submodule update --remote src/llvm-project` typically. | |
| 12. Wait for PR to be merged. | |
| An example PR: [#59089](https://github.com/rust-lang/rust/pull/59089) | |
| ## Backports (upstream not supported) | |
| Upstream LLVM releases are only supported for two to three months after the GA release. | |
| Once upstream backports are no longer accepted, changes should be | |
| cherry-picked directly to our fork. | |
| 1. Make sure the bugfix is in upstream LLVM. | |
| 2. Identify the branch that rustc is currently using. | |
| The `src/llvm-project` submodule is always pinned to a branch of the | |
| [rust-lang/llvm-project repository]. | |
| 3. Fork the rust-lang/llvm-project repository. | |
| 4. Check out the appropriate branch (typically named `rustc/a.b-yyyy-mm-dd`). | |
| 5. Add a remote for the upstream repository using | |
| `git remote add upstream https://github.com/llvm/llvm-project.git` and | |
| fetch it using `git fetch upstream`. | |
| 6. Cherry-pick the relevant commit(s) using `git cherry-pick -x`. | |
| 7. Push this branch to your fork. | |
| 8. Send a Pull Request to rust-lang/llvm-project to the same branch as before. | |
| Be sure to reference the Rust and/or LLVM issue that you're fixing in the PR description. | |
| 9. Wait for the PR to be merged. | |
| 10. Send a PR to rust-lang/rust updating the `src/llvm-project` submodule with your bugfix. | |
| This can be done locally with `git submodule update --remote src/llvm-project` typically. | |
| 11. Wait for PR to be merged. | |
| An example PR: [#59089](https://github.com/rust-lang/rust/pull/59089) | |
| ## New LLVM Release Updates | |
| Unlike bugfixes, | |
| updating to a new release of LLVM typically requires a lot more work. | |
| This is where we can't reasonably cherry-pick commits backwards, | |
| so we need to do a full update. | |
| There's a lot of stuff to do here, | |
| so let's go through each in detail. | |
| 1. LLVM announces that its latest release version has branched. | |
| This will show up as a branch in the [llvm/llvm-project repository], | |
| typically named `release/$N.x`, | |
| where `$N` is the version of LLVM that's being released. | |
| 1. Create a new branch in the [rust-lang/llvm-project repository] | |
| from this `release/$N.x` branch, | |
| and name it `rustc/a.b-yyyy-mm-dd`, | |
| where `a.b` is the current version number of LLVM in-tree at the time of the branch, | |
| and the remaining part is the current date. | |
| 1. Apply Rust-specific patches to the llvm-project repository. | |
| All features and bugfixes are upstream, | |
| but there's often some weird build-related patches that don't make sense to upstream. | |
| These patches are typically the latest patches in the | |
| rust-lang/llvm-project branch that rustc is currently using. | |
| 1. Build the new LLVM in the `rust` repository. | |
| To do this, | |
| you'll want to update the `src/llvm-project` repository to your branch, | |
| and the revision you've created. | |
| It's also typically a good idea to update `.gitmodules` with the new | |
| branch name of the LLVM submodule. | |
| Make sure you've committed changes to | |
| `src/llvm-project` to ensure submodule updates aren't reverted. | |
| Some commands you should execute are: | |
| * `./x build src/llvm-project` - test that LLVM still builds | |
| * `./x build` - build the rest of rustc | |
| You'll likely need to update [`llvm-wrapper/*.cpp`][`llvm-wrapper`] | |
| to compile with updated LLVM bindings. | |
| Note that you should use `#ifdef` and such to ensure | |
| that the bindings still compile on older LLVM versions. | |
| Note that `profile = "compiler"` and other defaults set by `./x setup` | |
| download LLVM from CI instead of building it from source. | |
| You should disable this temporarily to make sure your changes are being used. | |
| This is done by having the following setting in `bootstrap.toml`: | |
| ```toml | |
| llvm.download-ci-llvm = false | |
| ``` | |
| 1. Test for regressions across other platforms. | |
| LLVM often has at least one bug | |
| for non-tier-1 architectures, so it's good to do some more testing before | |
| sending this to bors! | |
| If you're low on resources you can send the PR as-is | |
| now to bors, though, and it'll get tested anyway. | |
| Ideally, build LLVM and test it on a few platforms: | |
| * Linux | |
| * macOS | |
| * Windows | |
| Afterwards, run some docker containers that CI also does: | |
| * `./src/ci/docker/run.sh wasm32` | |
| * `./src/ci/docker/run.sh arm-android` | |
| * `./src/ci/docker/run.sh dist-various-1` | |
| * `./src/ci/docker/run.sh dist-various-2` | |
| * `./src/ci/docker/run.sh armhf-gnu` | |
| 1. Prepare a PR to `rust-lang/rust`. | |
| Work with maintainers of | |
| `rust-lang/llvm-project` to get your commit in a branch of that repository, | |
| and then you can send a PR to `rust-lang/rust`. | |
| You'll change at least | |
| `src/llvm-project` and will likely also change [`llvm-wrapper`] as well. | |
| <!-- date-check: March 2026 --> | |
| > For prior art, here are some previous LLVM updates: | |
| > - [LLVM 17](https://github.com/rust-lang/rust/pull/115959) | |
| > - [LLVM 18](https://github.com/rust-lang/rust/pull/120055) | |
| > - [LLVM 19](https://github.com/rust-lang/rust/pull/127513) | |
| > - [LLVM 20](https://github.com/rust-lang/rust/pull/135763) | |
| > - [LLVM 21](https://github.com/rust-lang/rust/pull/143684) | |
| > - [LLVM 22](https://github.com/rust-lang/rust/pull/150722) | |
| Note that sometimes it's easiest to land [`llvm-wrapper`] compatibility as a PR | |
| before actually updating `src/llvm-project`. | |
| This way, | |
| while you're working through LLVM issues, | |
| others interested in trying out the new LLVM can benefit from work you've done | |
| to update the C++ bindings. | |
| 1. Over the next few months, | |
| LLVM will continually push commits to its `release/a.b` branch. | |
| We will often want to have those bug fixes as well. | |
| The merge process for that is to use `git merge` itself to merge LLVM's | |
| `release/a.b` branch with the branch created in step 2. | |
| This is typically done multiple times when necessary while LLVM's release branch is baking. | |
| 1. LLVM then announces the release of version `a.b`. | |
| 1. After LLVM's official release, | |
| we follow the process of creating a new branch on the rust-lang/llvm-project repository again, | |
| this time with a new date. | |
| It is only then that the PR to update Rust to use that version is merged. | |
| The commit history of `rust-lang/llvm-project` | |
| should look much cleaner as a `git rebase` is done, | |
| where just a few Rust-specific commits are stacked on top of stock LLVM's release branch. | |
| ### Caveats and gotchas | |
| Ideally the above instructions are pretty smooth, but here's some caveats to | |
| keep in mind while going through them: | |
| * LLVM bugs are hard to find, don't hesitate to ask for help! | |
| Bisection is definitely your friend here | |
| (yes LLVM takes forever to build, yet bisection is still your friend). | |
| Note that you can make use of [Dev Desktops], | |
| which is an initiative to provide the contributors with remote access to powerful hardware. | |
| * If you've got general questions, [wg-llvm] can help you out. | |
| * Creating branches is a privileged operation on GitHub, so you'll need someone | |
| with write access to create the branches for you most likely. | |
| [rust-lang/llvm-project repository]: https://github.com/rust-lang/llvm-project | |
| [llvm/llvm-project repository]: https://github.com/llvm/llvm-project | |
| [`llvm-wrapper`]: https://github.com/rust-lang/rust/tree/HEAD/compiler/rustc_llvm/llvm-wrapper | |
| [wg-llvm]: https://rust-lang.zulipchat.com/#narrow/stream/187780-t-compiler.2Fwg-llvm | |
| [Dev Desktops]: https://forge.rust-lang.org/infra/docs/dev-desktop.html | |
| [backport process]: https://llvm.org/docs/GitHub.html#backporting-fixes-to-the-release-branches |