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

rustc is too strict about reserved registers on ARM #85247

Closed
Skirmisher opened this issue May 13, 2021 · 2 comments · Fixed by #94169
Closed

rustc is too strict about reserved registers on ARM #85247

Skirmisher opened this issue May 13, 2021 · 2 comments · Fixed by #94169
Labels
C-bug Category: This is a bug. F-asm `#![feature(asm)]` (not `llvm_asm`) O-Arm Target: 32-bit Arm processors (armv6, armv7, thumb...), including 64-bit Arm in AArch32 state

Comments

@Skirmisher
Copy link

Recently, this commit came to my attention, as it added r9 to the list of LLVM-reserved registers on ARM according to rustc, breaking existing inline asm. I decided to look into this further, and found this page (section "Restrictions") which concisely states under what conditions certain registers are reserved in the ABI (with regards to armclang as described in the page, but it applies more generally). The relevant points are:

  • If RWPI (read-write position independent) code is enabled, R9 is reserved.
  • If needed, R7 is reserved for the frame pointer in T32 mode, and R11 is reserved in A32 mode.

However, rustc reserves these registers unconditionally. This seems incorrect, as both RWPI and frame pointers can be disabled via codegen options or a custom target. In our case, the custom target file (armv4t-none-eabi.json) has both "eliminate-frame-pointer": true and "relocation-model": "static" set, but rustc will reject uses of r9 and r11 with their respective error messages ("r9 is used internally by llvm" and "frame pointer (r11) cannot be used as an operand").

@Skirmisher Skirmisher added the C-bug Category: This is a bug. label May 13, 2021
@jonas-schievink jonas-schievink added F-asm `#![feature(asm)]` (not `llvm_asm`) O-Arm Target: 32-bit Arm processors (armv6, armv7, thumb...), including 64-bit Arm in AArch32 state labels May 13, 2021
@Lokathor
Copy link
Contributor

Lokathor commented May 17, 2021

The gba crate (thumbv4t-none-eabi target) also got hit with this.

Skirmisher added a commit to Skirmisher/rust that referenced this issue Sep 12, 2021
As described in rust-lang#85247, there are a number of cases where inline ARM assembly
in Rust programs is prevented from using certain registers. Sometimes these
registers are only reserved in certain situations; however, they are all
unconditionally restricted by the compiler. Many of rustc's diagnostics
describe the registers as being "used internally by LLVM", which obfuscates
the meaning of the registers and is ultimately unhelpful to low-level
programmers.

At the moment, it does not seem possible to ensure that the frame pointer or
base pointer will be elided, or to understand the conditions under which this
may occur. Some of this is due to the addition of a codegen abstraction layer,
where these behaviors may vary between backends and may not be configurable.
As such, this information is not available to Rust's assembly parser.

However, register r9 has a condition that is rather easily checked: the
relocation model. r9 is used as the "static base" (SB) for "read-write
position independence" (RWPI) as a base from which to address writable data,
as defined in the Procedure Call Standard for the Arm Architecture[1]. The
register is always available for use if RWPI is not used[2].

Rust allows RWPI mode to be selected on a per-target basis, as well as making
it available as a codegen option in rustc. Thus, we can predicate usage of r9
on this setting with confidence.

Allow r9 to be used in `asm!` blocks when the target does not use RWPI, and
define what r6 and r9 are reserved for in their respective diagnostics. The
frame pointer (r7/r11) and base pointer (r6) remain unconditionally restricted
for now.

[1]: https://developer.arm.com/documentation/ihi0042/j/
[2]: https://developer.arm.com/documentation/dui0056/d/using-the-procedure-call-standard/read-write-position-independence/register-usage-with-rwpi
@Skirmisher
Copy link
Author

Okay, so the codegen backend situation has changed a lot since this target file was first generated, and eliminate-frame-pointer was replaced a while back with frame-pointer which defaults to MayOmit—no longer implying a guarantee, mainly because a different codegen backend can make arbitrary decisions about the frame pointer (and it's unclear how or whether this setting eliminated the frame pointer in LLVM in the first place). I was not aware of the codegen backend abstraction work or anything else when filing this issue.

At any rate, R9 restriction is easiest to fix since the relocation model info is just There, and Arm's documentation is very clear about when it is and is not reserved. See my new pull request here with more info. The rest can be figured out later.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Feb 20, 2022
Fix several asm! related issues

This is a combination of several fixes, each split into a separate commit. Splitting these into PRs is not practical since they conflict with each other.

Fixes rust-lang#92378
Fixes rust-lang#85247

r? `@nagisa`
Manishearth added a commit to Manishearth/rust that referenced this issue Feb 20, 2022
Fix several asm! related issues

This is a combination of several fixes, each split into a separate commit. Splitting these into PRs is not practical since they conflict with each other.

Fixes rust-lang#92378
Fixes rust-lang#85247

r? ``@nagisa``
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Feb 22, 2022
Fix several asm! related issues

This is a combination of several fixes, each split into a separate commit. Splitting these into PRs is not practical since they conflict with each other.

Fixes rust-lang#92378
Fixes rust-lang#85247

r? `@nagisa`
@bors bors closed this as completed in 1cf2e69 Feb 22, 2022
bjorn3 pushed a commit to bjorn3/rust that referenced this issue Feb 23, 2022
Fix several asm! related issues

This is a combination of several fixes, each split into a separate commit. Splitting these into PRs is not practical since they conflict with each other.

Fixes rust-lang#92378
Fixes rust-lang#85247

r? ``@nagisa``
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. F-asm `#![feature(asm)]` (not `llvm_asm`) O-Arm Target: 32-bit Arm processors (armv6, armv7, thumb...), including 64-bit Arm in AArch32 state
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants