Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[AVR] Generalize the previous interrupt bugfix to signal handlers too
  • Loading branch information
dylanmckay committed Jun 23, 2020
commit 93a3b595d1c96b299f795fd2409a6776e4eb83ca
8 changes: 4 additions & 4 deletions llvm/lib/Target/AVR/AVRFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,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);
Expand All @@ -76,7 +76,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);
Expand Down Expand Up @@ -146,7 +146,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;
}

Expand All @@ -162,7 +162,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)
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AVR/AVRISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1418,7 +1418,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;

Expand Down
17 changes: 11 additions & 6 deletions llvm/lib/Target/AVR/AVRMachineFunctionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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; }
Expand All @@ -67,7 +68,11 @@ class AVRMachineFunctionInfo : public MachineFunctionInfo {
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; }
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/AVR/AVRRegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
16 changes: 16 additions & 0 deletions llvm/test/CodeGen/AVR/interrupts.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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" }