@@ -751,6 +751,11 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
751751 setOperationAction (ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);
752752 setOperationAction (ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
753753
754+ // We're not using SJLJ for exception handling, but they're implemented
755+ // solely to support use of __builtin_setjmp / __builtin_longjmp.
756+ setOperationAction (ISD::EH_SJLJ_SETJMP, MVT::i32 , Custom);
757+ setOperationAction (ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom);
758+
754759 // We want to use MVC in preference to even a single load/store pair.
755760 MaxStoresPerMemcpy = Subtarget.hasVector () ? 2 : 0 ;
756761 MaxStoresPerMemcpyOptSize = 0 ;
@@ -940,6 +945,240 @@ bool SystemZTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
940945 return SystemZVectorConstantInfo (Imm).isVectorConstantLegal (Subtarget);
941946}
942947
948+ MachineBasicBlock *
949+ SystemZTargetLowering::emitEHSjLjSetJmp (MachineInstr &MI,
950+ MachineBasicBlock *MBB) const {
951+ DebugLoc DL = MI.getDebugLoc ();
952+ const TargetInstrInfo *TII = Subtarget.getInstrInfo ();
953+ const SystemZRegisterInfo *TRI = Subtarget.getRegisterInfo ();
954+
955+ MachineFunction *MF = MBB->getParent ();
956+ MachineRegisterInfo &MRI = MF->getRegInfo ();
957+
958+ const BasicBlock *BB = MBB->getBasicBlock ();
959+ MachineFunction::iterator I = ++MBB->getIterator ();
960+
961+ Register DstReg = MI.getOperand (0 ).getReg ();
962+ const TargetRegisterClass *RC = MRI.getRegClass (DstReg);
963+ assert (TRI->isTypeLegalForClass (*RC, MVT::i32 ) && " Invalid destination!" );
964+ Register mainDstReg = MRI.createVirtualRegister (RC);
965+ Register restoreDstReg = MRI.createVirtualRegister (RC);
966+
967+ MVT PVT = getPointerTy (MF->getDataLayout ());
968+ assert ((PVT == MVT::i64 || PVT == MVT::i32 ) && " Invalid Pointer Size!" );
969+ // For v = setjmp(buf), we generate.
970+ // Algorithm:
971+ //
972+ // ---------
973+ // | thisMBB |
974+ // ---------
975+ // |
976+ // ------------------------
977+ // | |
978+ // ---------- ---------------
979+ // | mainMBB | | restoreMBB |
980+ // | v = 0 | | v = 1 |
981+ // ---------- ---------------
982+ // | |
983+ // -------------------------
984+ // |
985+ // -----------------------------
986+ // | sinkMBB |
987+ // | phi(v_mainMBB,v_restoreMBB) |
988+ // -----------------------------
989+ // thisMBB:
990+ // buf[FPOffset] = Frame Pointer if hasFP.
991+ // buf[LabelOffset] = restoreMBB <-- takes address of restoreMBB.
992+ // buf[BCOffset] = Backchain value if building with -mbackchain.
993+ // buf[SPOffset] = Stack Pointer.
994+ // buf[LPOffset] = We never write this slot with R13, gcc stores R13 always.
995+ // SjLjSetup restoreMBB
996+ // mainMBB:
997+ // v_main = 0
998+ // sinkMBB:
999+ // v = phi(v_main, v_restore)
1000+ // restoreMBB:
1001+ // v_restore = 1
1002+
1003+ MachineBasicBlock *thisMBB = MBB;
1004+ MachineBasicBlock *mainMBB = MF->CreateMachineBasicBlock (BB);
1005+ MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock (BB);
1006+ MachineBasicBlock *restoreMBB = MF->CreateMachineBasicBlock (BB);
1007+
1008+ MF->insert (I, mainMBB);
1009+ MF->insert (I, sinkMBB);
1010+ MF->push_back (restoreMBB);
1011+ restoreMBB->setMachineBlockAddressTaken ();
1012+
1013+ MachineInstrBuilder MIB;
1014+
1015+ // Transfer the remainder of BB and its successor edges to sinkMBB.
1016+ sinkMBB->splice (sinkMBB->begin (), MBB,
1017+ std::next (MachineBasicBlock::iterator (MI)), MBB->end ());
1018+ sinkMBB->transferSuccessorsAndUpdatePHIs (MBB);
1019+
1020+ // thisMBB:
1021+ const int64_t FPOffset = 0 ; // Slot 1.
1022+ const int64_t LabelOffset = 1 * PVT.getStoreSize (); // Slot 2.
1023+ const int64_t BCOffset = 2 * PVT.getStoreSize (); // Slot 3.
1024+ const int64_t SPOffset = 3 * PVT.getStoreSize (); // Slot 4.
1025+
1026+ // Buf address.
1027+ Register BufReg = MI.getOperand (1 ).getReg ();
1028+
1029+ const TargetRegisterClass *PtrRC = getRegClassFor (PVT);
1030+ unsigned LabelReg = MRI.createVirtualRegister (PtrRC);
1031+
1032+ // Prepare IP for longjmp.
1033+ BuildMI (*thisMBB, MI, DL, TII->get (SystemZ::LARL), LabelReg)
1034+ .addMBB (restoreMBB);
1035+ // Store IP for return from jmp, slot 2, offset = 1.
1036+ BuildMI (*thisMBB, MI, DL, TII->get (SystemZ::STG))
1037+ .addReg (LabelReg)
1038+ .addReg (BufReg)
1039+ .addImm (LabelOffset)
1040+ .addReg (0 );
1041+
1042+ auto *SpecialRegs = Subtarget.getSpecialRegisters ();
1043+ bool HasFP = Subtarget.getFrameLowering ()->hasFP (*MF);
1044+ if (HasFP) {
1045+ BuildMI (*thisMBB, MI, DL, TII->get (SystemZ::STG))
1046+ .addReg (SpecialRegs->getFramePointerRegister ())
1047+ .addReg (BufReg)
1048+ .addImm (FPOffset)
1049+ .addReg (0 );
1050+ }
1051+
1052+ // Store SP.
1053+ BuildMI (*thisMBB, MI, DL, TII->get (SystemZ::STG))
1054+ .addReg (SpecialRegs->getStackPointerRegister ())
1055+ .addReg (BufReg)
1056+ .addImm (SPOffset)
1057+ .addReg (0 );
1058+
1059+ // Slot 3(Offset = 2) Backchain value (if building with -mbackchain).
1060+ bool BackChain = MF->getSubtarget <SystemZSubtarget>().hasBackChain ();
1061+ if (BackChain) {
1062+ Register BCReg = MRI.createVirtualRegister (RC);
1063+ auto *TFL = Subtarget.getFrameLowering <SystemZFrameLowering>();
1064+ MIB = BuildMI (*thisMBB, MI, DL, TII->get (SystemZ::LG), BCReg)
1065+ .addReg (SpecialRegs->getStackPointerRegister ())
1066+ .addImm (TFL->getBackchainOffset (*MF))
1067+ .addReg (0 );
1068+
1069+ BuildMI (*thisMBB, MI, DL, TII->get (SystemZ::STG))
1070+ .addReg (BCReg)
1071+ .addReg (BufReg)
1072+ .addImm (BCOffset)
1073+ .addReg (0 );
1074+ }
1075+
1076+ // Setup.
1077+ MIB = BuildMI (*thisMBB, MI, DL, TII->get (SystemZ::EH_SjLj_Setup))
1078+ .addMBB (restoreMBB);
1079+
1080+ const SystemZRegisterInfo *RegInfo = Subtarget.getRegisterInfo ();
1081+ MIB.addRegMask (RegInfo->getNoPreservedMask ());
1082+
1083+ thisMBB->addSuccessor (mainMBB);
1084+ thisMBB->addSuccessor (restoreMBB);
1085+
1086+ // mainMBB:
1087+ BuildMI (mainMBB, DL, TII->get (SystemZ::LHI), mainDstReg).addImm (0 );
1088+ mainMBB->addSuccessor (sinkMBB);
1089+
1090+ // sinkMBB:
1091+ BuildMI (*sinkMBB, sinkMBB->begin (), DL, TII->get (SystemZ::PHI), DstReg)
1092+ .addReg (mainDstReg)
1093+ .addMBB (mainMBB)
1094+ .addReg (restoreDstReg)
1095+ .addMBB (restoreMBB);
1096+
1097+ // restoreMBB.
1098+ BuildMI (restoreMBB, DL, TII->get (SystemZ::LHI), restoreDstReg).addImm (1 );
1099+ BuildMI (restoreMBB, DL, TII->get (SystemZ::J)).addMBB (sinkMBB);
1100+ restoreMBB->addSuccessor (sinkMBB);
1101+
1102+ MI.eraseFromParent ();
1103+
1104+ return sinkMBB;
1105+ }
1106+
1107+ MachineBasicBlock *
1108+ SystemZTargetLowering::emitEHSjLjLongJmp (MachineInstr &MI,
1109+ MachineBasicBlock *MBB) const {
1110+
1111+ DebugLoc DL = MI.getDebugLoc ();
1112+ const TargetInstrInfo *TII = Subtarget.getInstrInfo ();
1113+
1114+ MachineFunction *MF = MBB->getParent ();
1115+ MachineRegisterInfo &MRI = MF->getRegInfo ();
1116+
1117+ MVT PVT = getPointerTy (MF->getDataLayout ());
1118+ assert ((PVT == MVT::i64 || PVT == MVT::i32 ) && " Invalid Pointer Size!" );
1119+ Register BufReg = MI.getOperand (0 ).getReg ();
1120+ const TargetRegisterClass *RC = MRI.getRegClass (BufReg);
1121+ auto *SpecialRegs = Subtarget.getSpecialRegisters ();
1122+
1123+ Register Tmp = MRI.createVirtualRegister (RC);
1124+ Register BCReg = MRI.createVirtualRegister (RC);
1125+
1126+ MachineInstrBuilder MIB;
1127+
1128+ const int64_t FPOffset = 0 ;
1129+ const int64_t LabelOffset = 1 * PVT.getStoreSize ();
1130+ const int64_t BCOffset = 2 * PVT.getStoreSize ();
1131+ const int64_t SPOffset = 3 * PVT.getStoreSize ();
1132+ const int64_t LPOffset = 4 * PVT.getStoreSize ();
1133+
1134+ MIB = BuildMI (*MBB, MI, DL, TII->get (SystemZ::LG), Tmp)
1135+ .addReg (BufReg)
1136+ .addImm (LabelOffset)
1137+ .addReg (0 );
1138+
1139+ MIB = BuildMI (*MBB, MI, DL, TII->get (SystemZ::LG),
1140+ SpecialRegs->getFramePointerRegister ())
1141+ .addReg (BufReg)
1142+ .addImm (FPOffset)
1143+ .addReg (0 );
1144+
1145+ // We are restoring R13 even though we never stored in setjmp from llvm,
1146+ // as gcc always stores R13 in builtin_setjmp. We could have mixed code
1147+ // gcc setjmp and llvm longjmp.
1148+ MIB = BuildMI (*MBB, MI, DL, TII->get (SystemZ::LG), SystemZ::R13D)
1149+ .addReg (BufReg)
1150+ .addImm (LPOffset)
1151+ .addReg (0 );
1152+
1153+ bool BackChain = MF->getSubtarget <SystemZSubtarget>().hasBackChain ();
1154+ if (BackChain) {
1155+ MIB = BuildMI (*MBB, MI, DL, TII->get (SystemZ::LG), BCReg)
1156+ .addReg (BufReg)
1157+ .addImm (BCOffset)
1158+ .addReg (0 );
1159+ }
1160+
1161+ MIB = BuildMI (*MBB, MI, DL, TII->get (SystemZ::LG),
1162+ SpecialRegs->getStackPointerRegister ())
1163+ .addReg (BufReg)
1164+ .addImm (SPOffset)
1165+ .addReg (0 );
1166+
1167+ if (BackChain) {
1168+ auto *TFL = Subtarget.getFrameLowering <SystemZFrameLowering>();
1169+ BuildMI (*MBB, MI, DL, TII->get (SystemZ::STG))
1170+ .addReg (BCReg)
1171+ .addReg (SpecialRegs->getStackPointerRegister ())
1172+ .addImm (TFL->getBackchainOffset (*MF))
1173+ .addReg (0 );
1174+ }
1175+
1176+ MIB = BuildMI (*MBB, MI, DL, TII->get (SystemZ::BR)).addReg (Tmp);
1177+
1178+ MI.eraseFromParent ();
1179+ return MBB;
1180+ }
1181+
9431182// / Returns true if stack probing through inline assembly is requested.
9441183bool SystemZTargetLowering::hasInlineStackProbe (const MachineFunction &MF) const {
9451184 // If the function specifically requests inline stack probes, emit them.
@@ -6292,6 +6531,14 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
62926531 return lowerGET_ROUNDING (Op, DAG);
62936532 case ISD::READCYCLECOUNTER:
62946533 return lowerREADCYCLECOUNTER (Op, DAG);
6534+ case ISD::EH_SJLJ_SETJMP:
6535+ case ISD::EH_SJLJ_LONGJMP:
6536+ // These operations are legal on our platform, but we cannot actually
6537+ // set the operation action to Legal as common code would treat this
6538+ // as equivalent to Expand. Instead, we keep the operation action to
6539+ // Custom and just leave them unchanged here.
6540+ return Op;
6541+
62956542 default :
62966543 llvm_unreachable (" Unexpected node to lower" );
62976544 }
@@ -9733,6 +9980,10 @@ MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter(
97339980
97349981 case SystemZ::PROBED_ALLOCA:
97359982 return emitProbedAlloca (MI, MBB);
9983+ case SystemZ::EH_SjLj_SetJmp:
9984+ return emitEHSjLjSetJmp (MI, MBB);
9985+ case SystemZ::EH_SjLj_LongJmp:
9986+ return emitEHSjLjLongJmp (MI, MBB);
97369987
97379988 case TargetOpcode::STACKMAP:
97389989 case TargetOpcode::PATCHPOINT:
0 commit comments