@@ -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,241 @@ 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
+ (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
+
943
1183
// / Returns true if stack probing through inline assembly is requested.
944
1184
bool SystemZTargetLowering::hasInlineStackProbe (const MachineFunction &MF) const {
945
1185
// If the function specifically requests inline stack probes, emit them.
@@ -6292,6 +6532,14 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
6292
6532
return lowerGET_ROUNDING (Op, DAG);
6293
6533
case ISD::READCYCLECOUNTER:
6294
6534
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
+
6295
6543
default :
6296
6544
llvm_unreachable (" Unexpected node to lower" );
6297
6545
}
@@ -9733,6 +9981,10 @@ MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter(
9733
9981
9734
9982
case SystemZ::PROBED_ALLOCA:
9735
9983
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);
9736
9988
9737
9989
case TargetOpcode::STACKMAP:
9738
9990
case TargetOpcode::PATCHPOINT:
0 commit comments