[AVR] Generalize the previous interrupt bugfix to signal handlers too
authorDylan McKay <me@dylanmckay.io>
Tue, 31 Mar 2020 06:28:01 +0000 (19:28 +1300)
committerDylan McKay <me@dylanmckay.io>
Tue, 31 Mar 2020 06:33:34 +0000 (19:33 +1300)
llvm/lib/Target/AVR/AVRFrameLowering.cpp
llvm/lib/Target/AVR/AVRISelLowering.cpp
llvm/lib/Target/AVR/AVRMachineFunctionInfo.h
llvm/lib/Target/AVR/AVRRegisterInfo.cpp
llvm/test/CodeGen/AVR/interrupts.ll

index f327f9b..27b9873 100644 (file)
@@ -60,7 +60,7 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
   bool HasFP = hasFP(MF);
 
   // Interrupt handlers re-enable interrupts in function entry.
-  if (AFI->isInterruptHandler() && CallConv != CallingConv::AVR_SIGNAL) {
+  if (AFI->isInterruptHandler()) {
     BuildMI(MBB, MBBI, DL, TII.get(AVR::BSETs))
         .addImm(0x07)
         .setMIFlag(MachineInstr::FrameSetup);
@@ -75,7 +75,7 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
 
   // Emit special prologue code to save R1, R0 and SREG in interrupt/signal
   // handlers before saving any other registers.
-  if (AFI->isInterruptHandler()) {
+  if (AFI->isInterruptOrSignalHandler()) {
     BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr))
         .addReg(AVR::R1R0, RegState::Kill)
         .setMIFlag(MachineInstr::FrameSetup);
@@ -145,7 +145,7 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
 
   // Early exit if the frame pointer is not needed in this function except for
   // signal/interrupt handlers where special code generation is required.
-  if (!hasFP(MF) && !AFI->isInterruptHandler()) {
+  if (!hasFP(MF) && !AFI->isInterruptOrSignalHandler()) {
     return;
   }
 
@@ -161,7 +161,7 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
 
   // Emit special epilogue code to restore R1, R0 and SREG in interrupt/signal
   // handlers at the very end of the function, just before reti.
-  if (AFI->isInterruptHandler()) {
+  if (AFI->isInterruptOrSignalHandler()) {
     BuildMI(MBB, MBBI, DL, TII.get(AVR::POPRd), AVR::R0);
     BuildMI(MBB, MBBI, DL, TII.get(AVR::OUTARr))
         .addImm(0x3f)
index 159a3ca..be8f8f7 100644 (file)
@@ -1432,7 +1432,7 @@ AVRTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
   const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
 
   unsigned RetOpc =
-    AFI->isInterruptHandler()
+    AFI->isInterruptOrSignalHandler()
         ? AVRISD::RETI_FLAG
         : AVRISD::RET_FLAG;
 
index 5fa6bb5..5432fac 100644 (file)
@@ -34,6 +34,9 @@ class AVRMachineFunctionInfo : public MachineFunctionInfo {
   /// Whether or not the function is an interrupt handler.
   bool IsInterruptHandler;
 
+  /// Whether or not the function is an non-blocking interrupt handler.
+  bool IsSignalHandler;
+
   /// Size of the callee-saved register portion of the
   /// stack frame in bytes.
   unsigned CalleeSavedFrameSize;
@@ -44,18 +47,16 @@ class AVRMachineFunctionInfo : public MachineFunctionInfo {
 public:
   AVRMachineFunctionInfo()
       : HasSpills(false), HasAllocas(false), HasStackArgs(false),
-        IsInterruptHandler(false), CalleeSavedFrameSize(0),
-        VarArgsFrameIndex(0) {}
+        IsInterruptHandler(false), IsSignalHandler(false),
+        CalleeSavedFrameSize(0), VarArgsFrameIndex(0) {}
 
   explicit AVRMachineFunctionInfo(MachineFunction &MF)
       : HasSpills(false), HasAllocas(false), HasStackArgs(false),
         CalleeSavedFrameSize(0), VarArgsFrameIndex(0) {
     unsigned CallConv = MF.getFunction().getCallingConv();
 
-    this->IsInterruptHandler =
-      CallConv == CallingConv::AVR_INTR ||
-      CallConv == CallingConv::AVR_SIGNAL ||
-      MF.getFunction().hasFnAttribute("interrupt");
+    this->IsInterruptHandler = CallConv == CallingConv::AVR_INTR || MF.getFunction().hasFnAttribute("interrupt");
+    this->IsSignalHandler = CallConv == CallingConv::AVR_SIGNAL || MF.getFunction().hasFnAttribute("signal");
   }
 
   bool getHasSpills() const { return HasSpills; }
@@ -67,7 +68,11 @@ public:
   bool getHasStackArgs() const { return HasStackArgs; }
   void setHasStackArgs(bool B) { HasStackArgs = B; }
 
+  /// Checks if the function is some form of interrupt service routine.
+  bool isInterruptOrSignalHandler() const { return isInterruptHandler() || isSignalHandler(); }
+
   bool isInterruptHandler() const { return IsInterruptHandler; }
+  bool isSignalHandler() const { return IsSignalHandler; }
 
   unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; }
   void setCalleeSavedFrameSize(unsigned Bytes) { CalleeSavedFrameSize = Bytes; }
index 6caa460..2a4905c 100644 (file)
@@ -37,7 +37,7 @@ const uint16_t *
 AVRRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
   const AVRMachineFunctionInfo *AFI = MF->getInfo<AVRMachineFunctionInfo>();
 
-  return AFI->isInterruptHandler()
+  return AFI->isInterruptOrSignalHandler()
               ? CSR_Interrupts_SaveList
               : CSR_Normal_SaveList;
 }
@@ -47,7 +47,7 @@ AVRRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
                                       CallingConv::ID CC) const {
   const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
 
-  return AFI->isInterruptHandler()
+  return AFI->isInterruptOrSignalHandler()
               ? CSR_Interrupts_RegMask
               : CSR_Normal_RegMask;
 }
index da8a5ce..b402d86 100644 (file)
@@ -48,5 +48,21 @@ define avr_signalcc void @signal_handler() {
   ret void
 }
 
+define void @signal_handler_via_attribute() #1 {
+; CHECK-LABEL: signal_handler_via_attribute:
+; CHECK-NOT: sei
+; CHECK: push r0
+; CHECK-NEXT: push r1
+; CHECK-NEXT: in r0, 63
+; CHECK-NEXT: push r0
+; CHECK: clr r0
+; CHECK: pop r0
+; CHECK-NEXT: out 63, r0
+; CHECK-NEXT: pop r1
+; CHECK-NEXT: pop r0
+; CHECK-NEXT: reti
+  ret void
+}
+
 attributes #0 = { "interrupt" }
 attributes #1 = { "signal" }