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 ()) &&
0 commit comments