mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Support clobber_abi
for AVR inline assembly
This commit adds the relevant registers to the list of clobbered regis- ters (part of #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
This commit is contained in:
parent
9b4d7c6a40
commit
ba73166556
@ -106,6 +106,11 @@ 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 changes within LLVM, the compiler might use the registers
|
||||
// in the future. This must be reflected in the set of clobbered
|
||||
// registers, else the clobber ABI implementation is *unsound*, as
|
||||
// this generates invalid code (register is not marked as clobbered
|
||||
// but may change the register content).
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -928,6 +928,7 @@ pub enum InlineAsmClobberAbi {
|
||||
AArch64,
|
||||
AArch64NoX18,
|
||||
Arm64EC,
|
||||
Avr,
|
||||
RiscV,
|
||||
RiscVE,
|
||||
LoongArch,
|
||||
@ -986,6 +987,10 @@ impl InlineAsmClobberAbi {
|
||||
}),
|
||||
_ => Err(&["C", "system", "efiapi"]),
|
||||
},
|
||||
InlineAsmArch::Avr => match name {
|
||||
"C" | "system" => Ok(InlineAsmClobberAbi::Avr),
|
||||
_ => Err(&["C", "system"]),
|
||||
},
|
||||
InlineAsmArch::LoongArch64 => match name {
|
||||
"C" | "system" => Ok(InlineAsmClobberAbi::LoongArch),
|
||||
_ => Err(&["C", "system"]),
|
||||
@ -1133,6 +1138,23 @@ impl InlineAsmClobberAbi {
|
||||
d24, d25, d26, d27, d28, d29, d30, d31,
|
||||
}
|
||||
},
|
||||
InlineAsmClobberAbi::Avr => clobbered_regs! {
|
||||
Avr AvrInlineAsmReg {
|
||||
// The list of "Call-Used Registers" according to
|
||||
// https://gcc.gnu.org/wiki/avr-gcc#Call-Used_Registers
|
||||
|
||||
// Clobbered registers available in inline assembly
|
||||
r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r30, r31,
|
||||
// As per the AVR-GCC-ABI documentation linked above, the R0
|
||||
// register is a clobbered register as well. Since we don't
|
||||
// allow the usage of R0 in inline assembly, nothing has to
|
||||
// be done here.
|
||||
// Likewise, the T-flag in the SREG should be clobbered, but
|
||||
// this is not necessary to be listed here, since the SREG
|
||||
// is considered clobbered anyways unless `preserve_flags`
|
||||
// is used.
|
||||
}
|
||||
},
|
||||
InlineAsmClobberAbi::RiscV => clobbered_regs! {
|
||||
RiscV RiscVInlineAsmReg {
|
||||
// ra
|
||||
|
Loading…
Reference in New Issue
Block a user