42#define DEBUG_TYPE "wasm-cfg-stackify"
44STATISTIC(NumCallUnwindMismatches,
"Number of call unwind mismatches found");
45STATISTIC(NumCatchUnwindMismatches,
"Number of catch unwind mismatches found");
51 StringRef getPassName()
const override {
return "WebAssembly CFG Stackify"; }
53 void getAnalysisUsage(AnalysisUsage &AU)
const override {
60 bool runOnMachineFunction(MachineFunction &MF)
override;
66 void updateScopeTops(MachineBasicBlock *Begin, MachineBasicBlock *End) {
69 if (!ScopeTops[EndNo] || ScopeTops[EndNo]->getNumber() > BeginNo)
70 ScopeTops[EndNo] = Begin;
74 void placeMarkers(MachineFunction &MF);
75 void placeBlockMarker(MachineBasicBlock &
MBB);
76 void placeLoopMarker(MachineBasicBlock &
MBB);
77 void placeTryMarker(MachineBasicBlock &
MBB);
78 void placeTryTableMarker(MachineBasicBlock &
MBB);
82 bool fixCallUnwindMismatches(MachineFunction &MF);
83 bool fixCatchUnwindMismatches(MachineFunction &MF);
84 void recalculateScopeTops(MachineFunction &MF);
86 void addNestedTryDelegate(MachineInstr *RangeBegin, MachineInstr *RangeEnd,
87 MachineBasicBlock *UnwindDest);
88 void removeUnnecessaryInstrs(MachineFunction &MF);
90 void addNestedTryTable(MachineInstr *RangeBegin, MachineInstr *RangeEnd,
91 MachineBasicBlock *UnwindDest);
92 MachineBasicBlock *getTrampolineBlock(MachineBasicBlock *UnwindDest);
96 std::pair<const MachineBasicBlock *, const MachineInstr *>;
97 unsigned getBranchDepth(
const SmallVectorImpl<EndMarkerInfo> &Stack,
98 const MachineBasicBlock *
MBB);
99 unsigned getDelegateDepth(
const SmallVectorImpl<EndMarkerInfo> &Stack,
100 const MachineBasicBlock *
MBB);
101 unsigned getRethrowDepth(
const SmallVectorImpl<EndMarkerInfo> &Stack,
102 const MachineBasicBlock *EHPadToRethrow);
103 void rewriteDepthImmediates(MachineFunction &MF);
104 void fixEndsAtEndOfFunction(MachineFunction &MF);
105 void cleanupFunctionData(MachineFunction &MF);
109 DenseMap<const MachineInstr *, MachineInstr *> BeginToEnd;
112 DenseMap<const MachineInstr *, MachineInstr *> EndToBegin;
114 DenseMap<const MachineInstr *, MachineBasicBlock *> TryToEHPad;
116 DenseMap<const MachineBasicBlock *, MachineInstr *> EHPadToTry;
118 DenseMap<const MachineBasicBlock *, MachineBasicBlock *>
119 UnwindDestToTrampoline;
123 MachineBasicBlock *AppendixBB =
nullptr;
124 MachineBasicBlock *getAppendixBlock(MachineFunction &MF) {
131 if (CallerTrampolineBB)
132 MF.
insert(CallerTrampolineBB->getIterator(), AppendixBB);
141 MachineBasicBlock *CallerTrampolineBB =
nullptr;
142 MachineBasicBlock *getCallerTrampolineBlock(MachineFunction &MF) {
143 if (!CallerTrampolineBB) {
147 return CallerTrampolineBB;
156 MachineBasicBlock *FakeCallerBB =
nullptr;
157 MachineBasicBlock *getFakeCallerBlock(MachineFunction &MF) {
165 void registerScope(MachineInstr *Begin, MachineInstr *End);
166 void registerTryScope(MachineInstr *Begin, MachineInstr *End,
167 MachineBasicBlock *EHPad);
168 void unregisterScope(MachineInstr *Begin);
172 WebAssemblyCFGStackify() : MachineFunctionPass(ID) {}
173 ~WebAssemblyCFGStackify()
override { releaseMemory(); }
174 void releaseMemory()
override;
178char WebAssemblyCFGStackify::ID = 0;
181 "Insert BLOCK/LOOP/TRY/TRY_TABLE markers for WebAssembly scopes",
false,
185 return new WebAssemblyCFGStackify();
197 if (MO.isMBB() && MO.getMBB() ==
MBB)
207template <
typename Container>
210 const Container &AfterSet) {
211 auto InsertPos =
MBB->end();
212 while (InsertPos !=
MBB->begin()) {
213 if (BeforeSet.count(&*std::prev(InsertPos))) {
216 for (
auto Pos = InsertPos,
E =
MBB->begin(); Pos !=
E; --Pos)
217 assert(!AfterSet.count(&*std::prev(Pos)));
231template <
typename Container>
234 const Container &AfterSet) {
235 auto InsertPos =
MBB->begin();
236 while (InsertPos !=
MBB->end()) {
237 if (AfterSet.count(&*InsertPos)) {
240 for (
auto Pos = InsertPos,
E =
MBB->end(); Pos !=
E; ++Pos)
241 assert(!BeforeSet.count(&*Pos));
250void WebAssemblyCFGStackify::registerScope(
MachineInstr *Begin,
252 BeginToEnd[Begin] = End;
253 EndToBegin[End] = Begin;
257void WebAssemblyCFGStackify::registerTryScope(MachineInstr *Begin,
259 MachineBasicBlock *EHPad) {
260 registerScope(Begin, End);
261 TryToEHPad[Begin] = EHPad;
262 EHPadToTry[EHPad] = Begin;
265void WebAssemblyCFGStackify::unregisterScope(MachineInstr *Begin) {
267 MachineInstr *End = BeginToEnd[Begin];
269 BeginToEnd.
erase(Begin);
270 EndToBegin.
erase(End);
271 MachineBasicBlock *EHPad = TryToEHPad.
lookup(Begin);
274 TryToEHPad.
erase(Begin);
275 EHPadToTry.
erase(EHPad);
282void WebAssemblyCFGStackify::placeBlockMarker(MachineBasicBlock &
MBB) {
285 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
286 const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
291 MachineBasicBlock *Header =
nullptr;
292 bool IsBranchedTo =
false;
295 if (Pred->getNumber() < MBBNumber) {
296 Header = Header ? MDT->findNearestCommonDominator(Header, Pred) : Pred;
306 assert(&
MBB != &MF.
front() &&
"Header blocks shouldn't have predecessors");
312 if (MachineBasicBlock *ScopeTop = ScopeTops[
I->getNumber()]) {
313 if (ScopeTop->getNumber() > Header->getNumber()) {
315 I = std::next(ScopeTop->getIterator());
327 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
329 SmallPtrSet<const MachineInstr *, 4> AfterSet;
330 for (
const auto &
MI : *Header) {
334 if (
MI.getOpcode() == WebAssembly::LOOP) {
335 auto *LoopBottom = BeginToEnd[&
MI]->getParent()->getPrevNode();
348 if (
MI.getOpcode() == WebAssembly::BLOCK ||
349 MI.getOpcode() == WebAssembly::TRY ||
350 MI.getOpcode() == WebAssembly::TRY_TABLE) {
361 if (
MI.getOpcode() == WebAssembly::END_BLOCK ||
362 MI.getOpcode() == WebAssembly::END_LOOP ||
363 MI.getOpcode() == WebAssembly::END_TRY ||
364 MI.getOpcode() == WebAssembly::END_TRY_TABLE)
369 if (
MI.isTerminator())
374 for (
auto I = Header->getFirstTerminator(),
E = Header->begin();
I !=
E;
376 if (std::prev(
I)->isDebugInstr() || std::prev(
I)->isPosition())
379 AfterSet.
insert(&*std::prev(
I));
387 MachineInstr *Begin =
388 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
389 TII.get(WebAssembly::BLOCK))
390 .
addImm(int64_t(ReturnType));
395 for (
auto &
MI :
MBB) {
398 if (
MI.getOpcode() == WebAssembly::LOOP)
411 if (
MI.getOpcode() == WebAssembly::END_LOOP ||
412 MI.getOpcode() == WebAssembly::END_TRY) {
413 if (EndToBegin[&
MI]->
getParent()->getNumber() >= Header->getNumber())
425 TII.get(WebAssembly::END_BLOCK));
426 registerScope(Begin, End);
429 updateScopeTops(Header, &
MBB);
433void WebAssemblyCFGStackify::placeLoopMarker(MachineBasicBlock &
MBB) {
435 const auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
436 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
437 SortRegionInfo SRI(MLI, WEI);
438 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
440 MachineLoop *Loop = MLI.getLoopFor(&
MBB);
446 MachineBasicBlock *Bottom = SRI.getBottom(Loop);
448 if (Iter == MF.
end()) {
449 getAppendixBlock(MF);
452 MachineBasicBlock *AfterLoop = &*Iter;
455 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
456 SmallPtrSet<const MachineInstr *, 4> AfterSet;
457 for (
const auto &
MI :
MBB) {
460 if (
MI.getOpcode() == WebAssembly::END_LOOP)
471 TII.get(WebAssembly::LOOP))
472 .
addImm(int64_t(WebAssembly::BlockType::Void));
478 for (
const auto &
MI :
MBB)
480 if (
MI.getOpcode() == WebAssembly::END_LOOP)
489 : (*AfterLoop->pred_rbegin())->findBranchDebugLoc();
491 BuildMI(*AfterLoop, InsertPos, EndDL,
TII.get(WebAssembly::END_LOOP));
492 registerScope(Begin, End);
496 "With block sorting the outermost loop for a block should be first.");
497 updateScopeTops(&
MBB, AfterLoop);
500void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock &
MBB) {
503 auto &MDT = getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
504 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
505 const auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
506 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
507 SortRegionInfo SRI(MLI, WEI);
508 const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
511 MachineBasicBlock *Header =
nullptr;
514 if (Pred->getNumber() < MBBNumber) {
515 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
517 "Explicit branch to an EH pad!");
525 WebAssemblyException *WE = WEI.getExceptionFor(&
MBB);
527 MachineBasicBlock *Bottom = SRI.getBottom(WE);
529 if (Iter == MF.
end()) {
530 getAppendixBlock(MF);
533 MachineBasicBlock *Cont = &*Iter;
538 if (MachineBasicBlock *ScopeTop = ScopeTops[
I->getNumber()]) {
539 if (ScopeTop->getNumber() > Header->getNumber()) {
541 I = std::next(ScopeTop->getIterator());
553 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
555 SmallPtrSet<const MachineInstr *, 4> AfterSet;
556 for (
const auto &
MI : *Header) {
560 if (
MI.getOpcode() == WebAssembly::LOOP) {
561 auto *LoopBottom = BeginToEnd[&
MI]->getParent()->getPrevNode();
572 if (
MI.getOpcode() == WebAssembly::BLOCK ||
573 MI.getOpcode() == WebAssembly::TRY)
578 if (
MI.getOpcode() == WebAssembly::END_BLOCK ||
579 MI.getOpcode() == WebAssembly::END_LOOP ||
580 MI.getOpcode() == WebAssembly::END_TRY)
585 if (
MI.isTerminator())
594 MachineInstr *ThrowingCall =
nullptr;
596 auto TermPos = Header->getFirstTerminator();
597 if (TermPos == Header->end() ||
598 TermPos->getOpcode() != WebAssembly::RETHROW) {
605 if (
MI.getIterator() != Header->begin() &&
606 std::prev(
MI.getIterator())->isEHLabel()) {
607 AfterSet.
insert(&*std::prev(
MI.getIterator()));
608 ThrowingCall = &*std::prev(
MI.getIterator());
623 : Header->getFirstTerminator();
624 for (
auto I = SearchStartPt,
E = Header->begin();
I !=
E; --
I) {
625 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
627 if (WebAssembly::isChild(*std::prev(I), MFI))
628 AfterSet.insert(&*std::prev(I));
635 MachineInstr *Begin =
636 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
637 TII.get(WebAssembly::TRY))
638 .
addImm(int64_t(WebAssembly::BlockType::Void));
643 for (
const auto &
MI : *Cont) {
646 if (
MI.getOpcode() == WebAssembly::LOOP)
651 if (
MI.getOpcode() == WebAssembly::END_TRY)
659 if (
MI.getOpcode() == WebAssembly::END_LOOP) {
662 if (EndToBegin[&
MI]->
getParent()->getNumber() > Header->getNumber())
676 TII.get(WebAssembly::END_TRY));
677 registerTryScope(Begin, End, &
MBB);
690 for (
auto *End : {&
MBB, Cont})
691 updateScopeTops(Header, End);
694void WebAssemblyCFGStackify::placeTryTableMarker(MachineBasicBlock &
MBB) {
697 auto &MDT = getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
698 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
699 const auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
700 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
701 SortRegionInfo SRI(MLI, WEI);
702 const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
705 MachineBasicBlock *Header =
nullptr;
708 if (Pred->getNumber() < MBBNumber) {
709 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
711 "Explicit branch to an EH pad!");
720 WebAssemblyException *WE = WEI.getExceptionFor(&
MBB);
722 MachineBasicBlock *Bottom = SRI.getBottom(WE);
724 if (Iter == MF.
end())
726 MachineBasicBlock *Cont = &*Iter;
731 if (MachineBasicBlock *ScopeTop = ScopeTops[
I->getNumber()]) {
732 if (ScopeTop->getNumber() > Header->getNumber()) {
734 I = std::next(ScopeTop->getIterator());
746 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
748 SmallPtrSet<const MachineInstr *, 4> AfterSet;
749 for (
const auto &
MI : *Header) {
753 if (
MI.getOpcode() == WebAssembly::LOOP) {
754 auto *LoopBottom = BeginToEnd[&
MI]->getParent()->getPrevNode();
765 if (
MI.getOpcode() == WebAssembly::BLOCK ||
766 MI.getOpcode() == WebAssembly::TRY_TABLE)
771 if (
MI.getOpcode() == WebAssembly::END_BLOCK ||
772 MI.getOpcode() == WebAssembly::END_LOOP ||
773 MI.getOpcode() == WebAssembly::END_TRY_TABLE)
778 if (
MI.isTerminator())
787 MachineInstr *ThrowingCall =
nullptr;
789 auto TermPos = Header->getFirstTerminator();
790 if (TermPos == Header->end() ||
791 TermPos->getOpcode() != WebAssembly::RETHROW) {
798 if (
MI.getIterator() != Header->begin() &&
799 std::prev(
MI.getIterator())->isEHLabel()) {
800 AfterSet.
insert(&*std::prev(
MI.getIterator()));
801 ThrowingCall = &*std::prev(
MI.getIterator());
816 : Header->getFirstTerminator();
817 for (
auto I = SearchStartPt,
E = Header->begin();
I !=
E; --
I) {
818 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
820 if (WebAssembly::isChild(*std::prev(I), MFI))
821 AfterSet.insert(&*std::prev(I));
840 MachineInstrBuilder BlockMIB =
841 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
842 TII.get(WebAssembly::BLOCK));
844 MachineInstrBuilder TryTableMIB =
845 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
846 TII.get(WebAssembly::TRY_TABLE))
847 .
addImm(int64_t(WebAssembly::BlockType::Void))
849 auto *TryTable = TryTableMIB.
getInstr();
855 *MF.
getSubtarget<WebAssemblySubtarget>().getTargetLowering();
858 ? WebAssembly::BlockType::I32
859 : WebAssembly::BlockType::I64;
861 switch (
Catch->getOpcode()) {
862 case WebAssembly::CATCH:
866 BlockMIB.
addImm(int64_t(PtrTy));
868 for (
const auto &Use :
Catch->uses()) {
875 case WebAssembly::CATCH_REF:
880 BlockMIB.
addImm(int64_t(WebAssembly::BlockType::Multivalue));
883 for (
const auto &Use :
Catch->uses()) {
889 case WebAssembly::CATCH_ALL:
891 BlockMIB.
addImm(int64_t(WebAssembly::BlockType::Void));
895 case WebAssembly::CATCH_ALL_REF:
897 BlockMIB.
addImm(int64_t(WebAssembly::BlockType::Exnref));
907 for (
const auto &
MI :
MBB) {
910 if (
MI.getOpcode() == WebAssembly::LOOP)
918 if (
MI.getOpcode() == WebAssembly::END_LOOP) {
919 if (EndToBegin[&
MI]->
getParent()->getNumber() >= Header->getNumber())
938 MachineInstr *EndTryTable =
940 TII.get(WebAssembly::END_TRY_TABLE));
941 registerTryScope(TryTable, EndTryTable, &
MBB);
942 MachineInstr *EndBlock =
944 TII.get(WebAssembly::END_BLOCK));
945 registerScope(
Block, EndBlock);
987 for (
auto *End : {&
MBB, Cont})
988 updateScopeTops(Header, End);
991void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) {
992 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
1027 for (
auto &
MBB : MF) {
1031 MachineBasicBlock *
TBB =
nullptr, *FBB =
nullptr;
1035 MachineBasicBlock *Cont = &
MBB;
1037 MachineInstr *Try = EHPadToTry[Cont];
1038 MachineInstr *EndTry = BeginToEnd[Try];
1051 if (Analyzable && ((
Cond.empty() &&
TBB &&
TBB == Cont) ||
1052 (!
Cond.empty() && FBB && FBB == Cont))) {
1053 bool ErasedUncondBr =
false;
1054 (void)ErasedUncondBr;
1055 for (
auto I = EHPadLayoutPred->
end(),
E = EHPadLayoutPred->
begin();
1057 auto PrevI = std::prev(
I);
1058 if (PrevI->isTerminator()) {
1059 assert(PrevI->getOpcode() == WebAssembly::BR);
1060 PrevI->eraseFromParent();
1061 ErasedUncondBr =
true;
1065 assert(ErasedUncondBr &&
"Unconditional branch not erased!");
1081 for (
auto &
MBB : MF) {
1082 for (
auto &
MI :
MBB) {
1083 if (
MI.getOpcode() != WebAssembly::TRY)
1085 MachineInstr *Try = &
MI, *EndTry = BeginToEnd[Try];
1086 if (EndTry->getOpcode() == WebAssembly::DELEGATE)
1089 MachineBasicBlock *TryBB = Try->
getParent();
1090 MachineBasicBlock *Cont = EndTry->
getParent();
1092 for (
auto B = Try->
getIterator(),
E = std::next(EndTry->getIterator());
1094 std::prev(
B)->getOpcode() == WebAssembly::BLOCK &&
1095 E->getOpcode() == WebAssembly::END_BLOCK &&
1096 std::prev(
B)->getOperand(0).getImm() == RetType;
1103 for (
auto *
MI : ToDelete) {
1104 if (
MI->getOpcode() == WebAssembly::BLOCK)
1105 unregisterScope(
MI);
1106 MI->eraseFromParent();
1119 for (
auto &
MI : Split) {
1120 for (
auto &MO :
MI.explicit_uses()) {
1121 if (!MO.isReg() || MO.getReg().isPhysical())
1123 if (
MachineInstr *Def = MRI.getUniqueVRegDef(MO.getReg()))
1124 if (Def->getParent() == &
MBB)
1125 MFI.unstackifyVReg(MO.getReg());
1158 if (!MFI.isVRegStackified(TeeReg)) {
1160 MFI.unstackifyVReg(DefReg);
1166 MI.eraseFromParent();
1173void WebAssemblyCFGStackify::addNestedTryDelegate(
1174 MachineInstr *RangeBegin, MachineInstr *RangeEnd,
1175 MachineBasicBlock *UnwindDest) {
1176 auto *BeginBB = RangeBegin->
getParent();
1178 MachineFunction &MF = *BeginBB->
getParent();
1179 const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
1180 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
1184 SmallPtrSet<const MachineInstr *, 4> AfterSet;
1185 AfterSet.
insert(RangeBegin);
1188 if (std::prev(
I)->isDebugInstr() || std::prev(
I)->isPosition())
1191 AfterSet.
insert(&*std::prev(
I));
1198 BeginBB, SmallPtrSet<const MachineInstr *, 4>(), AfterSet);
1200 TII.get(WebAssembly::TRY))
1201 .
addImm(int64_t(WebAssembly::BlockType::Void));
1207 if (UnwindDest != FakeCallerBB)
1210 auto SplitPos = std::next(RangeEnd->
getIterator());
1211 if (SplitPos == EndBB->end()) {
1214 MF.
insert(std::next(EndBB->getIterator()), DelegateBB);
1215 EndBB->addSuccessor(DelegateBB);
1225 bool CatchAfterSplit =
false;
1226 if (EndBB->isEHPad()) {
1230 CatchAfterSplit =
true;
1236 MachineBasicBlock *PreBB =
nullptr, *PostBB =
nullptr;
1237 if (!CatchAfterSplit) {
1256 PostBB->splice(PostBB->end(), PreBB, SplitPos, PreBB->
end());
1257 PostBB->transferSuccessors(PreBB);
1273 assert(EndBB->isEHPad());
1276 MF.
insert(PostBB->getIterator(), PreBB);
1277 MF.
insert(PostBB->getIterator(), DelegateBB);
1278 PreBB->
splice(PreBB->
end(), PostBB, PostBB->begin(), SplitPos);
1290 TII.get(WebAssembly::DELEGATE))
1292 registerTryScope(Try, Delegate,
nullptr);
1311WebAssemblyCFGStackify::getTrampolineBlock(MachineBasicBlock *UnwindDest) {
1315 auto It = UnwindDestToTrampoline.
find(UnwindDest);
1316 if (It != UnwindDestToTrampoline.
end())
1321 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
1323 MachineInstr *
Block =
nullptr;
1324 MachineBasicBlock *TrampolineBB =
nullptr;
1327 if (UnwindDest == getFakeCallerBlock(MF)) {
1331 auto BeginPos = MF.
begin()->begin();
1335 TII.get(WebAssembly::BLOCK))
1336 .
addImm(int64_t(WebAssembly::BlockType::Exnref));
1337 TrampolineBB = getCallerTrampolineBlock(MF);
1338 MachineBasicBlock *PrevBB = &*std::prev(CallerTrampolineBB->
getIterator());
1344 auto *TargetBeginTry = EHPadToTry[UnwindDest];
1345 auto *TargetEndTry = BeginToEnd[TargetBeginTry];
1346 auto *TargetBeginBB = TargetBeginTry->getParent();
1347 auto *TargetEndBB = TargetEndTry->getParent();
1349 Block =
BuildMI(*TargetBeginBB, std::next(TargetBeginTry->getIterator()),
1350 TargetBeginTry->getDebugLoc(),
TII.get(WebAssembly::BLOCK))
1351 .
addImm(int64_t(WebAssembly::BlockType::Exnref));
1353 EndDebugLoc = TargetEndTry->getDebugLoc();
1354 MF.
insert(TargetEndBB->getIterator(), TrampolineBB);
1360 MachineInstr *EndBlock =
1361 BuildMI(TrampolineBB, EndDebugLoc,
TII.get(WebAssembly::END_BLOCK));
1362 auto ExnReg = MRI.createVirtualRegister(&WebAssembly::EXNREFRegClass);
1363 BuildMI(TrampolineBB, EndDebugLoc,
TII.get(WebAssembly::CATCH_ALL_REF))
1365 BuildMI(TrampolineBB, EndDebugLoc,
TII.get(WebAssembly::THROW_REF))
1371 MachineBasicBlock *TrampolineLayoutPred = TrampolineBB->
getPrevNode();
1373 TII.get(WebAssembly::UNREACHABLE));
1375 registerScope(
Block, EndBlock);
1376 UnwindDestToTrampoline[UnwindDest] = TrampolineBB;
1377 return TrampolineBB;
1382void WebAssemblyCFGStackify::addNestedTryTable(MachineInstr *RangeBegin,
1383 MachineInstr *RangeEnd,
1384 MachineBasicBlock *UnwindDest) {
1385 auto *BeginBB = RangeBegin->
getParent();
1388 MachineFunction &MF = *BeginBB->getParent();
1389 const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
1390 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
1393 auto *TrampolineBB = getTrampolineBlock(UnwindDest);
1397 SmallPtrSet<const MachineInstr *, 4> AfterSet;
1398 AfterSet.
insert(RangeBegin);
1401 if (std::prev(
I)->isDebugInstr() || std::prev(
I)->isPosition())
1404 AfterSet.
insert(&*std::prev(
I));
1411 BeginBB, SmallPtrSet<const MachineInstr *, 4>(), AfterSet);
1412 MachineInstr *TryTable =
1414 TII.get(WebAssembly::TRY_TABLE))
1415 .
addImm(int64_t(WebAssembly::BlockType::Void))
1424 auto SplitPos = std::next(RangeEnd->
getIterator());
1425 if (SplitPos == EndBB->end()) {
1428 MF.
insert(std::next(EndBB->getIterator()), EndTryTableBB);
1429 EndBB->addSuccessor(EndTryTableBB);
1439 bool CatchAfterSplit =
false;
1440 if (EndBB->isEHPad()) {
1444 CatchAfterSplit =
true;
1450 MachineBasicBlock *PreBB =
nullptr, *PostBB =
nullptr;
1451 if (!CatchAfterSplit) {
1470 PostBB->splice(PostBB->end(), PreBB, SplitPos, PreBB->
end());
1471 PostBB->transferSuccessors(PreBB);
1487 assert(EndBB->isEHPad());
1490 MF.
insert(PostBB->getIterator(), PreBB);
1491 MF.
insert(PostBB->getIterator(), EndTryTableBB);
1492 PreBB->
splice(PreBB->
end(), PostBB, PostBB->begin(), SplitPos);
1504 TII.get(WebAssembly::END_TRY_TABLE));
1505 registerTryScope(TryTable, EndTryTable, TrampolineBB);
1557 MachineInstr *EndTryTable =
nullptr, *EndLoop =
nullptr;
1558 for (
auto &
MI :
reverse(*EndTryTableBB)) {
1559 if (
MI.getOpcode() == WebAssembly::END_TRY_TABLE) {
1563 if (EndTryTable &&
MI.getOpcode() == WebAssembly::END_LOOP) {
1573 auto SplitPos = std::next(EndLoop->getIterator());
1574 EndLoopBB->splice(EndLoopBB->end(), EndTryTableBB, EndTryTableBB->
begin(),
1576 EndLoopBB->addSuccessor(EndTryTableBB);
1582 std::string Name =
"bb.";
1584 if (
MBB->getBasicBlock()) {
1586 Name +=
MBB->getBasicBlock()->getName();
1591bool WebAssemblyCFGStackify::fixCallUnwindMismatches(MachineFunction &MF) {
1838 using TryRange = std::pair<MachineInstr *, MachineInstr *>;
1840 DenseMap<MachineBasicBlock *, SmallVector<TryRange, 4>> UnwindDestToTryRanges;
1846 bool SeenThrowableInstInBB =
false;
1850 else if (
MI.getOpcode() == WebAssembly::DELEGATE)
1855 else if (
MI.getOpcode() == WebAssembly::END_TRY_TABLE)
1896 EHPadStack.
push_back(TryToEHPad[EndToBegin[&
MI]]);
1905 SeenThrowableInstInBB =
true;
1909 MachineBasicBlock *UnwindDest =
nullptr;
1915 if (Succ->isEHPad()) {
1920 if (EHPadStack.
back() == UnwindDest)
1924 MachineInstr *RangeBegin = &
MI, *RangeEnd = &
MI;
1926 std::prev(RangeBegin->
getIterator())->isEHLabel())
1927 RangeBegin = &*std::prev(RangeBegin->
getIterator());
1928 if (std::next(RangeEnd->getIterator()) !=
MBB.
end() &&
1929 std::next(RangeEnd->getIterator())->isEHLabel())
1930 RangeEnd = &*std::next(RangeEnd->getIterator());
1933 UnwindDestToTryRanges[UnwindDest].push_back(
1934 TryRange(RangeBegin, RangeEnd));
1936 <<
"\nCall = " <<
MI
1937 <<
"\nOriginal dest = " <<
getBBName(UnwindDest)
1950 MachineInstr *RangeBegin =
nullptr, *RangeEnd =
nullptr;
1953 auto RecordCallerMismatchRange = [&](
const MachineBasicBlock *CurrentDest) {
1954 UnwindDestToTryRanges[getFakeCallerBlock(MF)].push_back(
1955 TryRange(RangeBegin, RangeEnd));
1958 <<
"\nRange begin = " << *RangeBegin
1959 <<
"Range end = " << *RangeEnd
1960 <<
"\nOriginal dest = caller Current dest = "
1962 RangeBegin = RangeEnd =
nullptr;
1966 bool SeenThrowableInstInBB =
false;
1974 SeenThrowableInstInBB =
true;
1979 RecordCallerMismatchRange(EHPadStack.
back());
1984 else if (EHPadStack.
empty() || EHPadStack.
back() == FakeCallerBB ||
1993 RangeBegin = RangeEnd = &
MI;
2001 else if (
MI.getOpcode() == WebAssembly::DELEGATE)
2007 MI.getOpcode() == WebAssembly::END_TRY_TABLE)
2008 EHPadStack.
push_back(TryToEHPad[EndToBegin[&
MI]]);
2012 RecordCallerMismatchRange(EHPadStack.
back());
2018 if (UnwindDestToTryRanges.
empty())
2024 for (
auto &[UnwindDest,
_] : UnwindDestToTryRanges) {
2025 auto It = EHPadToTry.
find(UnwindDest);
2028 if (It != EHPadToTry.
end()) {
2029 auto *TryTable = It->second;
2030 auto *EndTryTable = BeginToEnd[TryTable];
2036 for (
auto &
P : UnwindDestToTryRanges) {
2037 NumCallUnwindMismatches +=
P.second.size();
2038 MachineBasicBlock *UnwindDest =
P.first;
2039 auto &TryRanges =
P.second;
2041 for (
auto Range : TryRanges) {
2042 MachineInstr *RangeBegin =
nullptr, *RangeEnd =
nullptr;
2043 std::tie(RangeBegin, RangeEnd) =
Range;
2052 if (UnwindDest != getFakeCallerBlock(MF)) {
2053 MachineBasicBlock *EHPad =
nullptr;
2055 if (Succ->isEHPad()) {
2065 addNestedTryDelegate(RangeBegin, RangeEnd, UnwindDest);
2067 addNestedTryTable(RangeBegin, RangeEnd, UnwindDest);
2074bool WebAssemblyCFGStackify::fixCatchUnwindMismatches(MachineFunction &MF) {
2179 auto HasUnwindDest = [&](
const MachineBasicBlock *EHPad) {
2182 for (
auto I = InvokeBB->succ_begin(),
E = InvokeBB->succ_end();
I !=
E; ++
I)
2184 return std::next(
I) !=
E;
2190 auto GetUnwindDest = [&](
const MachineBasicBlock *EHPad) {
2193 for (
auto I = InvokeBB->succ_begin(),
E = InvokeBB->succ_end();
I !=
E;
2196 auto *
Next = std::next(
I);
2206 DenseMap<MachineBasicBlock *, MachineBasicBlock *> EHPadToUnwindDest;
2212 }
else if (
MI.getOpcode() == WebAssembly::DELEGATE) {
2224 else if (EHPadStack.
empty() && HasUnwindDest(EHPad)) {
2226 <<
"'s unwind destination does not exist anymore"
2232 else if (!EHPadStack.
empty() && EHPadStack.
back() != FakeCallerBB &&
2233 !HasUnwindDest(EHPad)) {
2234 EHPadToUnwindDest[EHPad] = getFakeCallerBlock(MF);
2236 <<
"- Catch unwind mismatch:\nEHPad = " <<
getBBName(EHPad)
2237 <<
" Original dest = caller Current dest = "
2243 else if (!EHPadStack.
empty() && HasUnwindDest(EHPad)) {
2244 auto *UnwindDest = GetUnwindDest(EHPad);
2245 if (EHPadStack.
back() != UnwindDest) {
2246 EHPadToUnwindDest[EHPad] = UnwindDest;
2248 <<
getBBName(EHPad) <<
" Original dest = "
2249 <<
getBBName(UnwindDest) <<
" Current dest = "
2260 if (EHPadToUnwindDest.
empty())
2265 for (
auto &[
_, UnwindDest] : EHPadToUnwindDest) {
2266 auto It = EHPadToTry.
find(UnwindDest);
2268 if (It != EHPadToTry.
end()) {
2269 auto *TryTable = It->second;
2270 auto *EndTryTable = BeginToEnd[TryTable];
2275 NumCatchUnwindMismatches += EHPadToUnwindDest.size();
2276 SmallPtrSet<MachineBasicBlock *, 4> NewEndTryBBs;
2278 for (
auto &[EHPad, UnwindDest] : EHPadToUnwindDest) {
2279 MachineInstr *Try = EHPadToTry[EHPad];
2280 MachineInstr *EndTry = BeginToEnd[Try];
2282 addNestedTryDelegate(Try, EndTry, UnwindDest);
2285 addNestedTryTable(Try, EndTry, UnwindDest);
2336 for (
auto &
MBB : MF) {
2337 for (
auto &
MI :
MBB) {
2338 if (
MI.isTerminator()) {
2339 for (
auto &MO :
MI.operands()) {
2340 if (MO.isMBB() && NewEndTryBBs.
count(MO.getMBB())) {
2341 auto *BrDest = MO.getMBB();
2342 bool FoundEndBlock =
false;
2343 for (; std::next(BrDest->getIterator()) != MF.end();
2344 BrDest = BrDest->getNextNode()) {
2345 for (
const auto &
MI : *BrDest) {
2346 if (
MI.getOpcode() == WebAssembly::END_BLOCK) {
2347 FoundEndBlock =
true;
2365void WebAssemblyCFGStackify::recalculateScopeTops(MachineFunction &MF) {
2375 switch (
MI.getOpcode()) {
2376 case WebAssembly::END_BLOCK:
2377 case WebAssembly::END_LOOP:
2378 case WebAssembly::END_TRY:
2379 case WebAssembly::END_TRY_TABLE:
2380 case WebAssembly::DELEGATE:
2383 case WebAssembly::CATCH_LEGACY:
2384 case WebAssembly::CATCH_ALL_LEGACY:
2399void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) {
2400 const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
2402 if (MFI.getResults().empty())
2408 MFI.getResults().size() > 1
2409 ? WebAssembly::BlockType::Multivalue
2419 MachineInstr &
MI = *It++;
2420 if (
MI.isPosition() ||
MI.isDebugInstr())
2422 switch (
MI.getOpcode()) {
2423 case WebAssembly::END_TRY: {
2427 auto *EHPad = TryToEHPad.
lookup(EndToBegin[&
MI]);
2431 if (NextIt != EHPad->
rend())
2435 case WebAssembly::END_BLOCK:
2436 case WebAssembly::END_LOOP:
2437 case WebAssembly::END_TRY_TABLE:
2438 case WebAssembly::DELEGATE:
2439 EndToBegin[&
MI]->getOperand(0).setImm(int32_t(RetType));
2451 while (!Worklist.
empty())
2461 TII.get(WebAssembly::END_FUNCTION));
2487 std::vector<MachineInstr *> EndTryTables;
2488 for (
auto &
MBB : MF)
2489 for (
auto &
MI :
MBB)
2490 if (
MI.getOpcode() == WebAssembly::END_TRY_TABLE)
2491 EndTryTables.push_back(&
MI);
2493 for (
auto *EndTryTable : EndTryTables) {
2496 MF.
insert(
MBB->getIterator(), NewEndTryTableBB);
2497 auto SplitPos = std::next(EndTryTable->
getIterator());
2498 NewEndTryTableBB->splice(NewEndTryTableBB->end(),
MBB,
MBB->begin(),
2500 NewEndTryTableBB->addSuccessor(
MBB);
2502 TII.get(WebAssembly::UNREACHABLE));
2507void WebAssemblyCFGStackify::placeMarkers(MachineFunction &MF) {
2512 for (
auto &
MBB : MF)
2513 placeLoopMarker(
MBB);
2515 const MCAsmInfo &MCAI = MF.getTarget().getMCAsmInfo();
2516 for (
auto &
MBB : MF) {
2520 MF.getFunction().hasPersonalityFn()) {
2522 placeTryMarker(
MBB);
2524 placeTryTableMarker(
MBB);
2528 placeBlockMarker(
MBB);
2533 MF.getFunction().hasPersonalityFn()) {
2534 const auto &
TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
2541 fixCatchUnwindMismatches(MF);
2542 fixCallUnwindMismatches(MF);
2545 recalculateScopeTops(MF);
2549unsigned WebAssemblyCFGStackify::getBranchDepth(
2550 const SmallVectorImpl<EndMarkerInfo> &Stack,
const MachineBasicBlock *
MBB) {
2561unsigned WebAssemblyCFGStackify::getDelegateDepth(
2562 const SmallVectorImpl<EndMarkerInfo> &Stack,
const MachineBasicBlock *
MBB) {
2563 if (
MBB == FakeCallerBB)
2564 return Stack.size();
2570 return getBranchDepth(Stack,
MBB);
2586 const MachineInstr *EndTry = BeginToEnd[EHPadToTry[
MBB]];
2588 if (
X.first == EndTry->
getParent() &&
X.second == EndTry)
2596unsigned WebAssemblyCFGStackify::getRethrowDepth(
2597 const SmallVectorImpl<EndMarkerInfo> &Stack,
2598 const MachineBasicBlock *EHPadToRethrow) {
2601 const MachineInstr *End =
X.second;
2602 if (End->
getOpcode() == WebAssembly::END_TRY) {
2603 auto *EHPad = TryToEHPad[EndToBegin[End]];
2604 if (EHPadToRethrow == EHPad)
2613void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) {
2617 auto RewriteOperands = [&](MachineInstr &
MI) {
2620 while (
MI.getNumOperands() > 0)
2621 MI.removeOperand(
MI.getNumOperands() - 1);
2622 for (
auto MO :
Ops) {
2624 if (
MI.getOpcode() == WebAssembly::DELEGATE)
2626 else if (
MI.getOpcode() == WebAssembly::RETHROW)
2631 MI.addOperand(MF, MO);
2637 switch (
MI.getOpcode()) {
2638 case WebAssembly::BLOCK:
2639 case WebAssembly::TRY:
2640 assert(ScopeTops[
Stack.back().first->getNumber()]->getNumber() <=
2642 "Block/try/try_table marker should be balanced");
2646 case WebAssembly::TRY_TABLE:
2647 assert(ScopeTops[
Stack.back().first->getNumber()]->getNumber() <=
2649 "Block/try/try_table marker should be balanced");
2651 RewriteOperands(
MI);
2654 case WebAssembly::LOOP:
2655 assert(
Stack.back().first == &
MBB &&
"Loop top should be balanced");
2659 case WebAssembly::END_BLOCK:
2660 case WebAssembly::END_TRY:
2661 case WebAssembly::END_TRY_TABLE:
2665 case WebAssembly::END_LOOP:
2669 case WebAssembly::DELEGATE:
2670 RewriteOperands(
MI);
2675 if (
MI.isTerminator())
2676 RewriteOperands(
MI);
2681 assert(
Stack.empty() &&
"Control flow should be balanced");
2684void WebAssemblyCFGStackify::cleanupFunctionData(MachineFunction &MF) {
2687 AppendixBB = FakeCallerBB = CallerTrampolineBB =
nullptr;
2690void WebAssemblyCFGStackify::releaseMemory() {
2696 UnwindDestToTrampoline.
clear();
2699bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) {
2701 "********** Function: "
2704 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
2718 removeUnnecessaryInstrs(MF);
2721 rewriteDepthImmediates(MF);
2725 fixEndsAtEndOfFunction(MF);
2728 const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
2731 cleanupFunctionData(MF);
2733 MF.
getInfo<WebAssemblyFunctionInfo>()->setCFGStackified();
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[]
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.
AnalysisUsage & addRequired()
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
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.
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
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
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
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.
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)
StringRef - Represent a constant reference to a string, i.e.
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.
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isChild(const MachineInstr &MI, const WebAssemblyFunctionInfo &MFI)
Test whether MI is a child of some other node in an expression tree.
bool isArgument(unsigned Opc)
bool isCatchAll(unsigned Opc)
bool isMarker(unsigned Opc)
unsigned getCopyOpcodeForRegClass(const TargetRegisterClass *RC)
Returns the appropriate copy opcode for the given register class.
wasm::ValType toValType(MVT Type)
cl::opt< bool > WasmUseLegacyEH
MachineInstr * findCatch(MachineBasicBlock *EHPad)
Find a catch instruction from an EH pad.
bool isCatch(unsigned Opc)
BlockType
Used as immediate MachineOperands for block signatures.
bool mayThrow(const MachineInstr &MI)
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...
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createWebAssemblyCFGStackify()
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FunctionAddr VTableAddr Next