LLVM: lib/CodeGen/WinEHPrepare.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
40
41using namespace llvm;
42
43#define DEBUG_TYPE "win-eh-prepare"
44
48 "Clone multicolor basic blocks but do not demote cross scopes"),
50
53 cl::desc("Do not remove implausible terminators or other similar cleanups"),
55
56
58 "demote-catchswitch-only", cl::Hidden,
59 cl::desc("Demote catchswitch BBs only (for wasm EH)"), cl::init(false));
60
61namespace {
62
63class WinEHPrepareImpl {
64public:
65 WinEHPrepareImpl(bool DemoteCatchSwitchPHIOnly)
66 : DemoteCatchSwitchPHIOnly(DemoteCatchSwitchPHIOnly) {}
67
69
70private:
71 void insertPHIStores(PHINode *OriginalPHI, AllocaInst *SpillSlot);
72 void
73 insertPHIStore(BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
74 SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist);
75 AllocaInst *insertPHILoads(PHINode *PN, Function &F);
76 void replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
77 DenseMap<BasicBlock *, Value *> &Loads, Function &F);
78 bool prepareExplicitEH(Function &F);
79 void colorFunclets(Function &F);
80
81 bool demotePHIsOnFunclets(Function &F, bool DemoteCatchSwitchPHIOnly);
82 bool cloneCommonBlocks(Function &F);
83 bool removeImplausibleInstructions(Function &F);
84 bool cleanupPreparedFunclets(Function &F);
85 void verifyPreparedFunclets(Function &F);
86
87 bool DemoteCatchSwitchPHIOnly;
88
89
90 EHPersonality Personality = EHPersonality::Unknown;
91
92 const DataLayout *DL = nullptr;
93 DenseMap<BasicBlock *, ColorVector> BlockColors;
94 MapVector<BasicBlock *, std::vector<BasicBlock *>> FuncletBlocks;
95};
96
98 bool DemoteCatchSwitchPHIOnly;
99
100public:
101 static char ID;
102
103 WinEHPrepare(bool DemoteCatchSwitchPHIOnly = false)
104 : FunctionPass(ID), DemoteCatchSwitchPHIOnly(DemoteCatchSwitchPHIOnly) {}
105
106 StringRef getPassName() const override {
107 return "Windows exception handling preparation";
108 }
109
111 return WinEHPrepareImpl(DemoteCatchSwitchPHIOnly).runOnFunction(Fn);
112 }
113};
114
115}
116
119 bool Changed = WinEHPrepareImpl(DemoteCatchSwitchPHIOnly).runOnFunction(F);
121}
122
123char WinEHPrepare::ID = 0;
125 false)
126
128 return new WinEHPrepare(DemoteCatchSwitchPHIOnly);
129}
130
131bool WinEHPrepareImpl::runOnFunction(Function &Fn) {
133 return false;
134
135
137
138
140 return false;
141
143 return prepareExplicitEH(Fn);
144}
145
154
156 int TryHigh, int CatchHigh,
159 TBME.TryLow = TryLow;
168 else
171 HT.Handler = CPI->getParent();
172 if (auto *AI =
175 else
178 }
180}
181
183 for (const User *U : CleanupPad->users())
185 return CRI->getUnwindDest();
186 return nullptr;
187}
188
191 auto *F = const_cast<Function *>(Fn);
195 if ()
196 continue;
197
198 auto &BBColors = BlockColors[&BB];
199 assert(BBColors.size() == 1 && "multi-color BB not removed by preparation");
201
203 auto *FuncletPad =
206 if (!FuncletPad)
207 FuncletUnwindDest = nullptr;
209 FuncletUnwindDest = CatchPad->getCatchSwitch()->getUnwindDest();
212 else
214
215 BasicBlock *InvokeUnwindDest = II->getUnwindDest();
216 int BaseState = -1;
217 if (FuncletUnwindDest == InvokeUnwindDest) {
220 BaseState = BaseStateI->second;
221 }
222
223 if (BaseState != -1) {
225 } else {
229 }
230 }
231}
232
233
234
246 struct WorkItem *WI = new WorkItem(BB, State);
248
249 while (!WorkList.empty()) {
252 int State = WI->State;
253 delete WI;
255 if (!Inserted && StateIt->second <= State)
256 continue;
257
260 if (It->isEHPad())
262 StateIt->second = State;
263
265
266 State = EHInfo.CxxUnwindMap[State].ToState;
269 const Function *Fn = Call->getCalledFunction();
271 (Fn->getIntrinsicID() == Intrinsic::seh_scope_begin ||
273
278
280
282 }
283 }
284
285 for (auto *SuccBB : successors(BB)) {
286 WI = new WorkItem(SuccBB, State);
288 }
289 }
290}
291
292
293
294
295
296
297
298
299
300
301
302
303
304
308 struct WorkItem *WI = new WorkItem(BB, State);
310
311 while (!WorkList.empty()) {
314 int State = WI->State;
315 delete WI;
318 continue;
319
322 if (It->isEHPad())
325
330 if ( ||
->getName().starts_with("__IsLocalUnwind"))
331 State = EHInfo.SEHUnwindMap[State].ToState;
333 State > 0) {
334
335 State = EHInfo.SEHUnwindMap[State].ToState;
338 const Function *Fn = Call->getCalledFunction();
341
345
347 }
348
349 for (auto *SuccBB : successors(BB)) {
350 WI = new WorkItem(SuccBB, State);
352 }
353 }
354}
355
356
357
359 Value *ParentPad) {
362 return nullptr;
364 if (CatchSwitch->getParentPad() != ParentPad)
365 return nullptr;
366 return BB;
367 }
370 if (CleanupPad->getParentPad() != ParentPad)
371 return nullptr;
372 return CleanupPad->getParent();
373}
374
375
376
377
380 int ParentState) {
383
386 "shouldn't revist catch funclets!");
387
389 for (const BasicBlock *CatchPadBB : CatchSwitch->handlers()) {
392 }
397 CatchSwitch->getParentPad())))
399 TryLow);
400 int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
401
402
403 int TryHigh = CatchLow - 1;
404
405
406
407
409 bool IsPreOrder = Mod->getTargetTriple().isArch64Bit();
410 if (IsPreOrder)
412 unsigned TBMEIdx = FuncInfo.TryBlockMap.size() - 1;
413
414 for (const auto *CatchPad : Handlers) {
417 for (const User *U : CatchPad->users()) {
420 BasicBlock *UnwindDest = InnerCatchSwitch->getUnwindDest();
421 if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
423 }
426
427
428
429 if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
431 }
432 }
433 }
435
436 if (IsPreOrder)
437 FuncInfo.TryBlockMap[TBMEIdx].CatchHigh = CatchHigh;
438 else
440
443 << '\n');
445 << '\n');
446 } else {
448
449
450
451 auto [It, Inserted] = FuncInfo.EHPadStateMap.try_emplace(CleanupPad);
452 if (!Inserted)
453 return;
454
456 It->second = CleanupState;
457 LLVM_DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
458 << BB->getName() << '\n');
461 CleanupPad->getParentPad()))) {
463 CleanupState);
464 }
465 }
466 for (const User *U : CleanupPad->users()) {
468 if (UserI->isEHPad())
469 report_fatal_error("Cleanup funclets for the MSVC++ personality cannot "
470 "contain exceptional actions");
471 }
472 }
473}
474
478 Entry.ToState = ParentState;
479 Entry.IsFinally = false;
480 Entry.Filter = Filter;
481 Entry.Handler = Handler;
484}
485
489 Entry.ToState = ParentState;
490 Entry.IsFinally = true;
491 Entry.Filter = nullptr;
492 Entry.Handler = Handler;
495}
496
497
498
499
502 int ParentState) {
505
508 "shouldn't revist catch funclets!");
509
510
511
512 assert(CatchSwitch->getNumHandlers() == 1 &&
513 "SEH doesn't have multiple handlers per __try");
514 const auto *CatchPad =
515 cast((*CatchSwitch->handler_begin())->getFirstNonPHIIt());
517 const Constant *FilterOrNull =
518 cast(CatchPad->getArgOperand(0)->stripPointerCasts());
521 "unexpected filter value");
522 int TryState = addSEHExcept(FuncInfo, ParentState, Filter, CatchPadBB);
523
524
527 LLVM_DEBUG(dbgs() << "Assigning state #" << TryState << " to BB "
528 << CatchPadBB->getName() << '\n');
531 CatchSwitch->getParentPad())))
533 TryState);
534
535
536
537 for (const User *U : CatchPad->users()) {
540 BasicBlock *UnwindDest = InnerCatchSwitch->getUnwindDest();
541 if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
543 }
546
547
548
549 if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
551 }
552 }
553 } else {
555
556
557
558 auto [It, Inserted] = FuncInfo.EHPadStateMap.try_emplace(CleanupPad);
559 if (!Inserted)
560 return;
561
562 int CleanupState = addSEHFinally(FuncInfo, ParentState, BB);
563 It->second = CleanupState;
564 LLVM_DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
565 << BB->getName() << '\n');
567 if ((PredBlock =
570 CleanupState);
571 for (const User *U : CleanupPad->users()) {
573 if (UserI->isEHPad())
574 report_fatal_error("Cleanup funclets for the SEH personality cannot "
575 "contain exceptional actions");
576 }
577 }
578}
579
583 CatchSwitch->unwindsToCaller();
588 return false;
590}
591
594
596 return;
597
599 if (!BB.isEHPad())
600 continue;
601 const Instruction *FirstNonPHI = &*BB.getFirstNonPHIIt();
603 continue;
605 }
606
608
610 if (IsEHa) {
613 }
614}
615
618
620 return;
621
623 if (!BB.isEHPad())
624 continue;
625 const Instruction *FirstNonPHI = &*BB.getFirstNonPHIIt();
627 continue;
629 }
630
632
634 if (IsEHa) {
637 }
638}
639
645 Entry.TryParentState = TryParentState;
646 Entry.Handler = Handler;
647 Entry.HandlerType = HandlerType;
648 Entry.TypeToken = TypeToken;
651}
652
655
657 return;
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
685 const Instruction *FirstNonPHI = &*BB.getFirstNonPHIIt();
686 const Value *ParentPad;
688 ParentPad = CPI->getParentPad();
690 ParentPad = CSI->getParentPad();
691 else
692 continue;
695 }
696
697
698
699
700
701
702
703 while (!Worklist.empty()) {
705 int HandlerParentState;
706 std::tie(Pad, HandlerParentState) = Worklist.pop_back_val();
707
709
710
714 int CleanupState = addClrEHHandler(FuncInfo, HandlerParentState, -1,
715 HandlerType, 0, Pad->getParent());
716
719 if (I->isEHPad())
721
723 } else {
724
725
727 int CatchState = -1, FollowerState = -1;
730
731
735 CatchState =
736 addClrEHHandler(FuncInfo, HandlerParentState, FollowerState,
738
739 for (const User *U : Catch->users())
741 if (I->isEHPad())
743
745 FollowerState = CatchState;
746 }
747
748 assert(CatchSwitch->getNumHandlers());
749 FuncInfo.EHPadStateMap[CatchSwitch] = CatchState;
750 }
751 }
752
753
754
755
759
760
763
764
765
766
767
768 if (Entry.TryParentState != -1)
769 continue;
770
771 UnwindDest = Catch->getCatchSwitch()->getUnwindDest();
772 } else {
774 UnwindDest = nullptr;
777
778
779 UnwindDest = CleanupRet->getUnwindDest();
780 break;
781 }
782
783
784 const BasicBlock *UserUnwindDest = nullptr;
786 UserUnwindDest = Invoke->getUnwindDest();
788 UserUnwindDest = CatchSwitch->getUnwindDest();
790 int UserState = FuncInfo.EHPadStateMap[ChildCleanup];
791 int UserUnwindState =
793 if (UserUnwindState != -1)
796 }
797
798
799
800
801
802 if (!UserUnwindDest)
803 continue;
804
805
806
808 const Value *UserUnwindParent;
810 UserUnwindParent = CSI->getParentPad();
811 else
812 UserUnwindParent =
814
815
816
817 if (UserUnwindParent == Cleanup)
818 continue;
819
820
821 UnwindDest = UserUnwindDest;
822 break;
823 }
824 }
825
826
827 int UnwindDestState;
828
829
830
831
832
833
834
835
836
837
838
839 if (!UnwindDest) {
840 UnwindDestState = -1;
841 } else {
842 UnwindDestState =
844 }
845
846 Entry.TryParentState = UnwindDestState;
847 }
848
849
851}
852
853void WinEHPrepareImpl::colorFunclets(Function &F) {
855
856
860 FuncletBlocks[Color].push_back(&BB);
861 }
862}
863
864bool WinEHPrepareImpl::demotePHIsOnFunclets(Function &F,
865 bool DemoteCatchSwitchPHIOnly) {
867
868
871 if (!BB.isEHPad())
872 continue;
873
876
877 if (!PN)
878 break;
879
880
881
882
883 if (DemoteCatchSwitchPHIOnly) {
885 bool HasIncomingCatchSwitchBB = false;
886 for (unsigned I = 0, E = PN->getNumIncomingValues(); I < E; ++I) {
888 PN->getIncomingBlock(I)->getFirstNonPHIIt())) {
889 HasIncomingCatchSwitchBB = true;
890 break;
891 }
892 }
893 if (!IsCatchSwitchBB && !HasIncomingCatchSwitchBB)
894 break;
895 }
896
898
899 AllocaInst *SpillSlot = insertPHILoads(PN, F);
900 if (SpillSlot)
901 insertPHIStores(PN, SpillSlot);
902
904 }
905 }
906
907 for (auto *PN : PHINodes) {
908
910 PN->eraseFromParent();
911 }
912
914}
915
916bool WinEHPrepareImpl::cloneCommonBlocks(Function &F) {
918
919
920
921
922 for (auto &Funclets : FuncletBlocks) {
923 BasicBlock *FuncletPadBB = Funclets.first;
924 std::vector<BasicBlock *> &BlocksInFunclet = Funclets.second;
925 Value *FuncletToken;
926 if (FuncletPadBB == &F.getEntryBlock())
928 else
930
931 std::vector<std::pair<BasicBlock *, BasicBlock *>> Orig2Clone;
933 for (BasicBlock *BB : BlocksInFunclet) {
934 ColorVector &ColorsForBB = BlockColors[BB];
935
936 size_t NumColorsForBB = ColorsForBB.size();
937 if (NumColorsForBB == 1)
938 continue;
939
941 dbgs() << " Cloning block \'" << BB->getName()
942 << "\' for funclet \'" << FuncletPadBB->getName()
943 << "\'.\n");
944
945
948
949
951
952
953 VMap[BB] = CBB;
954
955
956 Orig2Clone.emplace_back(BB, CBB);
957 }
958
959
960 if (Orig2Clone.empty())
961 continue;
962
964
965
966
967 for (auto &BBMapping : Orig2Clone) {
968 BasicBlock *OldBlock = BBMapping.first;
969 BasicBlock *NewBlock = BBMapping.second;
970
971 BlocksInFunclet.push_back(NewBlock);
972 ColorVector &NewColors = BlockColors[NewBlock];
973 assert(NewColors.empty() && "A new block should only have one color!");
974 NewColors.push_back(FuncletPadBB);
975
977 dbgs() << " Assigned color \'" << FuncletPadBB->getName()
978 << "\' to block \'" << NewBlock->getName()
979 << "\'.\n");
980
982 ColorVector &OldColors = BlockColors[OldBlock];
984
986 dbgs() << " Removed color \'" << FuncletPadBB->getName()
987 << "\' from block \'" << OldBlock->getName()
988 << "\'.\n");
989 }
990
991
992
993 for (BasicBlock *BB : BlocksInFunclet)
994
998
999
1000
1002 for (auto &BBMapping : Orig2Clone) {
1003 BasicBlock *OldBlock = BBMapping.first;
1004 BasicBlock *NewBlock = BBMapping.second;
1005
1006 FixupCatchrets.clear();
1009 if (CatchRet->getCatchSwitchParentPad() == FuncletToken)
1010 FixupCatchrets.push_back(CatchRet);
1011
1013 CatchRet->setSuccessor(NewBlock);
1014 }
1015
1016 auto UpdatePHIOnClonedBlock = [&](PHINode *PN, bool IsForOldBlock) {
1018 for (unsigned PredIdx = 0, PredEnd = NumPreds; PredIdx != PredEnd;
1019 ++PredIdx) {
1021 bool EdgeTargetsFunclet;
1022 if (auto *CRI =
1024 EdgeTargetsFunclet = (CRI->getCatchSwitchParentPad() == FuncletToken);
1025 } else {
1026 ColorVector &IncomingColors = BlockColors[IncomingBlock];
1027 assert(!IncomingColors.empty() && "Block not colored!");
1028 assert((IncomingColors.size() == 1 ||
1030 "Cloning should leave this funclet's blocks monochromatic");
1031 EdgeTargetsFunclet = (IncomingColors.front() == FuncletPadBB);
1032 }
1033 if (IsForOldBlock != EdgeTargetsFunclet)
1034 continue;
1036
1037 --PredIdx;
1038 --PredEnd;
1039 }
1040 };
1041
1042 for (auto &BBMapping : Orig2Clone) {
1043 BasicBlock *OldBlock = BBMapping.first;
1044 BasicBlock *NewBlock = BBMapping.second;
1045 for (PHINode &OldPN : OldBlock->phis()) {
1046 UpdatePHIOnClonedBlock(&OldPN, true);
1047 }
1048 for (PHINode &NewPN : NewBlock->phis()) {
1049 UpdatePHIOnClonedBlock(&NewPN, false);
1050 }
1051 }
1052
1053
1054
1055 for (auto &BBMapping : Orig2Clone) {
1056 BasicBlock *OldBlock = BBMapping.first;
1057 BasicBlock *NewBlock = BBMapping.second;
1059 for (PHINode &SuccPN : SuccBB->phis()) {
1060
1061
1062 int OldBlockIdx = SuccPN.getBasicBlockIndex(OldBlock);
1063 if (OldBlockIdx == -1)
1064 break;
1065 Value *IV = SuccPN.getIncomingValue(OldBlockIdx);
1066
1067
1072 }
1073
1074 SuccPN.addIncoming(IV, NewBlock);
1075 }
1076 }
1077 }
1078
1080
1081
1082
1083
1084
1086
1088 if (!OldI)
1089 continue;
1091
1092
1093 for (Use &U : OldI->uses()) {
1096 ColorVector &ColorsForUserBB = BlockColors[UserBB];
1098 if (ColorsForUserBB.size() > 1 ||
1099 *ColorsForUserBB.begin() != FuncletPadBB)
1101 }
1102
1103
1104
1105 if (UsesToRename.empty())
1106 continue;
1107
1108
1109
1110
1112 SSAUpdate.Initialize(OldI->getType(), OldI->getName());
1115
1116 while (!UsesToRename.empty())
1118 }
1119 }
1120
1122}
1123
1124bool WinEHPrepareImpl::removeImplausibleInstructions(Function &F) {
1126
1127
1128 for (auto &Funclet : FuncletBlocks) {
1129 BasicBlock *FuncletPadBB = Funclet.first;
1130 std::vector<BasicBlock *> &BlocksInFunclet = Funclet.second;
1135
1136 for (BasicBlock *BB : BlocksInFunclet) {
1139 if (!CB)
1140 continue;
1141
1142 Value *FuncletBundleOperand = nullptr;
1144 FuncletBundleOperand = BU->Inputs.front();
1145
1146 if (FuncletBundleOperand == FuncletPad)
1147 continue;
1148
1149
1150 auto *CalledFn =
1152 if (CB->isInlineAsm() ||
1153 (CalledFn && CalledFn->isIntrinsic() && CB->doesNotThrow()))
1154 continue;
1155
1157
1158
1160
1162
1164 std::prev(BB->getTerminator()->getIterator());
1167 } else {
1169 }
1170
1171
1172
1173 break;
1174 }
1175
1177
1178 bool IsUnreachableRet = isa(TI) && FuncletPad;
1179
1180 bool IsUnreachableCatchret = false;
1182 IsUnreachableCatchret = CRI->getCatchPad() != CatchPad;
1183
1184 bool IsUnreachableCleanupret = false;
1186 IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;
1187 if (IsUnreachableRet || IsUnreachableCatchret ||
1188 IsUnreachableCleanupret) {
1194
1195
1196
1198 }
1199 }
1200 }
1201 }
1202
1204}
1205
1206bool WinEHPrepareImpl::cleanupPreparedFunclets(Function &F) {
1208
1209
1210
1215 }
1216
1217
1218
1220
1222}
1223
1224#ifndef NDEBUG
1225void WinEHPrepareImpl::verifyPreparedFunclets(Function &F) {
1227 size_t NumColors = BlockColors[&BB].size();
1228 assert(NumColors == 1 && "Expected monochromatic BB!");
1229 if (NumColors == 0)
1231 if (NumColors > 1)
1234 "EH Pad still has a PHI!");
1235 }
1236}
1237#endif
1238
1239bool WinEHPrepareImpl::prepareExplicitEH(Function &F) {
1240
1241
1242
1244
1245
1246 colorFunclets(F);
1247
1248 Changed |= cloneCommonBlocks(F);
1249
1251 Changed |= demotePHIsOnFunclets(F, DemoteCatchSwitchPHIOnly ||
1253
1256 Changed |= removeImplausibleInstructions(F);
1257
1259 Changed |= cleanupPreparedFunclets(F);
1260 }
1261
1263
1266
1268}
1269
1270
1271
1276
1278
1279
1280 SpillSlot = new AllocaInst(PN->getType(), DL->getAllocaAddrSpace(), nullptr,
1282 F.getEntryBlock().begin());
1287 return SpillSlot;
1288 }
1289
1290
1291
1295 if (isa(UsingInst) && UsingInst->getParent()->isEHPad()) {
1296
1297
1298 continue;
1299 }
1300 replaceUseWithLoad(PN, U, SpillSlot, Loads, F);
1301 }
1302 return SpillSlot;
1303}
1304
1305
1306
1307
1308
1309void WinEHPrepareImpl::insertPHIStores(PHINode *OriginalPHI,
1311
1312
1314
1316
1317 while (!Worklist.empty()) {
1320 std::tie(EHBlock, InVal) = Worklist.pop_back_val();
1321
1323 if (PN && PN->getParent() == EHBlock) {
1324
1325
1326
1329
1330
1332 continue;
1333
1334 insertPHIStore(PN->getIncomingBlock(i), PredVal, SpillSlot, Worklist);
1335 }
1336 } else {
1337
1338
1340 insertPHIStore(PredBlock, InVal, SpillSlot, Worklist);
1341 }
1342 }
1343 }
1344}
1345
1346void WinEHPrepareImpl::insertPHIStore(
1348 SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist) {
1349
1351
1352 Worklist.push_back({PredBlock, PredVal});
1353 return;
1354 }
1355
1356
1358}
1359
1360void WinEHPrepareImpl::replaceUseWithLoad(
1363
1364 if (!SpillSlot)
1365 SpillSlot = new AllocaInst(V->getType(), DL->getAllocaAddrSpace(), nullptr,
1366 Twine(V->getName(), ".wineh.spillslot"),
1367 F.getEntryBlock().begin());
1368
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380 BasicBlock *IncomingBlock = UsingPHI->getIncomingBlock(U);
1381 if (auto *CatchRet =
1383
1384
1385
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1404 CatchRet->removeFromParent();
1405 CatchRet->insertInto(IncomingBlock, IncomingBlock->end());
1408 CatchRet->setSuccessor(NewBlock);
1409
1410
1411
1412
1413 ColorVector &ColorsForNewBlock = BlockColors[NewBlock];
1414 ColorVector &ColorsForPHIBlock = BlockColors[PHIBlock];
1415 ColorsForNewBlock = ColorsForPHIBlock;
1416 for (BasicBlock *FuncletPad : ColorsForPHIBlock)
1417 FuncletBlocks[FuncletPad].push_back(NewBlock);
1418
1419 IncomingBlock = NewBlock;
1420 }
1421 Value *&Load = Loads[IncomingBlock];
1422
1423 if (!Load)
1425 V->getType(), SpillSlot, Twine(V->getName(), ".wineh.reload"),
1427
1428 U.set(Load);
1429 } else {
1430
1431 auto *Load = new LoadInst(V->getType(), SpillSlot,
1432 Twine(V->getName(), ".wineh.reload"),
1433 false, UsingInst->getIterator());
1434 U.set(Load);
1435 }
1436}
1437
1442 "should get invoke with precomputed state");
1444}
1445
1448 LabelToStateMap[InvokeBegin] = std::make_pair(State, InvokeEnd);
1449}
1450
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
static const HTTPClientCleanup Cleanup
Module.h This file contains the declarations for the Module class.
This file implements a map that provides insertion order iteration.
uint64_t IntrinsicInst * II
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static cl::opt< bool > DisableDemotion("disable-demotion", cl::Hidden, cl::desc("Clone multicolor basic blocks but do not demote cross scopes"), cl::init(false))
static int addUnwindMapEntry(WinEHFuncInfo &FuncInfo, int ToState, const BasicBlock *BB)
Definition WinEHPrepare.cpp:146
static void calculateStateNumbersForInvokes(const Function *Fn, WinEHFuncInfo &FuncInfo)
Definition WinEHPrepare.cpp:189
static BasicBlock * getCleanupRetUnwindDest(const CleanupPadInst *CleanupPad)
Definition WinEHPrepare.cpp:182
static cl::opt< bool > DisableCleanups("disable-cleanups", cl::Hidden, cl::desc("Do not remove implausible terminators or other similar cleanups"), cl::init(false))
static int addSEHFinally(WinEHFuncInfo &FuncInfo, int ParentState, const BasicBlock *Handler)
Definition WinEHPrepare.cpp:486
static const BasicBlock * getEHPadFromPredecessor(const BasicBlock *BB, Value *ParentPad)
Definition WinEHPrepare.cpp:358
static int addClrEHHandler(WinEHFuncInfo &FuncInfo, int HandlerParentState, int TryParentState, ClrHandlerType HandlerType, uint32_t TypeToken, const BasicBlock *Handler)
Definition WinEHPrepare.cpp:640
static void calculateCXXStateNumbers(WinEHFuncInfo &FuncInfo, const Instruction *FirstNonPHI, int ParentState)
Definition WinEHPrepare.cpp:378
static cl::opt< bool > DemoteCatchSwitchPHIOnlyOpt("demote-catchswitch-only", cl::Hidden, cl::desc("Demote catchswitch BBs only (for wasm EH)"), cl::init(false))
static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow, int TryHigh, int CatchHigh, ArrayRef< const CatchPadInst * > Handlers)
Definition WinEHPrepare.cpp:155
static bool isTopLevelPadForMSVC(const Instruction *EHPad)
Definition WinEHPrepare.cpp:580
static int addSEHExcept(WinEHFuncInfo &FuncInfo, int ParentState, const Function *Filter, const BasicBlock *Handler)
Definition WinEHPrepare.cpp:475
static const uint32_t IV[8]
an instruction to allocate memory on the stack
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
InstListType::const_iterator const_iterator
const Instruction & front() const
LLVM_ABI void insertInto(Function *Parent, BasicBlock *InsertBefore=nullptr)
Insert unlinked basic block into a function.
InstListType::iterator iterator
Instruction iterators...
bool isEHPad() const
Return true if this basic block is an exception handling block.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Conditional or Unconditional Branch instruction.
void setSuccessor(unsigned idx, BasicBlock *NewSucc)
static LLVM_ABI ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
This is an important base class in LLVM.
const Constant * stripPointerCasts() const
LLVM_ABI bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
FunctionPass class - This class is used to implement most global optimizations.
const BasicBlock & getEntryBlock() const
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
bool hasPersonalityFn() const
Check whether this function has a personality function.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
bool isEHPad() const
Return true if the instruction is a variety of EH-block.
bool isTerminator() const
LLVM_ABI InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
An instruction for reading from memory.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
A Module instance is used to store all the information related to an LLVM module.
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
LLVM_ABI Value * removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty=true)
Remove an incoming value.
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Helper class for SSA formation on a set of values defined in multiple blocks.
void RewriteUseAfterInsertions(Use &U)
Rewrite a use like RewriteUse but handling in-block definitions.
void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
void AddAvailableValue(BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
void push_back(EltTy NewVal)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
A Use represents the edge between a Value definition and its users.
std::pair< const Value *, WeakTrackingVH > value_type
iterator find(const KeyT &Val)
ValueMapIteratorImpl< MapT, const Value *, false > iterator
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Definition WinEHPrepare.cpp:117
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions=false, const TargetLibraryInfo *TLI=nullptr, DomTreeUpdater *DTU=nullptr)
If a terminator instruction is predicated on a constant value, convert it into an unconditional branc...
LLVM_ABI BasicBlock * CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, const Twine &NameSuffix="", Function *F=nullptr, ClonedCodeInfo *CodeInfo=nullptr, bool MapAtoms=true)
Return a copy of the specified basic block, but without embedding the block into a particular functio...
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
LLVM_ABI bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
auto successors(const MachineBasicBlock *BB)
LLVM_ABI DenseMap< BasicBlock *, ColorVector > colorEHFunclets(Function &F)
If an EH funclet personality is in use (see isFuncletEHPersonality), this will recompute which blocks...
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI bool SimplifyInstructionsInBlock(BasicBlock *BB, const TargetLibraryInfo *TLI=nullptr)
Scan the specified basic block and try to simplify any instructions in it and recursively delete dead...
void calculateWinCXXEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo)
Analyze the IR in ParentFn and it's handlers to build WinEHFuncInfo, which describes the state number...
Definition WinEHPrepare.cpp:616
bool isScopedEHPersonality(EHPersonality Pers)
Returns true if this personality uses scope-style EH IR instructions: catchswitch,...
auto dyn_cast_or_null(const Y &Val)
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
auto reverse(ContainerTy &&C)
@ RF_IgnoreMissingLocals
If this flag is set, the remapper ignores missing function-local entries (Argument,...
@ RF_NoModuleLevelChanges
If this flag is set, the remapper knows that only local values within a function (such as an instruct...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI Instruction * removeUnwindEdge(BasicBlock *BB, DomTreeUpdater *DTU=nullptr)
Replace 'BB's terminator with one that does not have an unwind successor block.
void calculateSEHStateForAsynchEH(const BasicBlock *BB, int State, WinEHFuncInfo &FuncInfo)
Definition WinEHPrepare.cpp:305
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
void calculateCXXStateForAsynchEH(const BasicBlock *BB, int State, WinEHFuncInfo &FuncInfo)
Definition WinEHPrepare.cpp:243
void calculateSEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo)
Definition WinEHPrepare.cpp:592
LLVM_ABI bool MergeBlockIntoPredecessor(BasicBlock *BB, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, MemoryDependenceResults *MemDep=nullptr, bool PredecessorWithTwoSuccessors=false, DominatorTree *DT=nullptr)
Attempts to merge a block into its predecessor, if possible.
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, RemapFlags Flags=RF_None, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr, const MetadataPredicate *IdentityMD=nullptr)
Convert the instruction operands from referencing the current values into those specified by VM.
LLVM_ABI FunctionPass * createWinEHPass(bool DemoteCatchSwitchPHIOnly=false)
createWinEHPass - Prepares personality functions used by MSVC on Windows, in addition to the Itanium ...
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
TinyPtrVector< BasicBlock * > ColorVector
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the edge connecting the specified blocks, and return the newly created basic block between From...
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
void calculateClrEHStateNumbers(const Function *Fn, WinEHFuncInfo &FuncInfo)
Definition WinEHPrepare.cpp:653
const BasicBlock * Block
Definition WinEHPrepare.cpp:236
WorkItem(const BasicBlock *BB, int St)
Definition WinEHPrepare.cpp:238
int State
Definition WinEHPrepare.cpp:237
int HandlerParentState
Outer handler enclosing this entry's handler.
Similar to CxxUnwindMapEntry, but supports SEH filters.
int ToState
If unwinding continues through this handler, transition to the handler at this state.
void addIPToStateRange(const InvokeInst *II, MCSymbol *InvokeBegin, MCSymbol *InvokeEnd)
Definition WinEHPrepare.cpp:1438
SmallVector< SEHUnwindMapEntry, 4 > SEHUnwindMap
SmallVector< ClrEHUnwindMapEntry, 4 > ClrEHUnwindMap
DenseMap< const FuncletPadInst *, int > FuncletBaseStateMap
DenseMap< const BasicBlock *, int > BlockToStateMap
DenseMap< const InvokeInst *, int > InvokeStateMap
SmallVector< WinEHTryBlockMapEntry, 4 > TryBlockMap
DenseMap< const Instruction *, int > EHPadStateMap
DenseMap< MCSymbol *, std::pair< int, MCSymbol * > > LabelToStateMap
SmallVector< CxxUnwindMapEntry, 4 > CxxUnwindMap
int getLastStateNumber() const
GlobalVariable * TypeDescriptor
union llvm::WinEHHandlerType::@246205307012256373115155017221207221353102114334 CatchObj
The CatchObj starts out life as an LLVM alloca and is eventually turned frame index.
const AllocaInst * Alloca
SmallVector< WinEHHandlerType, 1 > HandlerArray