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

asm/arm: allow r9 when usable, make diagnostics more specific #88879

Closed

Conversation

Skirmisher
Copy link

As described in #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. The register is always available for use if RWPI is not used.

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.

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
@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @wesleywiser (or someone else) soon.

Please see the contribution instructions for more information.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 12, 2021
@Amanieu
Copy link
Member

Amanieu commented Sep 12, 2021

Technically we should be checking for the reserve-r9 LLVM feature here. But it's not currently exposed by rustc.

@Skirmisher
Copy link
Author

That is more precise, but that will still leave out other codegen backends, no?

_has_feature: impl FnMut(&str) -> bool,
target: &Target,
) -> Result<(), &'static str> {
if let RelocModel::Rwpi | RelocModel::RopiRwpi = target.relocation_model {
Copy link
Member

Choose a reason for hiding this comment

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

Should we only allow r9 when the relocation model was explicitly given to allow for more freedom in choosing which relocation model will be used by default without risking breaking this?

Copy link
Author

Choose a reason for hiding this comment

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

That might be a good idea, though it would make the diagnostic less clear if the user hasn't specifically opted in to that mode. I wanted to add a "note" to it, but this is my first time contributing to rustc and I don't know how to do that, much less how to make it work in the context of def_regs!.

How does one check if a target attribute is explicitly set?

Copy link
Member

Choose a reason for hiding this comment

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

You can check the value of sess.opts.cg.relocation_model. By the way I think target.relocation_model is only the default relocation model in all cases and not the one that will actually be used when compiling if -Crelocation-model is used.

Copy link
Author

Choose a reason for hiding this comment

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

Good catch, I didn't think of that since in my use case I'm using a custom target. I can fix that up. I'd still like to improve the diagnostics though.

Copy link
Author

Choose a reason for hiding this comment

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

Oh, Session already has a relocation_model getter that does the logic I was going to write anyway.

Copy link
Author

@Skirmisher Skirmisher Sep 13, 2021

Choose a reason for hiding this comment

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

Ah right, I can't actually do that because the asm parser isn't passed the Session, only the Target... Looks like I would need to change the definition of parse in the entire rustc_target::asm module at least, including arch-specific filter functions, then alter rustc_ast_lowering::LoweringContext to pass Session as well (possibly in place of Target since it can be accessed through Session). That feels like a fairly invasive change just to make a small thing more correct, but the overall effect should be negligible. If the maintainers are okay with it, I can go ahead and do it.

Copy link
Member

Choose a reason for hiding this comment

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

This won't work since rustc_target can't depend on rustc_session since that would create a circular dependency.

@wesleywiser
Copy link
Member

r? @Amanieu

@rust-highfive rust-highfive assigned Amanieu and unassigned wesleywiser Sep 13, 2021
@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 3, 2021
@apiraino apiraino added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Oct 14, 2021
@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 31, 2021
@sanxiyn sanxiyn added the O-Arm Target: 32-bit Arm processors (armv6, armv7, thumb...), including 64-bit Arm in AArch32 state label Nov 8, 2021
@pnkfelix
Copy link
Member

Hi @Amanieu ; do you think you'll be able to review this PR, or delegate it to some other expert on ARM asm! ?

@Amanieu
Copy link
Member

Amanieu commented Nov 21, 2021

I still think this should be changed to look for the reserve-r9 target feature since that will automatically pick up the case where the relocation model is changed on the command-line. Also, if we're going to do this then we should probably do the same with x18 on AArch64 which is reserved on some targets, but it's fine to leave this to a later PR.

Finally, the documentation in the unstable book needs to be updated to reflect the new behavior of r9.

@bors
Copy link
Contributor

bors commented Dec 9, 2021

☔ The latest upstream changes (presumably #91692) made this pull request unmergeable. Please resolve the merge conflicts.

@Amanieu
Copy link
Member

Amanieu commented Dec 9, 2021

Closing in favor of #91643.

@Amanieu Amanieu closed this Dec 9, 2021
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 11, 2021
asm: Allow using r9 (ARM) and x18 (AArch64) if they are not reserved by the current target

This supersedes rust-lang#88879.

cc `@Skirmisher`

r? `@joshtriplett`
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 11, 2021
asm: Allow using r9 (ARM) and x18 (AArch64) if they are not reserved by the current target

This supersedes rust-lang#88879.

cc `@Skirmisher`

r? `@joshtriplett`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-Arm Target: 32-bit Arm processors (armv6, armv7, thumb...), including 64-bit Arm in AArch32 state S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants