Skip to content

Commit

Permalink
Support clobber_abi for AVR inline assembly
Browse files Browse the repository at this point in the history
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.

An open question is the T-flag in the SREG. This is a one-bit temporary
storage inside a special-purpose register, which therefore cannot simply
be added to the clobber ABI list.

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
  • Loading branch information
jfrimmel committed Oct 6, 2024
1 parent 7d53688 commit ff676be
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 0 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_target/src/asm/avr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_target/src/asm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,7 @@ pub enum InlineAsmClobberAbi {
AArch64,
AArch64NoX18,
RiscV,
Avr,
LoongArch,
S390x,
}
Expand Down Expand Up @@ -938,6 +939,10 @@ impl InlineAsmClobberAbi {
"C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::RiscV),
_ => 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"]),
Expand Down Expand Up @@ -1088,6 +1093,21 @@ impl InlineAsmClobberAbi {
v24, v25, v26, v27, v28, v29, v30, v31,
}
},
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.

// FIXME: what to do about the T-flag in SREG?
}
},
InlineAsmClobberAbi::LoongArch => clobbered_regs! {
LoongArch LoongArchInlineAsmReg {
// ra
Expand Down

0 comments on commit ff676be

Please sign in to comment.