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