Skip to content

Commit 93891dd

Browse files
committed
Fix some interrupt stuff.
1 parent 56af4f8 commit 93891dd

File tree

7 files changed

+96
-39
lines changed

7 files changed

+96
-39
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

+1-1
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ def warn_arm_interrupt_calling_convention : Warning<
309309
"call to function without interrupt attribute could clobber interruptee's VFP registers">,
310310
InGroup<Extra>;
311311
def warn_interrupt_attribute_invalid : Warning<
312-
"%select{MIPS|MSP430|RISC-V}0 'interrupt' attribute only applies to "
312+
"%select{MIPS|MSP430|RISC-V|Z80}0 'interrupt' attribute only applies to "
313313
"functions that have %select{no parameters|a 'void' return type}1">,
314314
InGroup<IgnoredAttributes>;
315315
def warn_riscv_repeated_interrupt_attribute : Warning<

clang/lib/Sema/SemaDeclAttr.cpp

+27-2
Original file line numberDiff line numberDiff line change
@@ -7320,10 +7320,35 @@ static void handleZ80InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
73207320
return;
73217321
}
73227322

7323-
if (!AL.checkExactlyNumArgs(S, 0))
7323+
if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
7324+
S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
7325+
<< /*Z80*/ 3 << 0;
7326+
return;
7327+
}
7328+
7329+
if (!getFunctionOrMethodResultType(D)->isVoidType()) {
7330+
S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
7331+
<< /*Z80*/ 3 << 1;
73247332
return;
7333+
}
7334+
7335+
// The attribute takes an optional string argument.
7336+
if (!AL.checkAtMostNumArgs(S, 1))
7337+
return;
7338+
7339+
StringRef Str;
7340+
SourceLocation ArgLoc;
7341+
if (AL.getNumArgs() && !S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
7342+
return;
7343+
7344+
AnyZ80InterruptAttr::InterruptType Kind;
7345+
if (!AnyZ80InterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
7346+
S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
7347+
<< AL << ("\"" + Str + "\"").str() << ArgLoc;
7348+
Kind = AnyZ80InterruptAttr::InterruptType::Generic;
7349+
}
73257350

7326-
handleSimpleAttribute<AnyZ80InterruptAttr>(S, D, AL);
7351+
D->addAttr(::new (S.Context) AnyZ80InterruptAttr(S.Context, AL, Kind));
73277352
}
73287353

