-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Comments
The |
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
Okay, so the codegen backend situation has changed a lot since this target file was first generated, and 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. |
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`
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``
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`
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``
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:
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").The text was updated successfully, but these errors were encountered: