diff --git a/compiler/rustc_target/src/asm/avr.rs b/compiler/rustc_target/src/asm/avr.rs index 276f376b297e6..9adcbecdf3c10 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). } } diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 9fe733e063cf5..204d5d5336102 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -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