@@ -751,6 +751,11 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
751
751
setOperationAction (ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);
752
752
setOperationAction (ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
753
753
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
+
754
759
// We want to use MVC in preference to even a single load/store pair.
755
760
MaxStoresPerMemcpy = Subtarget.hasVector () ? 2 : 0 ;
756
761
MaxStoresPerMemcpyOptSize = 0 ;
@@ -940,6 +945,240 @@ bool SystemZTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
940
945
return SystemZVectorConstantInfo (Imm).isVectorConstantLegal (Subtarget);
941
946
}
942
947
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
+
943
1182
// / Returns true if stack probing through inline assembly is requested.
944
1183
bool SystemZTargetLowering::hasInlineStackProbe (const MachineFunction &MF) const {
945
1184
// If the function specifically requests inline stack probes, emit them.
@@ -6292,6 +6531,14 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
6292
6531
return lowerGET_ROUNDING (Op, DAG);
6293
6532
case ISD::READCYCLECOUNTER:
6294
6533
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
+
6295
6542
default :
6296
6543
llvm_unreachable (" Unexpected node to lower" );
6297
6544
}
@@ -9733,6 +9980,10 @@ MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter(
9733
9980
9734
9981
case SystemZ::PROBED_ALLOCA:
9735
9982
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);
9736
9987
9737
9988
case TargetOpcode::STACKMAP:
9738
9989
case TargetOpcode::PATCHPOINT:
0 commit comments