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 (II)

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 (Filter || Filter->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

1070 if (I != VMap.end())

1071 IV = I->second;

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