1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 20:23:11 +01:00

[AVR] Generalize the previous interrupt bugfix to signal handlers too

This commit is contained in:
Dylan McKay 2020-03-31 19:28:01 +13:00
parent 7132783865
commit dd0d79a2a1
5 changed files with 34 additions and 13 deletions

View 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)

View 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;

View 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; }

View 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;
}

View 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" }