-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Support clobber_abi
in AVR inline assembly
#131323
base: master
Are you sure you want to change the base?
Conversation
e6e6b84
to
5d58879
Compare
compiler/rustc_target/src/asm/avr.rs
Outdated
@@ -106,6 +106,7 @@ def_regs! { | |||
"the stack pointer cannot be used as an operand for inline asm", | |||
#error = ["r0", "r1", "r1r0"] => | |||
"r0 and r1 are not available due to an issue in LLVM", | |||
// if this issue is resolved, then R0 has to be added to clobbered registers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to carefully keep track of LLVM here: if LLVM ceases to treat these registers as reserved then we must immediately add them to the set of clobbered registers, otherwise incorrect code will be generated. This comment should be updated to reflect this.
Also, while reviewing the GCC docs, it seems that R1 always holds a value of 0. If this is a guarantee that asm can use then it should be documented, similar to how on x86 we guarantee the direction flag is always clear when entering or exiting inline asm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the feedback!
Do you have an idea on how to track LLVM here? I'd expect the ABI to be stable, but I don't know on how to test this, except for producing register-heavy code and hoping, that the "no more fixed register" would be used causing the test to fail. This seems rather fragile, though.
Or do you "just" want to phrase the comment different, so that the required immediate action is more clear?
For the second issue, I'll go ahead and document, that the R1 register needs to be restored if altered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's enough to just reword the comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've reworded the comment, please have a look if this works for you.
Regarding the R1 register content: the unstable-book already documents, that the value needs to be restored if altered:
| AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. | |
This commit adds the relevant registers to the list of clobbered regis- ters (part of rust-lang#93335). This follows the [ABI documentation] of AVR-GCC: > The [...] call-clobbered general purpose registers (GPRs) are > registers that might be destroyed (clobbered) by a function call. > > - **R18–R27, R30, R31** > > These GPRs are call clobbered. An ordinary function may use them > without restoring the contents. [...] > > - **R0, T-Flag** > > The temporary register and the T-flag in SREG are also call- > clobbered, but this knowledge is not exposed explicitly to the > compiler (R0 is a fixed register). Therefore this commit lists the aforementioned registers `r18–r27`, `r30` and `r31` as clobbered registers. Since the `r0` register (listed above as well) is not available in inline assembly at all (potentially because the AVR-GCC considers it a fixed register causing the register to never be used in register allocation and LLVM adopting this), there is no need to list it in the clobber list (the `r0`-variant is not even available). A comment was added to ensure, that the `r0` gets added to the clobber-list once the register gets usable in inline ASM. Since the SREG is normally considered clobbered anyways (unless the user supplies the `preserve_flags`-option), there is no need to explicitly list a bit in this register (which is not possible to list anyways). Note, that this commit completely ignores the case of interrupts (that are described in the ABI-specification), since every register touched in an ISR need to be saved anyways. [ABI documentation]: https://gcc.gnu.org/wiki/avr-gcc#Call-Used_Registers
5d58879
to
461c388
Compare
#error = ["r0", "r1", "r1r0"] => | ||
"r0 and r1 are not available due to an issue in LLVM", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(IIUC since r1 is a zero register, r1 and r1r0 cannot be used as an operand for inline asm, regardless of an LLVM issue.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, the fact that r1 is the zero-reg is the cause for the registers not being available for inline asm (although I'm not sure). For now, I think this is fine (please correct me if you think otherwise!).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, I think this is fine (please correct me if you think otherwise!).
Agreed. We may need to figure it out in some way before stabilization, but at least it should not be a blocker of clobber_abi implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would actually be nice to make the error message here clearer than "due to an issue in LLVM". The reason is that r0 is reserved as a scratch register and r1 is reserved as a constant zero register by LLVM.
Btw, AVRTiny1 appears to have a different convention (r0-r15 are unavailable, r16-r17 are similar to r0-r1 in AVR, r18-r19 are call-saved). Footnotes
|
ccc421a
to
558b1ae
Compare
Hm, I think in order to properly address the reduced tiny cores, one would need to wait for #131651 and parse the
|
I think it is indeed true that inline assembly support for AVRTiny is already broken (registers that should be reserved are not reserved) and therefore does not need to be fixed in this PR.
I think it is better to refer to the |
This PR implements the
clobber_abi
part necessary to eventually stabilize the inline assembly for AVR. This is tracked in #93335.This is heavily inspired by the sibling-PR #131310 for the MSP430. I've explained my reasoning in the first commit message in detail, which is reproduced below for easier reviewing:
This follows the ABI documentation of AVR-GCC:
Therefore this commit lists the aforementioned registers
r18–r27
,r30
andr31
as clobbered registers. Since ther0
register (listed above as well) is not available in inline assembly at all (potentially because the AVR-GCC considers it a fixed register causing the register to never be used in register allocation and LLVM adopting this), there is no need to list it in the clobber list (ther0
-variant is not even available). A comment was added to ensure, that ther0
gets added to the clobber-list once the register gets usable in inline ASM.Since the SREG is normally considered clobbered anyways (unless the user supplies the
preserve_flags
-option), there is no need to explicitly list a bit in this register (which is not possible to list anyways).Note, that this commit completely ignores the case of interrupts (that are described in the ABI-specification), since every register touched in an ISR need to be saved anyways.
r? @Amanieu
@rustbot label +O-AVR