diff options
author | Heejin Ahn <aheejin@gmail.com> | 2021-02-21 21:12:37 -0800 |
---|---|---|
committer | Heejin Ahn <aheejin@gmail.com> | 2021-02-22 13:25:58 -0800 |
commit | f47a654a3954b22daf831189e9c24a9ddf2bc9ff (patch) | |
tree | 3d2c3188b09ca42abf4a4fa783ae41140927fa3e /llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | |
parent | 51fb5bf4d6c91075abdfd24769ef60fcfd810baa (diff) | |
download | llvm-f47a654a3954b22daf831189e9c24a9ddf2bc9ff.zip llvm-f47a654a3954b22daf831189e9c24a9ddf2bc9ff.tar.gz llvm-f47a654a3954b22daf831189e9c24a9ddf2bc9ff.tar.bz2 |
[WebAssembly] Remap branch dests after fixCatchUnwindMismatches
Fixing catch unwind mismatches can sometimes invalidate existing branch
destinations. This CL remaps those destinations after placing
try-delegates.
Fixes https://github.com/emscripten-core/emscripten/issues/13515.
Reviewed By: dschuff
Differential Revision: https://reviews.llvm.org/D97178
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp')
-rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp index 1870979..73826d8 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -1368,6 +1368,9 @@ bool WebAssemblyCFGStackify::fixCatchUnwindMismatches(MachineFunction &MF) { if (EHPadToUnwindDest.empty()) return false; NumCatchUnwindMismatches += EHPadToUnwindDest.size(); + // <current branch dest, future branch dest> map, because fixing catch unwind + // mismatches can invalidate branch destinations + DenseMap<MachineBasicBlock *, MachineBasicBlock *> BrDestMap; for (auto &P : EHPadToUnwindDest) { MachineBasicBlock *EHPad = P.first; @@ -1375,6 +1378,66 @@ bool WebAssemblyCFGStackify::fixCatchUnwindMismatches(MachineFunction &MF) { MachineInstr *Try = EHPadToTry[EHPad]; MachineInstr *EndTry = BeginToEnd[Try]; addTryDelegate(Try, EndTry, UnwindDest); + BrDestMap[EndTry->getParent()] = + EndTry->getParent()->getNextNode()->getNextNode(); + } + + // Adding a try-delegate wrapping an existing try-catch-end can make existing + // branch destination BBs invalid. For example, + // + // - Before: + // bb0: + // block + // br bb3 + // bb1: + // try + // ... + // bb2: (ehpad) + // catch + // bb3: + // end_try + // end_block ;; 'br bb3' targets here + // + // Suppose this try-catch-end has a catch unwind mismatch, so we need to wrap + // this with a try-delegate. Then this becomes: + // + // - After: + // bb0: + // block + // br bb3 ;; invalid destination! + // bb1: + // try ;; (new instruction) + // try + // ... + // bb2: (ehpad) + // catch + // bb3: + // end_try ;; 'br bb3' still incorrectly targets here! + // delegate_bb: ;; (new BB) + // delegate ;; (new instruction) + // split_bb: ;; (new BB) + // end_block + // + // Now 'br bb3' incorrectly branches to an inner scope. + // + // As we can see in this case, when branches target a BB that has both + // 'end_try' and 'end_block' and the BB is split to insert a 'delegate', we + // have to remap existing branch destinations so that they target not the + // 'end_try' BB but the new 'end_block' BB, which should be the second next BB + // of 'end_try' (because there is a 'delegate' BB in between). In this + // example, the 'br bb3' instruction should be remapped to 'br split_bb'. + for (auto &MBB : MF) { + for (auto &MI : MBB) { + if (MI.isTerminator()) { + for (auto &MO : MI.operands()) { + if (MO.isMBB()) { + auto It = BrDestMap.find(MO.getMBB()); + if (It != BrDestMap.end()) + MO.setMBB(It->second); + } + } + } + } } return true; |