73297354
static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {

llvm/include/llvm/IR/CallingConv.h

+10-8
Original file line numberDiff line numberDiff line change
@@ -252,16 +252,18 @@ namespace CallingConv {
252252
/// M68k_INTR - Calling convention used for M68k interrupt routines.
253253
M68k_INTR = 101,
254254

255+
/// Calling convention for passing an OS-defined constant in the IY register.
256+
Z80_TIFlags = 102,
257+
255258
/// Calling conventions used for special Z80 rtlib functions
256259
/// which pass in registers and save all registers.
257-
Z80_LibCall = 102,
258-
Z80_LibCall_AB = 103,
259-
Z80_LibCall_AC = 104,
260-
Z80_LibCall_BC = 105,
261-
Z80_LibCall_L = 106,
262-
Z80_LibCall_F = 107,
263-
Z80_LibCall_16 = 108,
264-
Z80_TIFlags = 109,
260+
Z80_LibCall = 103,
261+
Z80_LibCall_AB = 104,
262+
Z80_LibCall_AC = 105,
263+
Z80_LibCall_BC = 106,
264+
Z80_LibCall_L = 107,
265+
Z80_LibCall_F = 108,
266+
Z80_LibCall_16 = 189,
265267

266268
/// The highest possible calling convention ID. Must be some 2^k - 1.
267269
MaxID = 1023

llvm/lib/Target/Z80/GISel/Z80CallLowering.cpp

+20-15
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "Z80MachineFunctionInfo.h"
2020
#include "Z80RegisterInfo.h"
2121
#include "Z80Subtarget.h"
22+
#include "llvm/ADT/StringSwitch.h"
2223
#include "llvm/CodeGen/Analysis.h"
2324
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
2425
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
@@ -425,12 +426,18 @@ bool Z80CallLowering::isEligibleForTailCallOptimization(
425426
if (!Info.IsTailCall)
426427
return false;
427428

429+
const Function *CalleeF = Info.CB ? Info.CB->getCalledFunction() : nullptr;
428430
CallingConv::ID CalleeCC = Info.CallConv;
429-
MachineFunction &MF = MIRBuilder.getMF();
430-
const Function &CallerF = MF.getFunction();
431+
MachineFunction &CallerMF = MIRBuilder.getMF();
432+
const Function &CallerF = CallerMF.getFunction();
431433

432434
LLVM_DEBUG(dbgs() << "Attempting to lower call as tail call\n");
433435

436+
if (CalleeF && CalleeF->hasFnAttribute("interrupt")) {
437+
LLVM_DEBUG(dbgs() << "... Cannot tail call interrupt handlers.\n");
438+
return false;
439+
}
440+
434441
if (Info.SwiftErrorVReg) {
435442
// TODO: We should handle this.
436443
// Note that this is also handled by the check for no outgoing arguments.
@@ -465,7 +472,7 @@ bool Z80CallLowering::isEligibleForTailCallOptimization(
465472
}
466473

467474
// If we have -tailcallopt, then we're done.
468-
if (MF.getTarget().Options.GuaranteedTailCallOpt)
475+
if (CallerMF.getTarget().Options.GuaranteedTailCallOpt)
469476
return canGuaranteeTCO(CalleeCC) && CalleeCC == CallerF.getCallingConv();
470477

471478
// We don't have -tailcallopt, so we're allowed to change the ABI (sibcall).
@@ -478,14 +485,14 @@ bool Z80CallLowering::isEligibleForTailCallOptimization(
478485

479486
// Verify that the incoming and outgoing arguments from the callee are
480487
// safe to tail call.
481-
if (!doCallerAndCalleePassArgsTheSameWay(Info, MF, InArgs)) {
488+
if (!doCallerAndCalleePassArgsTheSameWay(Info, CallerMF, InArgs)) {
482489
LLVM_DEBUG(
483490
dbgs()
484491
<< "... Caller and callee have incompatible calling conventions.\n");
485492
return false;
486493
}
487494

488-
if (!areCalleeOutgoingArgsTailCallable(Info, MF, OutArgs))
495+
if (!areCalleeOutgoingArgsTailCallable(Info, CallerMF, OutArgs))
489496
return false;
490497

491498
LLVM_DEBUG(dbgs() << "... Call is eligible for tail call optimization.\n");
@@ -506,14 +513,6 @@ bool Z80CallLowering::lowerTailCall(MachineIRBuilder &MIRBuilder,
506513
// True when we're tail calling, but without -tailcallopt.
507514
bool IsSibCall = !MF.getTarget().Options.GuaranteedTailCallOpt;
508515

509-
// TODO: Right now, regbankselect doesn't know how to handle the rtcGPR64
510-
// register class. Until we can do that, we should fall back here.
511-
if (F.hasFnAttribute("branch-target-enforcement")) {
512-
LLVM_DEBUG(
513-
dbgs() << "Cannot lower indirect tail calls with BTI enabled yet.\n");
514-
return false;
515-
}
516-
517516
MachineInstrBuilder CallSeqStart;
518517
if (!IsSibCall)
519518
CallSeqStart = MIRBuilder.buildInstr(TII.getCallFrameSetupOpcode());
@@ -779,11 +778,17 @@ bool Z80CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
779778
FunctionLoweringInfo &FLI) const {
780779
assert(!Val == VRegs.empty() && "Return value without a vreg");
781780
MachineFunction &MF = MIRBuilder.getMF();
781+
const Function &F = MF.getFunction();
782782
LLVMContext &Ctx = MF.getFunction().getContext();
783783
auto &FuncInfo = *MF.getInfo<Z80MachineFunctionInfo>();
784784
const auto &STI = MF.getSubtarget<Z80Subtarget>();
785-
auto MIB =
786-
MIRBuilder.buildInstrNoInsert(STI.is24Bit() ? Z80::RET24 : Z80::RET16);
785+
786+
bool Is24Bit = STI.is24Bit();
787+
auto MIB = MIRBuilder.buildInstrNoInsert(
788+
StringSwitch<unsigned>(F.getFnAttribute("interrupt").getValueAsString())
789+
.Cases("Generic", "Nested", Is24Bit ? Z80::RETI24 : Z80::RETI16)
790+
.Case("NMI", Is24Bit ? Z80::RETN24 : Z80::RETN16)
791+
.Default(Is24Bit ? Z80::RET24 : Z80::RET16));
787792

788793
Register SRetReturnReg = FuncInfo.getSRetReturnReg();
789794
assert((!SRetReturnReg || VRegs.empty()) &&

llvm/lib/Target/Z80/Z80CallingConv.td

+2
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@ def CSR_NoRegs : CalleeSavedRegs<(add)>;
124124
def CSR_Z80_C : CalleeSavedRegs<(add IX)>;
125125
def CSR_EZ80_C : CalleeSavedRegs<(add UIX)>;
126126
def CSR_Z80_AllRegs : CalleeSavedRegs<(add R16, A)>;
127+
def CSR_Z80_AllRegsAndFlags : CalleeSavedRegs<(add R16, AF)>;
127128
def CSR_EZ80_AllRegs : CalleeSavedRegs<(add R24, A)>;
128129
def CSR_EZ80_AllRegs16 : CalleeSavedRegs<(add (sub R24, UHL, UBC), HL, BC, A)>;
130+
def CSR_EZ80_AllRegsAndFlags : CalleeSavedRegs<(add R24, AF)>;
129131
def CSR_Z80_TIFlags : CalleeSavedRegs<(add I16)>;
130132
def CSR_EZ80_TIFlags : CalleeSavedRegs<(add I24)>;

llvm/lib/Target/Z80/Z80FrameLowering.cpp

+28-5
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,13 @@ static bool shouldUseShadow(const MachineFunction &MF) {
357357
return F.getFnAttribute("interrupt").getValueAsString() == "Generic";
358358
}
359359

360+
static MachineInstr& setImplicitUsesUndef(MachineInstr &MI) {
361+
for (MachineOperand &MO : MI.implicit_operands())
362+
if (MO.isReg() && MO.isUse())
363+
MO.setIsUndef();
364+
return MI;
365+
}
366+
360367
void Z80FrameLowering::shadowCalleeSavedRegisters(
361368
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL,
362369
MachineInstr::MIFlag Flag, const std::vector<CalleeSavedInfo> &CSI) const {
@@ -370,11 +377,13 @@ void Z80FrameLowering::shadowCalleeSavedRegisters(
370377
else if (Z80::G24RegClass.contains(Reg) || Z80::G16RegClass.contains(Reg))
371378
SaveG = true;
372379
}
373-
if (SaveAF)
374-
BuildMI(MBB, MI, DL, TII.get(Z80::EXAF)).setMIFlag(Flag);
375380
if (SaveG)
376-
BuildMI(MBB, MI, DL, TII.get(Is24Bit ? Z80::EXX24 : Z80::EXX16))
377-
.setMIFlag(Flag);
381+
setImplicitUsesUndef(
382+
*BuildMI(MBB, MI, DL, TII.get(Is24Bit ? Z80::EXX24 : Z80::EXX16))
383+
.setMIFlag(Flag));
384+
if (SaveAF)
385+
setImplicitUsesUndef(
386+
*BuildMI(MBB, MI, DL, TII.get(Z80::EXAF)).setMIFlag(Flag));
378387
}
379388

380389
static Z80MachineFunctionInfo::AltFPMode
@@ -407,7 +416,21 @@ bool Z80FrameLowering::assignCalleeSavedSpillSlots(
407416
auto &FuncInfo = *MF.getInfo<Z80MachineFunctionInfo>();
408417
FuncInfo.setUsesAltFP(shouldUseAltFP(MF, Is24Bit ? Z80::UIY : Z80::IY, TRI));
409418
MF.getRegInfo().freezeReservedRegs(MF);
410-
FuncInfo.setCalleeSavedFrameSize(CSI.size() * SlotSize);
419+
420+
bool UseShadow = shouldUseShadow(MF);
421+
unsigned CalleeSavedFrameSize = isFPSaved(MF) ? SlotSize : 0;
422+
for (unsigned i = CSI.size(); i != 0; --i) {
423+
unsigned Reg = CSI[i - 1].getReg();
424+
425+
// Non-index registers can be spilled to shadow registers.
426+
if (UseShadow && !Z80::I24RegClass.contains(Reg) &&
427+
!Z80::I16RegClass.contains(Reg))
428+
continue;
429+
430+
CalleeSavedFrameSize += SlotSize;
431+
}
432+
FuncInfo.setCalleeSavedFrameSize(CalleeSavedFrameSize);
433+
411434
return true;
412435
}
413436

llvm/lib/Target/Z80/Z80RegisterInfo.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,11 @@ unsigned Z80RegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
102102
const MCPhysReg *
103103
Z80RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
104104
switch (MF->getFunction().getCallingConv()) {
105-
default: llvm_unreachable("Unsupported calling convention");
105+
default:
106+
llvm_unreachable("Unsupported calling convention");
106107
case CallingConv::C:
107108
case CallingConv::Fast:
108109
return Is24Bit ? CSR_EZ80_C_SaveList : CSR_Z80_C_SaveList;
109-
case CallingConv::PreserveAll:
110110
case CallingConv::Z80_LibCall:
111111
case CallingConv::Z80_LibCall_AB:
112112
case CallingConv::Z80_LibCall_AC:
@@ -116,6 +116,9 @@ Z80RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
116116
return Is24Bit ? CSR_EZ80_AllRegs_SaveList : CSR_Z80_AllRegs_SaveList;
117117
case CallingConv::Z80_LibCall_16:
118118
return Is24Bit ? CSR_EZ80_AllRegs16_SaveList : CSR_Z80_AllRegs_SaveList;
119+
case CallingConv::PreserveAll:
120+
return Is24Bit ? CSR_EZ80_AllRegsAndFlags_SaveList
121+
: CSR_Z80_AllRegsAndFlags_SaveList;
119122
case CallingConv::Z80_TIFlags:
120123
return Is24Bit ? CSR_EZ80_TIFlags_SaveList : CSR_Z80_TIFlags_SaveList;
121124
}
@@ -208,12 +211,9 @@ void Z80RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
208211
assert(TFI->hasFP(MF) && "Stack slot use without fp unimplemented");
209212
auto Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) -
210213
TFI->getOffsetOfLocalArea();
211-
if (FrameIndex >= 0)
212-
// For non-fixed indices, skip over callee save slots.
213-
Offset -= MF.getInfo<Z80MachineFunctionInfo>()->getCalleeSavedFrameSize();
214-
else if (TFI->isFPSaved(MF))
215-
// For fixed indices, skip over FP save slot if it exists.
216-
Offset += TFI->getSlotSize();
214+
if (FrameIndex < 0)
215+
// For fixed indices, skip over callee save slots.
216+
Offset += MF.getInfo<Z80MachineFunctionInfo>()->getCalleeSavedFrameSize();
217217
TII.rewriteFrameIndex(MI, FIOperandNum, BaseReg, Offset, RS, SPAdj);
218218
}
219219

0 commit comments

Comments
 (0)