Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

date-check: updating-llvm #1424

Merged
merged 3 commits into from
Nov 20, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 82 additions & 85 deletions src/backend/updating-llvm.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,13 @@ policy!), but for now these are rough guidelines!

## Why update LLVM?

There are a few reasons nowadays that we want to update LLVM in one way or
another:
There are two reasons we would want to update LLVM:

* A bug could have been fixed! Often we find bugs in the compiler and fix
them upstream in LLVM. We'll want to pull fixes back to the compiler itself as
they're merged upstream.

* A new feature may be available in LLVM that we want to use in rustc,
but we don't want to wait for a full LLVM release to test it out.

* LLVM itself may have a new release and we'd like to update to this LLVM
release.
* LLVM itself may have a new release.
Comment on lines -29 to +28
Copy link
Member

@JohnTitor JohnTitor Aug 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't merge them as these two things are different, a new feature that isn't released may be cherry-picked into Rust's LLVM fork, e.g. rust-lang/llvm-project#135.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting, because @nikic said it is not done any more, maybe because it is rare in the recent past

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nikic Is that true? I thought the above PR is an example of a new feature cherry-picked into our LLVM fork.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The relevant distinction here is between a cherry-pick (bug fix or self-contained feature) and a rebase (new release). The thing we don't do any more is to rebase without a new (pending) release.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying! I think that should be documented above, the current sounds somewhat confusing.


Each of these reasons has a different strategy for updating LLVM, and we'll go
over them in detail here.
Expand All @@ -57,59 +52,67 @@ the branch we're already using. The steps for this are:
src/llvm-project` typically.
10. Wait for PR to be merged

The tl;dr; is that we can cherry-pick bugfixes at any time and pull them back
into the rust-lang/llvm-project branch that we're using, and getting it into the
compiler is just updating the submodule via a PR!

Example PRs look like:
An example PR:
[#59089](https://github.com/rust-lang/rust/pull/59089)

## Feature updates

> Note that this information is as of the time of this writing, <!--
date-check --> October 2021. The process for updating LLVM changes with
practically all LLVM updates, so this may be out of date!

Unlike bugfixes, updating to pick up a new feature 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. Create a new branch in the [rust-lang/llvm-project repository]. This branch
should be named `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
today's date. Move this branch to the commit in LLVM that you'd like, which
for this is probably the current LLVM HEAD.

2. 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 which we have on our repositories. These
patches are around the latest patches in the rust-lang/llvm-project branch
that rustc is currently using.
## New LLVM Release Updates

3. 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:
<!-- date-check: Aug 2022 -->

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.

2. 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.

3. 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.py build src/llvm` - test that LLVM still builds
* `./x.py build src/tools/lld` - same for LLD
* `./x.py 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
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.py setup`
download LLVM from CI instead of building it from source. You should
disable this temporarily to make sure your changes are being used, by setting
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 `config.toml`:

```toml
[llvm]
download-ci-llvm = false
```
in config.toml.

4. 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
Expand All @@ -122,7 +125,7 @@ through each in detail.
* macOS
* Windows

and afterwards run some docker containers that CI also does:
Afterwards, run some docker containers that CI also does:

* `./src/ci/docker/run.sh wasm32`
* `./src/ci/docker/run.sh arm-android`
Expand All @@ -135,16 +138,39 @@ through each in detail.
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.

For prior art, previous LLVM updates look like
[#62474](https://github.com/rust-lang/rust/pull/62474)
[#62592](https://github.com/rust-lang/rust/pull/62592)
[#67759](https://github.com/rust-lang/rust/pull/67759)
[#73526](https://github.com/rust-lang/rust/pull/73526)
[#81451](https://github.com/rust-lang/rust/pull/81451). 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.
> For prior art, here are some previous LLVM updates:
> - [LLVM 11](https://github.com/rust-lang/rust/pull/73526)
> - [LLVM 12](https://github.com/rust-lang/rust/pull/81451)
> - [LLVM 13](https://github.com/rust-lang/rust/pull/87570)
> - [LLVM 14](https://github.com/rust-lang/rust/pull/93577)
> - [LLVM 15](https://github.com/rust-lang/rust/pull/99464)

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.

3. 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.

4. LLVM then announces the release of version `a.b`.

5. 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

Expand All @@ -158,35 +184,6 @@ keep in mind while going through them:
* Creating branches is a privileged operation on GitHub, so you'll need someone
with write access to create the branches for you most likely.

## New LLVM Release Updates

Updating to a new release of LLVM is very similar to the "feature updates"
section above. The release process for LLVM is often months-long though and we
like to ensure compatibility ASAP. The main tweaks to the "feature updates"
section above is generally around branch naming. The sequence of events
typically looks like:

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.

2. We then follow the "feature updates" section above to create a new branch of
LLVM in our rust-lang/llvm-project repository. This follows the same naming
convention of branches as usual, except that `a.b` is the new version. This
update is eventually landed in the rust-lang/rust repository.

3. Over the next few months, LLVM will continually push commits to its
`release/a.b` branch. Often those are bug fixes we'd like to have 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.

4. LLVM then announces the release of version `a.b`.

5. After LLVM's official release, we follow the "feature update" section again
to create a new branch in the rust-lang/llvm-project repository, this time
with a new date. The commit history should look much cleaner as just a few
Rust-specific commits stacked on top of stock LLVM's release branch.

[rust-lang/llvm-project repository]: https://github.com/rust-lang/llvm-project
[llvm/llvm-project repository]: https://github.com/llvm/llvm-project
Expand Down