diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h --- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h @@ -16,6 +16,7 @@ #define LLVM_CODEGEN_TARGETREGISTERINFO_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" @@ -523,6 +524,16 @@ /// markSuperRegs() and checkAllSuperRegsMarked() in this case. virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0; + /// Returns either a string explaining why the given register is reserved for + /// this function, or an empty optional if no explanation has been written. + /// The absence of an explanation does not mean that the register is not + /// reserved (meaning, you should check that PhysReg is in fact reserved + /// before calling this). + virtual llvm::Optional + explainReservedReg(const MachineFunction &MF, MCRegister PhysReg) const { + return {}; + } + /// Returns false if we can't guarantee that Physreg, specified as an IR asm /// clobber constraint, will be preserved across the statement. virtual bool isAsmClobberable(const MachineFunction &MF, diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -411,6 +411,14 @@ LocCookie, Msg, DiagnosticSeverity::DS_Warning)); MMI->getModule()->getContext().diagnose( DiagnosticInfoInlineAsm(LocCookie, Note, DiagnosticSeverity::DS_Note)); + + for (const Register RR : RestrRegs) { + if (llvm::Optional reason = + TRI->explainReservedReg(*MF, RR)) { + MMI->getModule()->getContext().diagnose(DiagnosticInfoInlineAsm( + LocCookie, *reason, DiagnosticSeverity::DS_Note)); + } + } } emitInlineAsm(OS.str(), getSubtargetInfo(), TM.Options.MCOptions, LocMD, diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h @@ -91,6 +91,9 @@ BitVector getStrictlyReservedRegs(const MachineFunction &MF) const; BitVector getReservedRegs(const MachineFunction &MF) const override; + llvm::Optional + explainReservedReg(const MachineFunction &MF, + MCRegister PhysReg) const override; bool isAsmClobberable(const MachineFunction &MF, MCRegister PhysReg) const override; const TargetRegisterClass * diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -308,6 +308,16 @@ return CSR_AArch64_StackProbe_Windows_RegMask; } +llvm::Optional +AArch64RegisterInfo::explainReservedReg(const MachineFunction &MF, + MCRegister PhysReg) const { + if (hasBasePointer(MF) && + (PhysReg == AArch64::X19 || PhysReg == AArch64::W19)) + return std::string("X19 is used as the frame base pointer register."); + + return {}; +} + BitVector AArch64RegisterInfo::getStrictlyReservedRegs(const MachineFunction &MF) const { const AArch64FrameLowering *TFI = getFrameLowering(MF); diff --git a/llvm/test/CodeGen/AArch64/inline-asm-clobber-base-frame-pointer.ll b/llvm/test/CodeGen/AArch64/inline-asm-clobber-base-frame-pointer.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/inline-asm-clobber-base-frame-pointer.ll @@ -0,0 +1,15 @@ +; Check that not only do we warn about clobbering x19 we also say +; what it is used for. + +; RUN: llc <%s -mtriple=aarch64-none-eabi 2>&1 | FileCheck %s + +; CHECK: warning: inline asm clobber list contains reserved registers: X19 +; CHECK: note: X19 is used as the frame base pointer register. + +define void @alloca(i64 %size) { +entry: + %a = alloca i128, i64 %size, align 64 + call void asm sideeffect "nop", "~{x19}"() + ret void +} +