DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
const AVRInstrInfo &TII = *STI.getInstrInfo();
+ const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
bool HasFP = hasFP(MF);
// Interrupt handlers re-enable interrupts in function entry.
- if (CallConv == CallingConv::AVR_INTR) {
+ if (AFI->isInterruptHandler() && CallConv != CallingConv::AVR_SIGNAL) {
BuildMI(MBB, MBBI, DL, TII.get(AVR::BSETs))
.addImm(0x07)
.setMIFlag(MachineInstr::FrameSetup);
// Emit special prologue code to save R1, R0 and SREG in interrupt/signal
// handlers before saving any other registers.
- if (CallConv == CallingConv::AVR_INTR ||
- CallConv == CallingConv::AVR_SIGNAL) {
+ if (AFI->isInterruptHandler()) {
BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr))
.addReg(AVR::R1R0, RegState::Kill)
.setMIFlag(MachineInstr::FrameSetup);
}
const MachineFrameInfo &MFI = MF.getFrameInfo();
- const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
unsigned FrameSize = MFI.getStackSize() - AFI->getCalleeSavedFrameSize();
// Skip the callee-saved push instructions.
void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
- CallingConv::ID CallConv = MF.getFunction().getCallingConv();
- bool isHandler = (CallConv == CallingConv::AVR_INTR ||
- CallConv == CallingConv::AVR_SIGNAL);
+ const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
// 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) && !isHandler) {
+ if (!hasFP(MF) && !AFI->isInterruptHandler()) {
return;
}
DebugLoc DL = MBBI->getDebugLoc();
const MachineFrameInfo &MFI = MF.getFrameInfo();
- const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
unsigned FrameSize = MFI.getStackSize() - AFI->getCalleeSavedFrameSize();
const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
const AVRInstrInfo &TII = *STI.getInstrInfo();
// 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 (isHandler) {
+ if (AFI->isInterruptHandler()) {
BuildMI(MBB, MBBI, DL, TII.get(AVR::POPRd), AVR::R0);
BuildMI(MBB, MBBI, DL, TII.get(AVR::OUTARr))
.addImm(0x3f)
return Chain;
}
+ const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
+
unsigned RetOpc =
- (CallConv == CallingConv::AVR_INTR || CallConv == CallingConv::AVR_SIGNAL)
- ? AVRISD::RETI_FLAG
- : AVRISD::RET_FLAG;
+ AFI->isInterruptHandler()
+ ? AVRISD::RETI_FLAG
+ : AVRISD::RET_FLAG;
RetOps[0] = Chain; // Update chain.
/// used inside the function.
bool HasStackArgs;
+ /// Whether or not the function is an interrupt handler.
+ bool IsInterruptHandler;
+
/// Size of the callee-saved register portion of the
/// stack frame in bytes.
unsigned CalleeSavedFrameSize;
public:
AVRMachineFunctionInfo()
: HasSpills(false), HasAllocas(false), HasStackArgs(false),
- CalleeSavedFrameSize(0), VarArgsFrameIndex(0) {}
+ IsInterruptHandler(false), CalleeSavedFrameSize(0),
+ VarArgsFrameIndex(0) {}
explicit AVRMachineFunctionInfo(MachineFunction &MF)
: HasSpills(false), HasAllocas(false), HasStackArgs(false),
- CalleeSavedFrameSize(0), VarArgsFrameIndex(0) {}
+ CalleeSavedFrameSize(0), VarArgsFrameIndex(0) {
+ unsigned CallConv = MF.getFunction().getCallingConv();
+
+ this->IsInterruptHandler =
+ CallConv == CallingConv::AVR_INTR ||
+ CallConv == CallingConv::AVR_SIGNAL ||
+ MF.getFunction().hasFnAttribute("interrupt");
+ }
bool getHasSpills() const { return HasSpills; }
void setHasSpills(bool B) { HasSpills = B; }
bool getHasStackArgs() const { return HasStackArgs; }
void setHasStackArgs(bool B) { HasStackArgs = B; }
+ bool isInterruptHandler() const { return IsInterruptHandler; }
+
unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; }
void setCalleeSavedFrameSize(unsigned Bytes) { CalleeSavedFrameSize = Bytes; }
#include "AVR.h"
#include "AVRInstrInfo.h"
+#include "AVRMachineFunctionInfo.h"
#include "AVRTargetMachine.h"
#include "MCTargetDesc/AVRMCTargetDesc.h"
const uint16_t *
AVRRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
- CallingConv::ID CC = MF->getFunction().getCallingConv();
+ const AVRMachineFunctionInfo *AFI = MF->getInfo<AVRMachineFunctionInfo>();
- return ((CC == CallingConv::AVR_INTR || CC == CallingConv::AVR_SIGNAL)
+ return AFI->isInterruptHandler()
? CSR_Interrupts_SaveList
- : CSR_Normal_SaveList);
+ : CSR_Normal_SaveList;
}
const uint32_t *
AVRRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
CallingConv::ID CC) const {
- return ((CC == CallingConv::AVR_INTR || CC == CallingConv::AVR_SIGNAL)
+ const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
+
+ return AFI->isInterruptHandler()
? CSR_Interrupts_RegMask
- : CSR_Normal_RegMask);
+ : CSR_Normal_RegMask;
}
BitVector AVRRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
ret void
}
+define void @interrupt_handler_via_ir_attribute() #0 {
+; CHECK-LABEL: interrupt_handler_via_ir_attribute:
+; CHECK: sei
+; CHECK-NEXT: 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
+}
+
define avr_signalcc void @signal_handler() {
; CHECK-LABEL: signal_handler:
; CHECK-NOT: sei
; CHECK-NEXT: reti
ret void
}
+
+attributes #0 = { "interrupt" }
+attributes #1 = { "signal" }