about summary refs log tree commit diff
path: root/compiler/rustc_target/src/asm/avr.rs
diff options
context:
space:
mode:
authorJulian Frimmel <julian@fri-me.de>2024-10-06 12:33:25 +0200
committerJulian Frimmel <julian@fri-me.de>2024-11-28 16:12:02 +0100
commitba7316655645c020263e207ee9c036131b511d45 (patch)
tree779e4c6007505f71c01102664006aedb301e0d4c /compiler/rustc_target/src/asm/avr.rs
parent9b4d7c6a40b328d212095c28670c629facf1557d (diff)
downloadrust-ba7316655645c020263e207ee9c036131b511d45.tar.gz
rust-ba7316655645c020263e207ee9c036131b511d45.zip
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
Diffstat (limited to 'compiler/rustc_target/src/asm/avr.rs')
-rw-r--r--compiler/rustc_target/src/asm/avr.rs5
1 files changed, 5 insertions, 0 deletions
diff --git a/compiler/rustc_target/src/asm/avr.rs b/compiler/rustc_target/src/asm/avr.rs
index 276f376b297..9adcbecdf3c 100644
--- a/compiler/rustc_target/src/asm/avr.rs
+++ b/compiler/rustc_target/src/asm/avr.rs
@@ -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).
     }
 }