47#define DEBUG_TYPE "wasm-cfg-stackify"
49STATISTIC(NumCallUnwindMismatches,
"Number of call unwind mismatches found");
50STATISTIC(NumCatchUnwindMismatches,
"Number of catch unwind mismatches found");
53class WebAssemblyCFGStackifyImpl {
65 if (!ScopeTops[EndNo] || ScopeTops[EndNo]->getNumber() > BeginNo)
66 ScopeTops[EndNo] = Begin;
70 void placeMarkers(MachineFunction &MF);
71 void placeBlockMarker(MachineBasicBlock &
MBB);
72 void placeLoopMarker(MachineBasicBlock &
MBB);
73 void placeTryMarker(MachineBasicBlock &
MBB);
74 void placeTryTableMarker(MachineBasicBlock &
MBB);
78 bool fixCallUnwindMismatches(MachineFunction &MF);
79 bool fixCatchUnwindMismatches(MachineFunction &MF);
80 void recalculateScopeTops(MachineFunction &MF);
82 void addNestedTryDelegate(MachineInstr *RangeBegin, MachineInstr *RangeEnd,
83 MachineBasicBlock *UnwindDest);
84 void removeUnnecessaryInstrs(MachineFunction &MF);
86 void addNestedTryTable(MachineInstr *RangeBegin, MachineInstr *RangeEnd,
87 MachineBasicBlock *UnwindDest);
88 MachineBasicBlock *getTrampolineBlock(MachineBasicBlock *UnwindDest);
92 std::pair<const MachineBasicBlock *, const MachineInstr *>;
93 unsigned getBranchDepth(
const SmallVectorImpl<EndMarkerInfo> &Stack,
94 const MachineBasicBlock *
MBB);
95 unsigned getDelegateDepth(
const SmallVectorImpl<EndMarkerInfo> &Stack,
96 const MachineBasicBlock *
MBB);
97 unsigned getRethrowDepth(
const SmallVectorImpl<EndMarkerInfo> &Stack,
98 const MachineBasicBlock *EHPadToRethrow);
99 void rewriteDepthImmediates(MachineFunction &MF);
100 void fixEndsAtEndOfFunction(MachineFunction &MF);
101 void cleanupFunctionData(MachineFunction &MF);
105 DenseMap<const MachineInstr *, MachineInstr *> BeginToEnd;
108 DenseMap<const MachineInstr *, MachineInstr *> EndToBegin;
110 DenseMap<const MachineInstr *, MachineBasicBlock *> TryToEHPad;
112 DenseMap<const MachineBasicBlock *, MachineInstr *> EHPadToTry;
114 DenseMap<const MachineBasicBlock *, MachineBasicBlock *>
115 UnwindDestToTrampoline;
119 MachineBasicBlock *AppendixBB =
nullptr;
120 MachineBasicBlock *getAppendixBlock(MachineFunction &MF) {
127 if (CallerTrampolineBB)
128 MF.
insert(CallerTrampolineBB->getIterator(), AppendixBB);
137 MachineBasicBlock *CallerTrampolineBB =
nullptr;
138 MachineBasicBlock *getCallerTrampolineBlock(MachineFunction &MF) {
139 if (!CallerTrampolineBB) {
143 return CallerTrampolineBB;
152 MachineBasicBlock *FakeCallerBB =
nullptr;
153 MachineBasicBlock *getFakeCallerBlock(MachineFunction &MF) {
161 void registerScope(MachineInstr *Begin, MachineInstr *End);
162 void registerTryScope(MachineInstr *Begin, MachineInstr *End,
163 MachineBasicBlock *EHPad);
164 void unregisterScope(MachineInstr *Begin);
167 WebAssemblyCFGStackifyImpl(MachineDominatorTree &MDT, MachineLoopInfo &MLI,
168 WebAssemblyExceptionInfo &WEI)
169 : MDT(MDT), MLI(MLI), WEI(WEI) {}
171 bool runOnMachineFunction(MachineFunction &MF);
175 StringRef getPassName()
const override {
return "WebAssembly CFG Stackify"; }
177 void getAnalysisUsage(AnalysisUsage &AU)
const override {
180 AU.
addRequired<WebAssemblyExceptionInfoWrapperPass>();
185 bool runOnMachineFunction(MachineFunction &MF)
override;
187 WebAssemblyCFGStackifyLegacy() : MachineFunctionPass(ID) {}
191char WebAssemblyCFGStackifyLegacy::ID = 0;
194 "Insert BLOCK/LOOP/TRY/TRY_TABLE markers for WebAssembly scopes",
false,
198 return new WebAssemblyCFGStackifyLegacy();
210 if (MO.isMBB() && MO.getMBB() ==
MBB)
220template <
typename Container>
223 const Container &AfterSet) {
224 auto InsertPos =
MBB->end();
225 while (InsertPos !=
MBB->begin()) {
226 if (BeforeSet.count(&*std::prev(InsertPos))) {
229 for (
auto Pos = InsertPos,
E =
MBB->begin(); Pos !=
E; --Pos)
230 assert(!AfterSet.count(&*std::prev(Pos)));
244template <
typename Container>
247 const Container &AfterSet) {
248 auto InsertPos =
MBB->begin();
249 while (InsertPos !=
MBB->end()) {
250 if (AfterSet.count(&*InsertPos)) {
253 for (
auto Pos = InsertPos,
E =
MBB->end(); Pos !=
E; ++Pos)
254 assert(!BeforeSet.count(&*Pos));
263void WebAssemblyCFGStackifyImpl::registerScope(
MachineInstr *Begin,
265 BeginToEnd[Begin] = End;
266 EndToBegin[End] = Begin;
270void WebAssemblyCFGStackifyImpl::registerTryScope(MachineInstr *Begin,
272 MachineBasicBlock *EHPad) {
273 registerScope(Begin, End);
274 TryToEHPad[Begin] = EHPad;
275 EHPadToTry[EHPad] = Begin;
278void WebAssemblyCFGStackifyImpl::unregisterScope(MachineInstr *Begin) {
280 MachineInstr *End = BeginToEnd[Begin];
282 BeginToEnd.
erase(Begin);
283 EndToBegin.
erase(End);
284 MachineBasicBlock *EHPad = TryToEHPad.
lookup(Begin);
287 TryToEHPad.
erase(Begin);
288 EHPadToTry.
erase(EHPad);
295void WebAssemblyCFGStackifyImpl::placeBlockMarker(MachineBasicBlock &
MBB) {
298 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
299 const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
304 MachineBasicBlock *Header =
nullptr;
305 bool IsBranchedTo =
false;
308 if (Pred->getNumber() < MBBNumber) {
319 assert(&
MBB != &MF.
front() &&
"Header blocks shouldn't have predecessors");
325 if (MachineBasicBlock *ScopeTop = ScopeTops[
I->getNumber()]) {
326 if (ScopeTop->getNumber() > Header->getNumber()) {
328 I = std::next(ScopeTop->getIterator());
340 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
342 SmallPtrSet<const MachineInstr *, 4> AfterSet;
343 for (
const auto &
MI : *Header) {
347 if (
MI.getOpcode() == WebAssembly::LOOP) {
348 auto *LoopBottom = BeginToEnd[&
MI]->getParent()->getPrevNode();
361 if (
MI.getOpcode() == WebAssembly::BLOCK ||
362 MI.getOpcode() == WebAssembly::TRY ||
363 MI.getOpcode() == WebAssembly::TRY_TABLE) {
374 if (
MI.getOpcode() == WebAssembly::END_BLOCK ||
375 MI.getOpcode() == WebAssembly::END_LOOP ||
376 MI.getOpcode() == WebAssembly::END_TRY ||
377 MI.getOpcode() == WebAssembly::END_TRY_TABLE)
382 if (
MI.isTerminator())
387 for (
auto I = Header->getFirstTerminator(),
E = Header->begin();
I !=
E;
389 if (std::prev(
I)->isDebugInstr() || std::prev(
I)->isPosition())
391 if (WebAssembly::isChild(*std::prev(
I), MFI))
392 AfterSet.
insert(&*std::prev(
I));
398 WebAssembly::BlockType
ReturnType = WebAssembly::BlockType::Void;
400 MachineInstr *Begin =
401 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
402 TII.get(WebAssembly::BLOCK))
403 .
addImm(int64_t(ReturnType));
408 for (
auto &
MI :
MBB) {
411 if (
MI.getOpcode() == WebAssembly::LOOP)
424 if (
MI.getOpcode() == WebAssembly::END_LOOP ||
425 MI.getOpcode() == WebAssembly::END_TRY) {
426 if (EndToBegin[&
MI]->
getParent()->getNumber() >= Header->getNumber())
438 TII.get(WebAssembly::END_BLOCK));
439 registerScope(Begin, End);
442 updateScopeTops(Header, &
MBB);
446void WebAssemblyCFGStackifyImpl::placeLoopMarker(MachineBasicBlock &
MBB) {
448 SortRegionInfo SRI(MLI, WEI);
449 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
457 MachineBasicBlock *Bottom = SRI.getBottom(Loop);
459 if (Iter == MF.
end()) {
460 getAppendixBlock(MF);
463 MachineBasicBlock *AfterLoop = &*Iter;
466 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
467 SmallPtrSet<const MachineInstr *, 4> AfterSet;
468 for (
const auto &
MI :
MBB) {
471 if (
MI.getOpcode() == WebAssembly::END_LOOP)
482 TII.get(WebAssembly::LOOP))
483 .
addImm(int64_t(WebAssembly::BlockType::Void));
489 for (
const auto &
MI :
MBB)
491 if (
MI.getOpcode() == WebAssembly::END_LOOP)
500 : (*AfterLoop->pred_rbegin())->findBranchDebugLoc();
502 BuildMI(*AfterLoop, InsertPos, EndDL,
TII.get(WebAssembly::END_LOOP));
503 registerScope(Begin, End);
507 "With block sorting the outermost loop for a block should be first.");
508 updateScopeTops(&
MBB, AfterLoop);
511void WebAssemblyCFGStackifyImpl::placeTryMarker(MachineBasicBlock &
MBB) {
514 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
515 SortRegionInfo SRI(MLI, WEI);
516 const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
519 MachineBasicBlock *Header =
nullptr;
522 if (Pred->getNumber() < MBBNumber) {
525 "Explicit branch to an EH pad!");
535 MachineBasicBlock *Bottom = SRI.getBottom(WE);
537 if (Iter == MF.
end()) {
538 getAppendixBlock(MF);
541 MachineBasicBlock *Cont = &*Iter;
546 if (MachineBasicBlock *ScopeTop = ScopeTops[
I->getNumber()]) {
547 if (ScopeTop->getNumber() > Header->getNumber()) {
549 I = std::next(ScopeTop->getIterator());
561 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
563 SmallPtrSet<const MachineInstr *, 4> AfterSet;
564 for (
const auto &
MI : *Header) {
568 if (
MI.getOpcode() == WebAssembly::LOOP) {
569 auto *LoopBottom = BeginToEnd[&
MI]->getParent()->getPrevNode();
580 if (
MI.getOpcode() == WebAssembly::BLOCK ||
581 MI.getOpcode() == WebAssembly::TRY)
586 if (
MI.getOpcode() == WebAssembly::END_BLOCK ||
587 MI.getOpcode() == WebAssembly::END_LOOP ||
588 MI.getOpcode() == WebAssembly::END_TRY)
593 if (
MI.isTerminator())
602 MachineInstr *ThrowingCall =
nullptr;
604 auto TermPos = Header->getFirstTerminator();
605 if (TermPos == Header->end() ||
606 TermPos->getOpcode() != WebAssembly::RETHROW) {
613 if (
MI.getIterator() != Header->begin() &&
614 std::prev(
MI.getIterator())->isEHLabel()) {
615 AfterSet.
insert(&*std::prev(
MI.getIterator()));
616 ThrowingCall = &*std::prev(
MI.getIterator());
631 : Header->getFirstTerminator();
632 for (
auto I = SearchStartPt,
E = Header->begin();
I !=
E; --
I) {
633 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
635 if (WebAssembly::isChild(*std::prev(I), MFI))
636 AfterSet.insert(&*std::prev(I));
643 MachineInstr *Begin =
644 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
645 TII.get(WebAssembly::TRY))
646 .
addImm(int64_t(WebAssembly::BlockType::Void));
651 for (
const auto &
MI : *Cont) {
654 if (
MI.getOpcode() == WebAssembly::LOOP)
659 if (
MI.getOpcode() == WebAssembly::END_TRY)
667 if (
MI.getOpcode() == WebAssembly::END_LOOP) {
670 if (EndToBegin[&
MI]->
getParent()->getNumber() > Header->getNumber())
684 TII.get(WebAssembly::END_TRY));
685 registerTryScope(Begin, End, &
MBB);
698 for (
auto *End : {&
MBB, Cont})
699 updateScopeTops(Header, End);
702void WebAssemblyCFGStackifyImpl::placeTryTableMarker(MachineBasicBlock &
MBB) {
705 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
706 SortRegionInfo SRI(MLI, WEI);
707 const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
710 MachineBasicBlock *Header =
nullptr;
713 if (Pred->getNumber() < MBBNumber) {
716 "Explicit branch to an EH pad!");
727 MachineBasicBlock *Bottom = SRI.getBottom(WE);
729 if (Iter == MF.
end())
731 MachineBasicBlock *Cont = &*Iter;
736 if (MachineBasicBlock *ScopeTop = ScopeTops[
I->getNumber()]) {
737 if (ScopeTop->getNumber() > Header->getNumber()) {
739 I = std::next(ScopeTop->getIterator());
751 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
753 SmallPtrSet<const MachineInstr *, 4> AfterSet;
754 for (
const auto &
MI : *Header) {
758 if (
MI.getOpcode() == WebAssembly::LOOP) {
759 auto *LoopBottom = BeginToEnd[&
MI]->getParent()->getPrevNode();
770 if (
MI.getOpcode() == WebAssembly::BLOCK ||
771 MI.getOpcode() == WebAssembly::TRY_TABLE)
776 if (
MI.getOpcode() == WebAssembly::END_BLOCK ||
777 MI.getOpcode() == WebAssembly::END_LOOP ||
778 MI.getOpcode() == WebAssembly::END_TRY_TABLE)
783 if (
MI.isTerminator())
792 MachineInstr *ThrowingCall =
nullptr;
794 auto TermPos = Header->getFirstTerminator();
795 if (TermPos == Header->end() ||
796 TermPos->getOpcode() != WebAssembly::RETHROW) {
803 if (
MI.getIterator() != Header->begin() &&
804 std::prev(
MI.getIterator())->isEHLabel()) {
805 AfterSet.
insert(&*std::prev(
MI.getIterator()));
806 ThrowingCall = &*std::prev(
MI.getIterator());
821 : Header->getFirstTerminator();
822 for (
auto I = SearchStartPt,
E = Header->begin();
I !=
E; --
I) {
823 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
825 if (WebAssembly::isChild(*std::prev(I), MFI))
826 AfterSet.insert(&*std::prev(I));
845 MachineInstrBuilder BlockMIB =
846 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
847 TII.get(WebAssembly::BLOCK));
849 MachineInstrBuilder TryTableMIB =
850 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
851 TII.get(WebAssembly::TRY_TABLE))
852 .
addImm(int64_t(WebAssembly::BlockType::Void))
854 auto *TryTable = TryTableMIB.
getInstr();
860 *MF.
getSubtarget<WebAssemblySubtarget>().getTargetLowering();
861 WebAssembly::BlockType PtrTy =
863 ? WebAssembly::BlockType::I32
864 : WebAssembly::BlockType::I64;
865 auto *
Catch = WebAssembly::findCatch(&
MBB);
866 switch (
Catch->getOpcode()) {
867 case WebAssembly::CATCH:
871 BlockMIB.
addImm(int64_t(PtrTy));
873 for (
const auto &Use :
Catch->uses()) {
880 case WebAssembly::CATCH_REF:
885 BlockMIB.
addImm(int64_t(WebAssembly::BlockType::Multivalue));
888 for (
const auto &Use :
Catch->uses()) {
894 case WebAssembly::CATCH_ALL:
896 BlockMIB.
addImm(int64_t(WebAssembly::BlockType::Void));
900 case WebAssembly::CATCH_ALL_REF:
902 BlockMIB.
addImm(int64_t(WebAssembly::BlockType::Exnref));
912 for (
const auto &
MI :
MBB) {
915 if (
MI.getOpcode() == WebAssembly::LOOP)
923 if (
MI.getOpcode() == WebAssembly::END_LOOP) {
924 if (EndToBegin[&
MI]->
getParent()->getNumber() >= Header->getNumber())
936 if (WebAssembly::isCatch(
MI.getOpcode()))
943 MachineInstr *EndTryTable =
945 TII.get(WebAssembly::END_TRY_TABLE));
946 registerTryScope(TryTable, EndTryTable, &
MBB);
947 MachineInstr *EndBlock =
949 TII.get(WebAssembly::END_BLOCK));
950 registerScope(
Block, EndBlock);
992 for (
auto *End : {&
MBB, Cont})
993 updateScopeTops(Header, End);
996void WebAssemblyCFGStackifyImpl::removeUnnecessaryInstrs(MachineFunction &MF) {
997 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
1032 for (
auto &
MBB : MF) {
1036 MachineBasicBlock *
TBB =
nullptr, *FBB =
nullptr;
1040 MachineBasicBlock *Cont = &
MBB;
1042 MachineInstr *Try = EHPadToTry[Cont];
1043 MachineInstr *EndTry = BeginToEnd[Try];
1056 if (Analyzable && ((
Cond.empty() &&
TBB &&
TBB == Cont) ||
1057 (!
Cond.empty() && FBB && FBB == Cont))) {
1058 bool ErasedUncondBr =
false;
1059 (void)ErasedUncondBr;
1060 for (
auto I = EHPadLayoutPred->
end(),
E = EHPadLayoutPred->
begin();
1062 auto PrevI = std::prev(
I);
1063 if (PrevI->isTerminator()) {
1064 assert(PrevI->getOpcode() == WebAssembly::BR);
1065 PrevI->eraseFromParent();
1066 ErasedUncondBr =
true;
1070 assert(ErasedUncondBr &&
"Unconditional branch not erased!");
1086 for (
auto &
MBB : MF) {
1087 for (
auto &
MI :
MBB) {
1088 if (
MI.getOpcode() != WebAssembly::TRY)
1090 MachineInstr *Try = &
MI, *EndTry = BeginToEnd[Try];
1091 if (EndTry->getOpcode() == WebAssembly::DELEGATE)
1094 MachineBasicBlock *TryBB = Try->
getParent();
1095 MachineBasicBlock *Cont = EndTry->
getParent();
1097 for (
auto B = Try->
getIterator(),
E = std::next(EndTry->getIterator());
1099 std::prev(
B)->getOpcode() == WebAssembly::BLOCK &&
1100 E->getOpcode() == WebAssembly::END_BLOCK &&
1101 std::prev(
B)->getOperand(0).getImm() == RetType;
1108 for (
auto *
MI : ToDelete) {
1109 if (
MI->getOpcode() == WebAssembly::BLOCK)
1110 unregisterScope(
MI);
1111 MI->eraseFromParent();
1124 for (
auto &
MI : Split) {
1125 for (
auto &MO :
MI.explicit_uses()) {
1126 if (!MO.isReg() || MO.getReg().isPhysical())
1128 if (
MachineInstr *Def = MRI.getUniqueVRegDef(MO.getReg()))
1129 if (Def->getParent() == &
MBB)
1130 MFI.unstackifyVReg(MO.getReg());
1163 if (!MFI.isVRegStackified(TeeReg)) {
1165 MFI.unstackifyVReg(DefReg);
1171 MI.eraseFromParent();
1178void WebAssemblyCFGStackifyImpl::addNestedTryDelegate(
1179 MachineInstr *RangeBegin, MachineInstr *RangeEnd,
1180 MachineBasicBlock *UnwindDest) {
1181 auto *BeginBB = RangeBegin->
getParent();
1183 MachineFunction &MF = *BeginBB->
getParent();
1184 const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
1185 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
1189 SmallPtrSet<const MachineInstr *, 4> AfterSet;
1190 AfterSet.
insert(RangeBegin);
1193 if (std::prev(
I)->isDebugInstr() || std::prev(
I)->isPosition())
1195 if (WebAssembly::isChild(*std::prev(
I), MFI))
1196 AfterSet.
insert(&*std::prev(
I));
1203 BeginBB, SmallPtrSet<const MachineInstr *, 4>(), AfterSet);
1205 TII.get(WebAssembly::TRY))
1206 .
addImm(int64_t(WebAssembly::BlockType::Void));
1212 if (UnwindDest != FakeCallerBB)
1215 auto SplitPos = std::next(RangeEnd->
getIterator());
1216 if (SplitPos == EndBB->end()) {
1219 MF.
insert(std::next(EndBB->getIterator()), DelegateBB);
1220 EndBB->addSuccessor(DelegateBB);
1230 bool CatchAfterSplit =
false;
1231 if (EndBB->isEHPad()) {
1234 if (WebAssembly::isCatch(
I->getOpcode())) {
1235 CatchAfterSplit =
true;
1241 MachineBasicBlock *PreBB =
nullptr, *PostBB =
nullptr;
1242 if (!CatchAfterSplit) {
1261 PostBB->splice(PostBB->end(), PreBB, SplitPos, PreBB->
end());
1262 PostBB->transferSuccessors(PreBB);
1278 assert(EndBB->isEHPad());
1281 MF.
insert(PostBB->getIterator(), PreBB);
1282 MF.
insert(PostBB->getIterator(), DelegateBB);
1283 PreBB->
splice(PreBB->
end(), PostBB, PostBB->begin(), SplitPos);
1295 TII.get(WebAssembly::DELEGATE))
1297 registerTryScope(Try, Delegate,
nullptr);
1316WebAssemblyCFGStackifyImpl::getTrampolineBlock(MachineBasicBlock *UnwindDest) {
1320 auto It = UnwindDestToTrampoline.
find(UnwindDest);
1321 if (It != UnwindDestToTrampoline.
end())
1326 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
1328 MachineInstr *
Block =
nullptr;
1329 MachineBasicBlock *TrampolineBB =
nullptr;
1332 if (UnwindDest == getFakeCallerBlock(MF)) {
1336 auto BeginPos = MF.
begin()->begin();
1337 while (WebAssembly::isArgument(BeginPos->getOpcode()))
1340 TII.get(WebAssembly::BLOCK))
1341 .
addImm(int64_t(WebAssembly::BlockType::Exnref));
1342 TrampolineBB = getCallerTrampolineBlock(MF);
1343 MachineBasicBlock *PrevBB = &*std::prev(CallerTrampolineBB->
getIterator());
1349 auto *TargetBeginTry = EHPadToTry[UnwindDest];
1350 auto *TargetEndTry = BeginToEnd[TargetBeginTry];
1351 auto *TargetBeginBB = TargetBeginTry->getParent();
1352 auto *TargetEndBB = TargetEndTry->getParent();
1354 Block =
BuildMI(*TargetBeginBB, std::next(TargetBeginTry->getIterator()),
1355 TargetBeginTry->getDebugLoc(),
TII.get(WebAssembly::BLOCK))
1356 .
addImm(int64_t(WebAssembly::BlockType::Exnref));
1358 EndDebugLoc = TargetEndTry->getDebugLoc();
1359 MF.
insert(TargetEndBB->getIterator(), TrampolineBB);
1365 MachineInstr *EndBlock =
1366 BuildMI(TrampolineBB, EndDebugLoc,
TII.get(WebAssembly::END_BLOCK));
1367 auto ExnReg = MRI.createVirtualRegister(&WebAssembly::EXNREFRegClass);
1368 BuildMI(TrampolineBB, EndDebugLoc,
TII.get(WebAssembly::CATCH_ALL_REF))
1370 BuildMI(TrampolineBB, EndDebugLoc,
TII.get(WebAssembly::THROW_REF))
1376 MachineBasicBlock *TrampolineLayoutPred = TrampolineBB->
getPrevNode();
1378 TII.get(WebAssembly::UNREACHABLE));
1380 registerScope(
Block, EndBlock);
1381 UnwindDestToTrampoline[UnwindDest] = TrampolineBB;
1382 return TrampolineBB;
1387void WebAssemblyCFGStackifyImpl::addNestedTryTable(
1388 MachineInstr *RangeBegin, MachineInstr *RangeEnd,
1389 MachineBasicBlock *UnwindDest) {
1390 auto *BeginBB = RangeBegin->
getParent();
1393 MachineFunction &MF = *BeginBB->getParent();
1394 const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
1395 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
1398 auto *TrampolineBB = getTrampolineBlock(UnwindDest);
1402 SmallPtrSet<const MachineInstr *, 4> AfterSet;
1403 AfterSet.
insert(RangeBegin);
1406 if (std::prev(
I)->isDebugInstr() || std::prev(
I)->isPosition())
1408 if (WebAssembly::isChild(*std::prev(
I), MFI))
1409 AfterSet.
insert(&*std::prev(
I));
1416 BeginBB, SmallPtrSet<const MachineInstr *, 4>(), AfterSet);
1417 MachineInstr *TryTable =
1419 TII.get(WebAssembly::TRY_TABLE))
1420 .
addImm(int64_t(WebAssembly::BlockType::Void))
1429 auto SplitPos = std::next(RangeEnd->
getIterator());
1430 if (SplitPos == EndBB->end()) {
1433 MF.
insert(std::next(EndBB->getIterator()), EndTryTableBB);
1434 EndBB->addSuccessor(EndTryTableBB);
1444 bool CatchAfterSplit =
false;
1445 if (EndBB->isEHPad()) {
1448 if (WebAssembly::isCatch(
I->getOpcode())) {
1449 CatchAfterSplit =
true;
1455 MachineBasicBlock *PreBB =
nullptr, *PostBB =
nullptr;
1456 if (!CatchAfterSplit) {
1475 PostBB->splice(PostBB->end(), PreBB, SplitPos, PreBB->
end());
1476 PostBB->transferSuccessors(PreBB);
1492 assert(EndBB->isEHPad());
1495 MF.
insert(PostBB->getIterator(), PreBB);
1496 MF.
insert(PostBB->getIterator(), EndTryTableBB);
1497 PreBB->
splice(PreBB->
end(), PostBB, PostBB->begin(), SplitPos);
1509 TII.get(WebAssembly::END_TRY_TABLE));
1510 registerTryScope(TryTable, EndTryTable, TrampolineBB);
1562 MachineInstr *EndTryTable =
nullptr, *EndLoop =
nullptr;
1563 for (
auto &
MI :
reverse(*EndTryTableBB)) {
1564 if (
MI.getOpcode() == WebAssembly::END_TRY_TABLE) {
1568 if (EndTryTable &&
MI.getOpcode() == WebAssembly::END_LOOP) {
1578 auto SplitPos = std::next(EndLoop->getIterator());
1579 EndLoopBB->splice(EndLoopBB->end(), EndTryTableBB, EndTryTableBB->
begin(),
1581 EndLoopBB->addSuccessor(EndTryTableBB);
1587 std::string Name =
"bb.";
1589 if (
MBB->getBasicBlock()) {
1591 Name +=
MBB->getBasicBlock()->getName();
1596bool WebAssemblyCFGStackifyImpl::fixCallUnwindMismatches(MachineFunction &MF) {
1843 using TryRange = std::pair<MachineInstr *, MachineInstr *>;
1845 MapVector<MachineBasicBlock *, SmallVector<TryRange, 4>>
1846 UnwindDestToTryRanges;
1852 bool SeenThrowableInstInBB =
false;
1854 if (WebAssembly::isTry(
MI.getOpcode()))
1856 else if (
MI.getOpcode() == WebAssembly::DELEGATE)
1858 else if (WebAssembly::WasmUseLegacyEH &&
1859 WebAssembly::isCatch(
MI.getOpcode()))
1861 else if (
MI.getOpcode() == WebAssembly::END_TRY_TABLE)
1902 EHPadStack.
push_back(TryToEHPad[EndToBegin[&
MI]]);
1909 !WebAssembly::mayThrow(
MI))
1911 SeenThrowableInstInBB =
true;
1915 MachineBasicBlock *UnwindDest =
nullptr;
1921 if (Succ->isEHPad()) {
1926 if (EHPadStack.
back() == UnwindDest)
1930 MachineInstr *RangeBegin = &
MI, *RangeEnd = &
MI;
1932 std::prev(RangeBegin->
getIterator())->isEHLabel())
1933 RangeBegin = &*std::prev(RangeBegin->
getIterator());
1934 if (std::next(RangeEnd->getIterator()) !=
MBB.
end() &&
1935 std::next(RangeEnd->getIterator())->isEHLabel())
1936 RangeEnd = &*std::next(RangeEnd->getIterator());
1939 UnwindDestToTryRanges[UnwindDest].push_back(
1940 TryRange(RangeBegin, RangeEnd));
1942 <<
"\nCall = " <<
MI
1943 <<
"\nOriginal dest = " <<
getBBName(UnwindDest)
1956 MachineInstr *RangeBegin =
nullptr, *RangeEnd =
nullptr;
1959 auto RecordCallerMismatchRange = [&](
const MachineBasicBlock *CurrentDest) {
1960 UnwindDestToTryRanges[getFakeCallerBlock(MF)].push_back(
1961 TryRange(RangeBegin, RangeEnd));
1964 <<
"\nRange begin = " << *RangeBegin
1965 <<
"Range end = " << *RangeEnd
1966 <<
"\nOriginal dest = caller Current dest = "
1968 RangeBegin = RangeEnd =
nullptr;
1972 bool SeenThrowableInstInBB =
false;
1974 bool MayThrow = WebAssembly::mayThrow(
MI);
1980 SeenThrowableInstInBB =
true;
1984 else if (RangeEnd && WebAssembly::isMarker(
MI.getOpcode()))
1985 RecordCallerMismatchRange(EHPadStack.
back());
1990 else if (EHPadStack.
empty() || EHPadStack.
back() == FakeCallerBB ||
1999 RangeBegin = RangeEnd = &
MI;
2005 if (WebAssembly::isTry(
MI.getOpcode()))
2007 else if (
MI.getOpcode() == WebAssembly::DELEGATE)
2009 else if (WebAssembly::WasmUseLegacyEH &&
2010 WebAssembly::isCatch(
MI.getOpcode()))
2012 else if (!WebAssembly::WasmUseLegacyEH &&
2013 MI.getOpcode() == WebAssembly::END_TRY_TABLE)
2014 EHPadStack.
push_back(TryToEHPad[EndToBegin[&
MI]]);
2018 RecordCallerMismatchRange(EHPadStack.
back());
2024 if (UnwindDestToTryRanges.
empty())
2029 if (!WebAssembly::WasmUseLegacyEH)
2030 for (
auto &[UnwindDest,
_] : UnwindDestToTryRanges) {
2031 auto It = EHPadToTry.
find(UnwindDest);
2034 if (It != EHPadToTry.
end()) {
2035 auto *TryTable = It->second;
2036 auto *EndTryTable = BeginToEnd[TryTable];
2042 for (
auto &
P : UnwindDestToTryRanges) {
2043 NumCallUnwindMismatches +=
P.second.size();
2044 MachineBasicBlock *UnwindDest =
P.first;
2045 auto &TryRanges =
P.second;
2047 for (
auto Range : TryRanges) {
2048 MachineInstr *RangeBegin =
nullptr, *RangeEnd =
nullptr;
2049 std::tie(RangeBegin, RangeEnd) =
Range;
2058 if (UnwindDest != getFakeCallerBlock(MF)) {
2059 MachineBasicBlock *EHPad =
nullptr;
2061 if (Succ->isEHPad()) {
2070 if (WebAssembly::WasmUseLegacyEH)
2071 addNestedTryDelegate(RangeBegin, RangeEnd, UnwindDest);
2073 addNestedTryTable(RangeBegin, RangeEnd, UnwindDest);
2080bool WebAssemblyCFGStackifyImpl::fixCatchUnwindMismatches(MachineFunction &MF) {
2185 auto HasUnwindDest = [&](
const MachineBasicBlock *EHPad) {
2188 for (
auto I = InvokeBB->succ_begin(),
E = InvokeBB->succ_end();
I !=
E; ++
I)
2190 return std::next(
I) !=
E;
2196 auto GetUnwindDest = [&](
const MachineBasicBlock *EHPad) {
2199 for (
auto I = InvokeBB->succ_begin(),
E = InvokeBB->succ_end();
I !=
E;
2202 auto *
Next = std::next(
I);
2212 MapVector<MachineBasicBlock *, MachineBasicBlock *> EHPadToUnwindDest;
2216 if (WebAssembly::isTry(
MI.getOpcode())) {
2218 }
else if (
MI.getOpcode() == WebAssembly::DELEGATE) {
2220 }
else if (WebAssembly::isCatch(
MI.getOpcode())) {
2225 if (WebAssembly::isCatchAll(
MI.getOpcode())) {
2230 else if (EHPadStack.
empty() && HasUnwindDest(EHPad)) {
2232 <<
"'s unwind destination does not exist anymore"
2238 else if (!EHPadStack.
empty() && EHPadStack.
back() != FakeCallerBB &&
2239 !HasUnwindDest(EHPad)) {
2240 EHPadToUnwindDest[EHPad] = getFakeCallerBlock(MF);
2242 <<
"- Catch unwind mismatch:\nEHPad = " <<
getBBName(EHPad)
2243 <<
" Original dest = caller Current dest = "
2249 else if (!EHPadStack.
empty() && HasUnwindDest(EHPad)) {
2250 auto *UnwindDest = GetUnwindDest(EHPad);
2251 if (EHPadStack.
back() != UnwindDest) {
2252 EHPadToUnwindDest[EHPad] = UnwindDest;
2254 <<
getBBName(EHPad) <<
" Original dest = "
2255 <<
getBBName(UnwindDest) <<
" Current dest = "
2266 if (EHPadToUnwindDest.
empty())
2271 for (
auto &[
_, UnwindDest] : EHPadToUnwindDest) {
2272 auto It = EHPadToTry.
find(UnwindDest);
2274 if (It != EHPadToTry.
end()) {
2275 auto *TryTable = It->second;
2276 auto *EndTryTable = BeginToEnd[TryTable];
2281 NumCatchUnwindMismatches += EHPadToUnwindDest.size();
2282 SmallPtrSet<MachineBasicBlock *, 4> NewEndTryBBs;
2284 for (
auto &[EHPad, UnwindDest] : EHPadToUnwindDest) {
2285 MachineInstr *Try = EHPadToTry[EHPad];
2286 MachineInstr *EndTry = BeginToEnd[Try];
2287 if (WebAssembly::WasmUseLegacyEH) {
2288 addNestedTryDelegate(Try, EndTry, UnwindDest);
2291 addNestedTryTable(Try, EndTry, UnwindDest);
2295 if (!WebAssembly::WasmUseLegacyEH)
2342 for (
auto &
MBB : MF) {
2343 for (
auto &
MI :
MBB) {
2344 if (
MI.isTerminator()) {
2345 for (
auto &MO :
MI.operands()) {
2346 if (MO.isMBB() && NewEndTryBBs.
count(MO.getMBB())) {
2347 auto *BrDest = MO.getMBB();
2348 bool FoundEndBlock =
false;
2349 for (; std::next(BrDest->getIterator()) != MF.end();
2350 BrDest = BrDest->getNextNode()) {
2351 for (
const auto &
MI : *BrDest) {
2352 if (
MI.getOpcode() == WebAssembly::END_BLOCK) {
2353 FoundEndBlock =
true;
2371void WebAssemblyCFGStackifyImpl::recalculateScopeTops(MachineFunction &MF) {
2381 switch (
MI.getOpcode()) {
2382 case WebAssembly::END_BLOCK:
2383 case WebAssembly::END_LOOP:
2384 case WebAssembly::END_TRY:
2385 case WebAssembly::END_TRY_TABLE:
2386 case WebAssembly::DELEGATE:
2389 case WebAssembly::CATCH_LEGACY:
2390 case WebAssembly::CATCH_ALL_LEGACY:
2405void WebAssemblyCFGStackifyImpl::fixEndsAtEndOfFunction(MachineFunction &MF) {
2406 const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
2408 if (MFI.getResults().empty())
2413 WebAssembly::BlockType RetType =
2414 MFI.getResults().size() > 1
2415 ? WebAssembly::BlockType::Multivalue
2416 : WebAssembly::BlockType(
2417 WebAssembly::toValType(MFI.getResults().front()));
2425 MachineInstr &
MI = *It++;
2426 if (
MI.isPosition() ||
MI.isDebugInstr())
2428 switch (
MI.getOpcode()) {
2429 case WebAssembly::END_TRY: {
2433 auto *EHPad = TryToEHPad.
lookup(EndToBegin[&
MI]);
2436 std::next(WebAssembly::findCatch(EHPad)->getReverseIterator());
2437 if (NextIt != EHPad->
rend())
2441 case WebAssembly::END_BLOCK:
2442 case WebAssembly::END_LOOP:
2443 case WebAssembly::END_TRY_TABLE:
2444 case WebAssembly::DELEGATE:
2445 EndToBegin[&
MI]->getOperand(0).setImm(int32_t(RetType));
2457 while (!Worklist.
empty())
2467 TII.get(WebAssembly::END_FUNCTION));
2493 std::vector<MachineInstr *> EndTryTables;
2494 for (
auto &
MBB : MF)
2495 for (
auto &
MI :
MBB)
2496 if (
MI.getOpcode() == WebAssembly::END_TRY_TABLE)
2497 EndTryTables.push_back(&
MI);
2499 for (
auto *EndTryTable : EndTryTables) {
2502 MF.
insert(
MBB->getIterator(), NewEndTryTableBB);
2503 auto SplitPos = std::next(EndTryTable->
getIterator());
2504 NewEndTryTableBB->splice(NewEndTryTableBB->end(),
MBB,
MBB->begin(),
2506 NewEndTryTableBB->addSuccessor(
MBB);
2508 TII.get(WebAssembly::UNREACHABLE));
2513void WebAssemblyCFGStackifyImpl::placeMarkers(MachineFunction &MF) {
2518 for (
auto &
MBB : MF)
2519 placeLoopMarker(
MBB);
2521 const MCAsmInfo &MCAI = MF.getTarget().getMCAsmInfo();
2522 for (
auto &
MBB : MF) {
2526 MF.getFunction().hasPersonalityFn()) {
2527 if (WebAssembly::WasmUseLegacyEH)
2528 placeTryMarker(
MBB);
2530 placeTryTableMarker(
MBB);
2534 placeBlockMarker(
MBB);
2539 MF.getFunction().hasPersonalityFn()) {
2540 const auto &
TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
2547 fixCatchUnwindMismatches(MF);
2548 fixCallUnwindMismatches(MF);
2551 recalculateScopeTops(MF);
2555unsigned WebAssemblyCFGStackifyImpl::getBranchDepth(
2556 const SmallVectorImpl<EndMarkerInfo> &Stack,
const MachineBasicBlock *
MBB) {
2567unsigned WebAssemblyCFGStackifyImpl::getDelegateDepth(
2568 const SmallVectorImpl<EndMarkerInfo> &Stack,
const MachineBasicBlock *
MBB) {
2569 if (
MBB == FakeCallerBB)
2570 return Stack.size();
2576 return getBranchDepth(Stack,
MBB);
2592 const MachineInstr *EndTry = BeginToEnd[EHPadToTry[
MBB]];
2594 if (
X.first == EndTry->
getParent() &&
X.second == EndTry)
2602unsigned WebAssemblyCFGStackifyImpl::getRethrowDepth(
2603 const SmallVectorImpl<EndMarkerInfo> &Stack,
2604 const MachineBasicBlock *EHPadToRethrow) {
2607 const MachineInstr *End =
X.second;
2608 if (End->
getOpcode() == WebAssembly::END_TRY) {
2609 auto *EHPad = TryToEHPad[EndToBegin[End]];
2610 if (EHPadToRethrow == EHPad)
2619void WebAssemblyCFGStackifyImpl::rewriteDepthImmediates(MachineFunction &MF) {
2623 auto RewriteOperands = [&](MachineInstr &
MI) {
2626 while (
MI.getNumOperands() > 0)
2627 MI.removeOperand(
MI.getNumOperands() - 1);
2628 for (
auto MO :
Ops) {
2630 if (
MI.getOpcode() == WebAssembly::DELEGATE)
2632 else if (
MI.getOpcode() == WebAssembly::RETHROW)
2637 MI.addOperand(MF, MO);
2643 switch (
MI.getOpcode()) {
2644 case WebAssembly::BLOCK:
2645 case WebAssembly::TRY:
2646 assert(ScopeTops[
Stack.back().first->getNumber()]->getNumber() <=
2648 "Block/try/try_table marker should be balanced");
2652 case WebAssembly::TRY_TABLE:
2653 assert(ScopeTops[
Stack.back().first->getNumber()]->getNumber() <=
2655 "Block/try/try_table marker should be balanced");
2657 RewriteOperands(
MI);
2660 case WebAssembly::LOOP:
2661 assert(
Stack.back().first == &
MBB &&
"Loop top should be balanced");
2665 case WebAssembly::END_BLOCK:
2666 case WebAssembly::END_TRY:
2667 case WebAssembly::END_TRY_TABLE:
2671 case WebAssembly::END_LOOP:
2675 case WebAssembly::DELEGATE:
2676 RewriteOperands(
MI);
2681 if (
MI.isTerminator())
2682 RewriteOperands(
MI);
2687 assert(
Stack.empty() &&
"Control flow should be balanced");
2690void WebAssemblyCFGStackifyImpl::cleanupFunctionData(MachineFunction &MF) {
2693 AppendixBB = FakeCallerBB = CallerTrampolineBB =
nullptr;
2696bool WebAssemblyCFGStackifyImpl::runOnMachineFunction(MachineFunction &MF) {
2698 "********** Function: "
2712 removeUnnecessaryInstrs(MF);
2715 rewriteDepthImmediates(MF);
2719 fixEndsAtEndOfFunction(MF);
2722 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
2725 cleanupFunctionData(MF);
2727 MF.
getInfo<WebAssemblyFunctionInfo>()->setCFGStackified();
2731bool WebAssemblyCFGStackifyLegacy::runOnMachineFunction(MachineFunction &MF) {
2732 MachineDominatorTree &MDT =
2733 getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
2734 MachineLoopInfo &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
2735 WebAssemblyExceptionInfo &WEI =
2736 getAnalysis<WebAssemblyExceptionInfoWrapperPass>().getWEI();
2737 WebAssemblyCFGStackifyImpl Impl(MDT, MLI, WEI);
2738 return Impl.runOnMachineFunction(MF);
2748 WebAssemblyCFGStackifyImpl Impl(MDT, MLI, WEI);
2749 return Impl.runOnMachineFunction(MF)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const Function * getParent(const Value *V)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file implements a map that provides insertion order iteration.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static std::string getBBName(const MachineBasicBlock *MBB)
static bool explicitlyBranchesTo(MachineBasicBlock *Pred, MachineBasicBlock *MBB)
Test whether Pred has any terminators explicitly branching to MBB, as opposed to falling through.
static void addUnreachableAfterTryTables(MachineFunction &MF, const WebAssemblyInstrInfo &TII)
static MachineBasicBlock::iterator getLatestInsertPos(MachineBasicBlock *MBB, const Container &BeforeSet, const Container &AfterSet)
static void splitEndLoopBB(MachineBasicBlock *EndTryTableBB)
static void appendEndToFunction(MachineFunction &MF, const WebAssemblyInstrInfo &TII)
static void unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB, MachineBasicBlock &Split)
static MachineBasicBlock::iterator getEarliestInsertPos(MachineBasicBlock *MBB, const Container &BeforeSet, const Container &AfterSet)
This file implements WebAssemblyException information analysis.
This file declares WebAssembly-specific per-machine-function information.
This file implements regions used in CFGSort and CFGStackify.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
This file declares the WebAssembly-specific subclass of TargetMachine.
This file contains the declaration of the WebAssembly-specific type parsing utility functions.
This file contains the declaration of the WebAssembly-specific utility functions.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
Find nearest common dominator basic block for basic block A and B.
FunctionPass class - This class is used to implement most global optimizations.
bool hasPersonalityFn() const
Check whether this function has a personality function.
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
BlockT * getHeader() const
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
ExceptionHandling getExceptionHandlingType() const
LLVM_ABI bool hasEHPadSuccessor() const
bool isEHPad() const
Returns true if the block is a landing pad.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
LLVM_ABI bool isPredecessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a predecessor of this block.
LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
pred_iterator pred_begin()
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
LLVM_ABI DebugLoc findPrevDebugLoc(instr_iterator MBBI)
Find the previous valid DebugLoc preceding MBBI, skipping any debug instructions.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI DebugLoc findBranchDebugLoc()
Find and return the merged DebugLoc of the branch instructions of the block.
iterator_range< succ_iterator > successors()
reverse_iterator rbegin()
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
void push_back(MachineBasicBlock *MBB)
reverse_iterator rbegin()
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
void deleteMachineBasicBlock(MachineBasicBlock *MBB)
DeleteMachineBasicBlock - Delete the given MachineBasicBlock.
Function & getFunction()
Return the LLVM function that this machine code represents.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
const MachineBasicBlock & back() const
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
void RenumberBlocks(MachineBasicBlock *MBBFrom=nullptr)
RenumberBlocks - This discards all of the MachineBasicBlock numbers and recomputes them.
const MachineBasicBlock & front() const
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
Analysis pass that exposes the MachineLoopInfo for a machine function.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateImm(int64_t Val)
void setTargetFlags(unsigned F)
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
WebAssemblyException * getExceptionFor(const MachineBasicBlock *MBB) const
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
self_iterator getIterator()
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getCopyOpcodeForRegClass(const TargetRegisterClass *RC)
Returns the appropriate copy opcode for the given register class.
NodeAddr< UseNode * > Use
@ WASM_OPCODE_CATCH_ALL_REF
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
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...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FunctionPass * createWebAssemblyCFGStackifyLegacyPass()
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next