Skip to content

Commit b8dd23e

Browse files
committed
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
1 parent f6648f2 commit b8dd23e

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

compiler/rustc_target/src/asm/avr.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ def_regs! {
106106
"the stack pointer cannot be used as an operand for inline asm",
107107
#error = ["r0", "r1", "r1r0"] =>
108108
"r0 and r1 are not available due to an issue in LLVM",
109+
// If this changes within LLVM, the compiler might use the registers
110+
// in the future. This must be reflected in the set of clobbered
111+
// registers, else the clobber ABI implementation is *unsound*, as
112+
// this generates invalid code (register is not marked as clobbered
113+
// but may change the register content).
109114
}
110115
}
111116

compiler/rustc_target/src/asm/mod.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,7 @@ pub enum InlineAsmClobberAbi {
891891
AArch64,
892892
AArch64NoX18,
893893
RiscV,
894+
Avr,
894895
LoongArch,
895896
S390x,
896897
Msp430,
@@ -939,6 +940,10 @@ impl InlineAsmClobberAbi {
939940
"C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::RiscV),
940941
_ => Err(&["C", "system", "efiapi"]),
941942
},
943+
InlineAsmArch::Avr => match name {
944+
"C" | "system" => Ok(InlineAsmClobberAbi::Avr),
945+
_ => Err(&["C", "system"]),
946+
},
942947
InlineAsmArch::LoongArch64 => match name {
943948
"C" | "system" => Ok(InlineAsmClobberAbi::LoongArch),
944949
_ => Err(&["C", "system"]),
@@ -1093,6 +1098,23 @@ impl InlineAsmClobberAbi {
10931098
v24, v25, v26, v27, v28, v29, v30, v31,
10941099
}
10951100
},
1101+
InlineAsmClobberAbi::Avr => clobbered_regs! {
1102+
Avr AvrInlineAsmReg {
1103+
// The list of "Call-Used Registers" according to
1104+
// https://gcc.gnu.org/wiki/avr-gcc#Call-Used_Registers
1105+
1106+
// Clobbered registers available in inline assembly
1107+
r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r30, r31,
1108+
// As per the AVR-GCC-ABI documentation linked above, the R0
1109+
// register is a clobbered register as well. Since we don't
1110+
// allow the usage of R0 in inline assembly, nothing has to
1111+
// be done here.
1112+
// Likewise, the T-flag in the SREG should be clobbered, but
1113+
// this is not necessary to be listed here, since the SREG
1114+
// is considered clobbered anyways unless `preserve_flags`
1115+
// is used.
1116+
}
1117+
},
10961118
InlineAsmClobberAbi::LoongArch => clobbered_regs! {
10971119
LoongArch LoongArchInlineAsmReg {
10981120
// ra

0 commit comments

Comments
 (0)