]>
Commit | Line | Data |
---|---|---|
532ac7d7 XL |
1 | # Updating LLVM |
2 | ||
6a06907d XL |
3 | <!-- toc --> |
4 | ||
532ac7d7 XL |
5 | The Rust compiler uses LLVM as its primary codegen backend today, and naturally |
6 | we want to at least occasionally update this dependency! Currently we do not | |
7 | have a strict policy about when to update LLVM or what it can be updated to, but | |
8 | a few guidelines are applied: | |
9 | ||
10 | * We try to always support the latest released version of LLVM | |
11 | * We try to support the "last few" versions of LLVM (how many is changing over | |
12 | time) | |
13 | * We allow moving to arbitrary commits during development. | |
14 | * Strongly prefer to upstream all patches to LLVM before including them in | |
15 | rustc. | |
16 | ||
17 | This policy may change over time (or may actually start to exist as a formal | |
18 | policy!), but for now these are rough guidelines! | |
19 | ||
20 | ## Why update LLVM? | |
21 | ||
60c5eb7d | 22 | There are a few reasons nowadays that we want to update LLVM in one way or |
532ac7d7 XL |
23 | another: |
24 | ||
60c5eb7d | 25 | * A bug could have been fixed! Often we find bugs in the compiler and fix |
532ac7d7 XL |
26 | them upstream in LLVM. We'll want to pull fixes back to the compiler itself as |
27 | they're merged upstream. | |
28 | ||
60c5eb7d | 29 | * A new feature may be available in LLVM that we want to use in rustc, |
532ac7d7 XL |
30 | but we don't want to wait for a full LLVM release to test it out. |
31 | ||
60c5eb7d XL |
32 | * LLVM itself may have a new release and we'd like to update to this LLVM |
33 | release. | |
34 | ||
532ac7d7 | 35 | Each of these reasons has a different strategy for updating LLVM, and we'll go |
60c5eb7d | 36 | over them in detail here. |
532ac7d7 XL |
37 | |
38 | ## Bugfix Updates | |
39 | ||
60c5eb7d XL |
40 | For updates of LLVM that are to fix a small bug, we cherry-pick the bugfix to |
41 | the branch we're already using. The steps for this are: | |
532ac7d7 XL |
42 | |
43 | 1. Make sure the bugfix is in upstream LLVM. | |
48663c56 XL |
44 | 2. Identify the branch that rustc is currently using. The `src/llvm-project` |
45 | submodule is always pinned to a branch of the | |
f2b60f7d | 46 | [rust-lang/llvm-project repository]. |
48663c56 XL |
47 | 3. Fork the rust-lang/llvm-project repository |
48 | 4. Check out the appropriate branch (typically named `rustc/a.b-yyyy-mm-dd`) | |
532ac7d7 XL |
49 | 5. Cherry-pick the upstream commit onto the branch |
50 | 6. Push this branch to your fork | |
60c5eb7d XL |
51 | 7. Send a Pull Request to rust-lang/llvm-project to the same branch as before. |
52 | Be sure to reference the Rust and/or LLVM issue that you're fixing in the PR | |
53 | description. | |
532ac7d7 | 54 | 8. Wait for the PR to be merged |
48663c56 | 55 | 9. Send a PR to rust-lang/rust updating the `src/llvm-project` submodule with |
60c5eb7d XL |
56 | your bugfix. This can be done locally with `git submodule update --remote |
57 | src/llvm-project` typically. | |
532ac7d7 XL |
58 | 10. Wait for PR to be merged |
59 | ||
60 | The tl;dr; is that we can cherry-pick bugfixes at any time and pull them back | |
48663c56 | 61 | into the rust-lang/llvm-project branch that we're using, and getting it into the |
532ac7d7 XL |
62 | compiler is just updating the submodule via a PR! |
63 | ||
64 | Example PRs look like: | |
48663c56 | 65 | [#59089](https://github.com/rust-lang/rust/pull/59089) |
532ac7d7 XL |
66 | |
67 | ## Feature updates | |
68 | ||
f2b60f7d FG |
69 | > Note that this information is as of the time of this writing, <!-- |
70 | date-check --> October 2021. The process for updating LLVM changes with | |
6a06907d | 71 | practically all LLVM updates, so this may be out of date! |
532ac7d7 XL |
72 | |
73 | Unlike bugfixes, updating to pick up a new feature of LLVM typically requires a | |
74 | lot more work. This is where we can't reasonably cherry-pick commits backwards | |
75 | so we need to do a full update. There's a lot of stuff to do here, so let's go | |
76 | through each in detail. | |
77 | ||
cdc7bbd5 | 78 | 1. Create a new branch in the [rust-lang/llvm-project repository]. This branch |
48663c56 XL |
79 | should be named `rustc/a.b-yyyy-mm-dd` where `a.b` is the current version |
80 | number of LLVM in-tree at the time of the branch and the remaining part is | |
60c5eb7d XL |
81 | today's date. Move this branch to the commit in LLVM that you'd like, which |
82 | for this is probably the current LLVM HEAD. | |
48663c56 XL |
83 | |
84 | 2. Apply Rust-specific patches to the llvm-project repository. All features and | |
85 | bugfixes are upstream, but there's often some weird build-related patches | |
86 | that don't make sense to upstream which we have on our repositories. These | |
87 | patches are around the latest patches in the rust-lang/llvm-project branch | |
88 | that rustc is currently using. | |
532ac7d7 | 89 | |
60c5eb7d XL |
90 | 3. Build the new LLVM in the `rust` repository. To do this you'll want to update |
91 | the `src/llvm-project` repository to your branch and the revision you've | |
92 | created. It's also typically a good idea to update `.gitmodules` with the new | |
93 | branch name of the LLVM submodule. Make sure you've committed changes to | |
94 | `src/llvm-project` to ensure submodule updates aren't reverted. Some commands | |
95 | you should execute are: | |
532ac7d7 XL |
96 | |
97 | * `./x.py build src/llvm` - test that LLVM still builds | |
98 | * `./x.py build src/tools/lld` - same for LLD | |
99 | * `./x.py build` - build the rest of rustc | |
100 | ||
6a06907d XL |
101 | You'll likely need to update [`llvm-wrapper/*.cpp`][`llvm-wrapper`] to compile |
102 | with updated LLVM bindings. Note that you should use `#ifdef` and such to ensure | |
103 | that the bindings still compile on older LLVM versions. | |
104 | ||
3c0e092e | 105 | Note that `profile = "compiler"` and other defaults set by `./x.py setup` |
6a06907d XL |
106 | download LLVM from CI instead of building it from source. You should |
107 | disable this temporarily to make sure your changes are being used, by setting | |
108 | ```toml | |
109 | [llvm] | |
110 | download-ci-llvm = false | |
111 | ``` | |
112 | in config.toml. | |
532ac7d7 | 113 | |
60c5eb7d | 114 | 4. Test for regressions across other platforms. LLVM often has at least one bug |
532ac7d7 XL |
115 | for non-tier-1 architectures, so it's good to do some more testing before |
116 | sending this to bors! If you're low on resources you can send the PR as-is | |
117 | now to bors, though, and it'll get tested anyway. | |
118 | ||
119 | Ideally, build LLVM and test it on a few platforms: | |
120 | ||
121 | * Linux | |
cdc7bbd5 | 122 | * macOS |
532ac7d7 XL |
123 | * Windows |
124 | ||
125 | and afterwards run some docker containers that CI also does: | |
126 | ||
cdc7bbd5 | 127 | * `./src/ci/docker/run.sh wasm32` |
532ac7d7 XL |
128 | * `./src/ci/docker/run.sh arm-android` |
129 | * `./src/ci/docker/run.sh dist-various-1` | |
130 | * `./src/ci/docker/run.sh dist-various-2` | |
131 | * `./src/ci/docker/run.sh armhf-gnu` | |
132 | ||
60c5eb7d XL |
133 | 5. Prepare a PR to `rust-lang/rust`. Work with maintainers of |
134 | `rust-lang/llvm-project` to get your commit in a branch of that repository, | |
135 | and then you can send a PR to `rust-lang/rust`. You'll change at least | |
6a06907d | 136 | `src/llvm-project` and will likely also change [`llvm-wrapper`] as well. |
532ac7d7 XL |
137 | |
138 | For prior art, previous LLVM updates look like | |
60c5eb7d | 139 | [#62474](https://github.com/rust-lang/rust/pull/62474) |
cdc7bbd5 XL |
140 | [#62592](https://github.com/rust-lang/rust/pull/62592) |
141 | [#67759](https://github.com/rust-lang/rust/pull/67759) | |
142 | [#73526](https://github.com/rust-lang/rust/pull/73526) | |
143 | [#81451](https://github.com/rust-lang/rust/pull/81451). Note that sometimes it's | |
6a06907d | 144 | easiest to land [`llvm-wrapper`] compatibility as a PR before actually updating |
60c5eb7d XL |
145 | `src/llvm-project`. This way while you're working through LLVM issues others |
146 | interested in trying out the new LLVM can benefit from work you've done to | |
147 | update the C++ bindings. | |
532ac7d7 XL |
148 | |
149 | ### Caveats and gotchas | |
150 | ||
151 | Ideally the above instructions are pretty smooth, but here's some caveats to | |
152 | keep in mind while going through them: | |
153 | ||
154 | * LLVM bugs are hard to find, don't hesitate to ask for help! Bisection is | |
155 | definitely your friend here (yes LLVM takes forever to build, yet bisection is | |
156 | still your friend) | |
cdc7bbd5 | 157 | * If you've got general questions, [wg-llvm] can help you out. |
532ac7d7 XL |
158 | * Creating branches is a privileged operation on GitHub, so you'll need someone |
159 | with write access to create the branches for you most likely. | |
60c5eb7d XL |
160 | |
161 | ## New LLVM Release Updates | |
162 | ||
163 | Updating to a new release of LLVM is very similar to the "feature updates" | |
164 | section above. The release process for LLVM is often months-long though and we | |
165 | like to ensure compatibility ASAP. The main tweaks to the "feature updates" | |
166 | section above is generally around branch naming. The sequence of events | |
167 | typically looks like: | |
168 | ||
169 | 1. LLVM announces that its latest release version has branched. This will show | |
f2b60f7d | 170 | up as a branch in the [llvm/llvm-project repository] typically named |
60c5eb7d XL |
171 | `release/$N.x` where `$N` is the version of LLVM that's being released. |
172 | ||
173 | 2. We then follow the "feature updates" section above to create a new branch of | |
174 | LLVM in our rust-lang/llvm-project repository. This follows the same naming | |
175 | convention of branches as usual, except that `a.b` is the new version. This | |
176 | update is eventually landed in the rust-lang/rust repository. | |
177 | ||
178 | 3. Over the next few months, LLVM will continually push commits to its | |
179 | `release/a.b` branch. Often those are bug fixes we'd like to have as well. | |
180 | The merge process for that is to use `git merge` itself to merge LLVM's | |
181 | `release/a.b` branch with the branch created in step 2. This is typically | |
182 | done multiple times when necessary while LLVM's release branch is baking. | |
183 | ||
184 | 4. LLVM then announces the release of version `a.b`. | |
185 | ||
186 | 5. After LLVM's official release, we follow the "feature update" section again | |
187 | to create a new branch in the rust-lang/llvm-project repository, this time | |
188 | with a new date. The commit history should look much cleaner as just a few | |
189 | Rust-specific commits stacked on top of stock LLVM's release branch. | |
f2b60f7d FG |
190 | |
191 | [rust-lang/llvm-project repository]: https://github.com/rust-lang/llvm-project | |
192 | [llvm/llvm-project repository]: https://github.com/llvm/llvm-project | |
193 | [`llvm-wrapper`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_llvm/llvm-wrapper | |
194 | [wg-llvm]: https://rust-lang.zulipchat.com/#narrow/stream/187780-t-compiler.2Fwg-llvm |