blob: 900178798393a1bc225fd22996bbc06b5d402feb [file] [log] [blame]
Dan Gohman950a13c2015-09-16 16:51:30 +00001//===-- WebAssemblyCFGStackify.cpp - CFG Stackification -------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Dan Gohman950a13c2015-09-16 16:51:30 +00006//
7//===----------------------------------------------------------------------===//
8///
9/// \file
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000010/// This file implements a CFG stacking pass.
Dan Gohman950a13c2015-09-16 16:51:30 +000011///
Heejin Ahne76fa9e2018-08-16 23:50:59 +000012/// This pass inserts BLOCK, LOOP, and TRY markers to mark the start of scopes,
13/// since scope boundaries serve as the labels for WebAssembly's control
14/// transfers.
Dan Gohman950a13c2015-09-16 16:51:30 +000015///
16/// This is sufficient to convert arbitrary CFGs into a form that works on
17/// WebAssembly, provided that all loops are single-entry.
18///
Heejin Ahne76fa9e2018-08-16 23:50:59 +000019/// In case we use exceptions, this pass also fixes mismatches in unwind
20/// destinations created during transforming CFG into wasm structured format.
21///
Dan Gohman950a13c2015-09-16 16:51:30 +000022//===----------------------------------------------------------------------===//
23
Dan Gohman950a13c2015-09-16 16:51:30 +000024#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000025#include "WebAssembly.h"
Heejin Ahne76fa9e2018-08-16 23:50:59 +000026#include "WebAssemblyExceptionInfo.h"
Dan Gohmaned0f1132016-01-30 05:01:06 +000027#include "WebAssemblyMachineFunctionInfo.h"
Dan Gohman950a13c2015-09-16 16:51:30 +000028#include "WebAssemblySubtarget.h"
Dan Gohman4fc4e422016-10-24 19:49:43 +000029#include "WebAssemblyUtilities.h"
Dan Gohman32807932015-11-23 16:19:56 +000030#include "llvm/CodeGen/MachineDominators.h"
Dan Gohman950a13c2015-09-16 16:51:30 +000031#include "llvm/CodeGen/MachineFunction.h"
32#include "llvm/CodeGen/MachineInstrBuilder.h"
33#include "llvm/CodeGen/MachineLoopInfo.h"
Derek Schuff9c3bf312016-01-13 17:10:28 +000034#include "llvm/CodeGen/MachineRegisterInfo.h"
Dan Gohman950a13c2015-09-16 16:51:30 +000035#include "llvm/CodeGen/Passes.h"
Heejin Ahne76fa9e2018-08-16 23:50:59 +000036#include "llvm/CodeGen/WasmEHFuncInfo.h"
37#include "llvm/MC/MCAsmInfo.h"
Dan Gohman950a13c2015-09-16 16:51:30 +000038#include "llvm/Support/Debug.h"
39#include "llvm/Support/raw_ostream.h"
Heejin Ahnd6f48782019-01-30 03:21:57 +000040#include <cstring>
Dan Gohman950a13c2015-09-16 16:51:30 +000041using namespace llvm;
42
43#define DEBUG_TYPE "wasm-cfg-stackify"
44
45namespace {
46class WebAssemblyCFGStackify final : public MachineFunctionPass {
Mehdi Amini117296c2016-10-01 02:56:57 +000047 StringRef getPassName() const override { return "WebAssembly CFG Stackify"; }
Dan Gohman950a13c2015-09-16 16:51:30 +000048
49 void getAnalysisUsage(AnalysisUsage &AU) const override {
Dan Gohman32807932015-11-23 16:19:56 +000050 AU.addRequired<MachineDominatorTree>();
Dan Gohman950a13c2015-09-16 16:51:30 +000051 AU.addRequired<MachineLoopInfo>();
Heejin Ahne76fa9e2018-08-16 23:50:59 +000052 AU.addRequired<WebAssemblyExceptionInfo>();
Dan Gohman950a13c2015-09-16 16:51:30 +000053 MachineFunctionPass::getAnalysisUsage(AU);
54 }
55
56 bool runOnMachineFunction(MachineFunction &MF) override;
57
Heejin Ahne76fa9e2018-08-16 23:50:59 +000058 // For each block whose label represents the end of a scope, record the block
59 // which holds the beginning of the scope. This will allow us to quickly skip
60 // over scoped regions when walking blocks.
61 SmallVector<MachineBasicBlock *, 8> ScopeTops;
62
63 void placeMarkers(MachineFunction &MF);
64 void placeBlockMarker(MachineBasicBlock &MBB);
65 void placeLoopMarker(MachineBasicBlock &MBB);
66 void placeTryMarker(MachineBasicBlock &MBB);
Heejin Ahncf699b42019-02-27 00:50:53 +000067 void removeUnnecessaryInstrs(MachineFunction &MF);
Heejin Ahne76fa9e2018-08-16 23:50:59 +000068 void rewriteDepthImmediates(MachineFunction &MF);
69 void fixEndsAtEndOfFunction(MachineFunction &MF);
70
71 // For each BLOCK|LOOP|TRY, the corresponding END_(BLOCK|LOOP|TRY).
72 DenseMap<const MachineInstr *, MachineInstr *> BeginToEnd;
73 // For each END_(BLOCK|LOOP|TRY), the corresponding BLOCK|LOOP|TRY.
74 DenseMap<const MachineInstr *, MachineInstr *> EndToBegin;
75 // <TRY marker, EH pad> map
76 DenseMap<const MachineInstr *, MachineBasicBlock *> TryToEHPad;
77 // <EH pad, TRY marker> map
78 DenseMap<const MachineBasicBlock *, MachineInstr *> EHPadToTry;
Heejin Ahne76fa9e2018-08-16 23:50:59 +000079
Heejin Ahncf699b42019-02-27 00:50:53 +000080 // Helper functions to register / unregister scope information created by
81 // marker instructions.
Heejin Ahne76fa9e2018-08-16 23:50:59 +000082 void registerScope(MachineInstr *Begin, MachineInstr *End);
83 void registerTryScope(MachineInstr *Begin, MachineInstr *End,
84 MachineBasicBlock *EHPad);
Heejin Ahncf699b42019-02-27 00:50:53 +000085 void unregisterScope(MachineInstr *Begin);
Heejin Ahne76fa9e2018-08-16 23:50:59 +000086
Dan Gohman950a13c2015-09-16 16:51:30 +000087public:
88 static char ID; // Pass identification, replacement for typeid
89 WebAssemblyCFGStackify() : MachineFunctionPass(ID) {}
Heejin Ahne76fa9e2018-08-16 23:50:59 +000090 ~WebAssemblyCFGStackify() override { releaseMemory(); }
91 void releaseMemory() override;
Dan Gohman950a13c2015-09-16 16:51:30 +000092};
93} // end anonymous namespace
94
95char WebAssemblyCFGStackify::ID = 0;
Jacob Gravelle40926452018-03-30 20:36:58 +000096INITIALIZE_PASS(WebAssemblyCFGStackify, DEBUG_TYPE,
Heejin Ahnf208f632018-09-05 01:27:38 +000097 "Insert BLOCK and LOOP markers for WebAssembly scopes", false,
98 false)
Jacob Gravelle40926452018-03-30 20:36:58 +000099
Dan Gohman950a13c2015-09-16 16:51:30 +0000100FunctionPass *llvm::createWebAssemblyCFGStackify() {
101 return new WebAssemblyCFGStackify();
102}
103
Dan Gohmanb3aa1ec2015-12-16 19:06:41 +0000104/// Test whether Pred has any terminators explicitly branching to MBB, as
105/// opposed to falling through. Note that it's possible (eg. in unoptimized
106/// code) for a branch instruction to both branch to a block and fallthrough
107/// to it, so we check the actual branch operands to see if there are any
108/// explicit mentions.
Heejin Ahn18c56a02019-02-04 19:13:39 +0000109static bool explicitlyBranchesTo(MachineBasicBlock *Pred,
Dan Gohman35e4a282016-01-08 01:06:00 +0000110 MachineBasicBlock *MBB) {
Dan Gohmanb3aa1ec2015-12-16 19:06:41 +0000111 for (MachineInstr &MI : Pred->terminators())
Heejin Ahnd6f48782019-01-30 03:21:57 +0000112 for (MachineOperand &MO : MI.explicit_operands())
113 if (MO.isMBB() && MO.getMBB() == MBB)
114 return true;
Dan Gohmanb3aa1ec2015-12-16 19:06:41 +0000115 return false;
116}
117
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000118// Returns an iterator to the earliest position possible within the MBB,
119// satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet
120// contains instructions that should go before the marker, and AfterSet contains
121// ones that should go after the marker. In this function, AfterSet is only
122// used for sanity checking.
123static MachineBasicBlock::iterator
Heejin Ahn18c56a02019-02-04 19:13:39 +0000124getEarliestInsertPos(MachineBasicBlock *MBB,
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000125 const SmallPtrSet<const MachineInstr *, 4> &BeforeSet,
126 const SmallPtrSet<const MachineInstr *, 4> &AfterSet) {
127 auto InsertPos = MBB->end();
128 while (InsertPos != MBB->begin()) {
129 if (BeforeSet.count(&*std::prev(InsertPos))) {
130#ifndef NDEBUG
131 // Sanity check
132 for (auto Pos = InsertPos, E = MBB->begin(); Pos != E; --Pos)
133 assert(!AfterSet.count(&*std::prev(Pos)));
134#endif
135 break;
136 }
137 --InsertPos;
138 }
139 return InsertPos;
140}
141
142// Returns an iterator to the latest position possible within the MBB,
143// satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet
144// contains instructions that should go before the marker, and AfterSet contains
145// ones that should go after the marker. In this function, BeforeSet is only
146// used for sanity checking.
147static MachineBasicBlock::iterator
Heejin Ahn18c56a02019-02-04 19:13:39 +0000148getLatestInsertPos(MachineBasicBlock *MBB,
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000149 const SmallPtrSet<const MachineInstr *, 4> &BeforeSet,
150 const SmallPtrSet<const MachineInstr *, 4> &AfterSet) {
151 auto InsertPos = MBB->begin();
152 while (InsertPos != MBB->end()) {
153 if (AfterSet.count(&*InsertPos)) {
154#ifndef NDEBUG
155 // Sanity check
156 for (auto Pos = InsertPos, E = MBB->end(); Pos != E; ++Pos)
157 assert(!BeforeSet.count(&*Pos));
158#endif
159 break;
160 }
161 ++InsertPos;
162 }
163 return InsertPos;
164}
165
166void WebAssemblyCFGStackify::registerScope(MachineInstr *Begin,
167 MachineInstr *End) {
168 BeginToEnd[Begin] = End;
169 EndToBegin[End] = Begin;
170}
171
172void WebAssemblyCFGStackify::registerTryScope(MachineInstr *Begin,
173 MachineInstr *End,
174 MachineBasicBlock *EHPad) {
175 registerScope(Begin, End);
176 TryToEHPad[Begin] = EHPad;
177 EHPadToTry[EHPad] = Begin;
178}
179
Heejin Ahncf699b42019-02-27 00:50:53 +0000180void WebAssemblyCFGStackify::unregisterScope(MachineInstr *Begin) {
181 assert(BeginToEnd.count(Begin));
182 MachineInstr *End = BeginToEnd[Begin];
183 assert(EndToBegin.count(End));
184 BeginToEnd.erase(Begin);
185 EndToBegin.erase(End);
186 MachineBasicBlock *EHPad = TryToEHPad.lookup(Begin);
187 if (EHPad) {
188 assert(EHPadToTry.count(EHPad));
189 TryToEHPad.erase(Begin);
190 EHPadToTry.erase(EHPad);
191 }
192}
193
Dan Gohman32807932015-11-23 16:19:56 +0000194/// Insert a BLOCK marker for branches to MBB (if needed).
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000195void WebAssemblyCFGStackify::placeBlockMarker(MachineBasicBlock &MBB) {
196 // This should have been handled in placeTryMarker.
197 if (MBB.isEHPad())
198 return;
199
200 MachineFunction &MF = *MBB.getParent();
201 auto &MDT = getAnalysis<MachineDominatorTree>();
202 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
203 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
204
Dan Gohman8fe7e862015-12-14 22:51:54 +0000205 // First compute the nearest common dominator of all forward non-fallthrough
206 // predecessors so that we minimize the time that the BLOCK is on the stack,
207 // which reduces overall stack height.
Dan Gohman32807932015-11-23 16:19:56 +0000208 MachineBasicBlock *Header = nullptr;
209 bool IsBranchedTo = false;
Heejin Ahnd6f48782019-01-30 03:21:57 +0000210 bool IsBrOnExn = false;
211 MachineInstr *BrOnExn = nullptr;
Dan Gohman32807932015-11-23 16:19:56 +0000212 int MBBNumber = MBB.getNumber();
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000213 for (MachineBasicBlock *Pred : MBB.predecessors()) {
Dan Gohman32807932015-11-23 16:19:56 +0000214 if (Pred->getNumber() < MBBNumber) {
215 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
Heejin Ahn18c56a02019-02-04 19:13:39 +0000216 if (explicitlyBranchesTo(Pred, &MBB)) {
Dan Gohman32807932015-11-23 16:19:56 +0000217 IsBranchedTo = true;
Heejin Ahnd6f48782019-01-30 03:21:57 +0000218 if (Pred->getFirstTerminator()->getOpcode() == WebAssembly::BR_ON_EXN) {
219 IsBrOnExn = true;
220 assert(!BrOnExn && "There should be only one br_on_exn per block");
221 BrOnExn = &*Pred->getFirstTerminator();
222 }
223 }
Dan Gohman32807932015-11-23 16:19:56 +0000224 }
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000225 }
Dan Gohman32807932015-11-23 16:19:56 +0000226 if (!Header)
227 return;
228 if (!IsBranchedTo)
Dan Gohman950a13c2015-09-16 16:51:30 +0000229 return;
230
Dan Gohman8fe7e862015-12-14 22:51:54 +0000231 assert(&MBB != &MF.front() && "Header blocks shouldn't have predecessors");
Benjamin Krameref0a45a2016-09-05 12:06:47 +0000232 MachineBasicBlock *LayoutPred = &*std::prev(MachineFunction::iterator(&MBB));
Dan Gohman8fe7e862015-12-14 22:51:54 +0000233
234 // If the nearest common dominator is inside a more deeply nested context,
235 // walk out to the nearest scope which isn't more deeply nested.
236 for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) {
237 if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) {
238 if (ScopeTop->getNumber() > Header->getNumber()) {
239 // Skip over an intervening scope.
Benjamin Krameref0a45a2016-09-05 12:06:47 +0000240 I = std::next(MachineFunction::iterator(ScopeTop));
Dan Gohman8fe7e862015-12-14 22:51:54 +0000241 } else {
242 // We found a scope level at an appropriate depth.
243 Header = ScopeTop;
244 break;
245 }
246 }
247 }
248
Dan Gohman8fe7e862015-12-14 22:51:54 +0000249 // Decide where in Header to put the BLOCK.
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000250
251 // Instructions that should go before the BLOCK.
252 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
253 // Instructions that should go after the BLOCK.
254 SmallPtrSet<const MachineInstr *, 4> AfterSet;
255 for (const auto &MI : *Header) {
256 // If there is a previously placed LOOP/TRY marker and the bottom block of
257 // the loop/exception is above MBB, it should be after the BLOCK, because
258 // the loop/exception is nested in this block. Otherwise it should be before
259 // the BLOCK.
260 if (MI.getOpcode() == WebAssembly::LOOP ||
261 MI.getOpcode() == WebAssembly::TRY) {
Heejin Ahn85631d82019-02-22 07:19:30 +0000262 auto *BottomBB =
263 &*std::prev(MachineFunction::iterator(BeginToEnd[&MI]->getParent()));
264 if (MBB.getNumber() > BottomBB->getNumber())
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000265 AfterSet.insert(&MI);
266#ifndef NDEBUG
267 else
268 BeforeSet.insert(&MI);
269#endif
270 }
271
272 // All previously inserted BLOCK markers should be after the BLOCK because
273 // they are all nested blocks.
274 if (MI.getOpcode() == WebAssembly::BLOCK)
275 AfterSet.insert(&MI);
276
277#ifndef NDEBUG
278 // All END_(BLOCK|LOOP|TRY) markers should be before the BLOCK.
279 if (MI.getOpcode() == WebAssembly::END_BLOCK ||
280 MI.getOpcode() == WebAssembly::END_LOOP ||
281 MI.getOpcode() == WebAssembly::END_TRY)
282 BeforeSet.insert(&MI);
283#endif
284
285 // Terminators should go after the BLOCK.
286 if (MI.isTerminator())
287 AfterSet.insert(&MI);
288 }
289
290 // Local expression tree should go after the BLOCK.
291 for (auto I = Header->getFirstTerminator(), E = Header->begin(); I != E;
292 --I) {
Yury Delendik409b4392018-10-04 23:31:00 +0000293 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
294 continue;
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000295 if (WebAssembly::isChild(*std::prev(I), MFI))
296 AfterSet.insert(&*std::prev(I));
297 else
298 break;
Dan Gohman950a13c2015-09-16 16:51:30 +0000299 }
300
Dan Gohman8fe7e862015-12-14 22:51:54 +0000301 // Add the BLOCK.
Heejin Ahnd6f48782019-01-30 03:21:57 +0000302
303 // 'br_on_exn' extracts except_ref object and pushes variable number of values
304 // depending on its tag. For C++ exception, its a single i32 value, and the
305 // generated code will be in the form of:
306 // block i32
307 // br_on_exn 0, $__cpp_exception
308 // rethrow
309 // end_block
310 WebAssembly::ExprType ReturnType = WebAssembly::ExprType::Void;
311 if (IsBrOnExn) {
312 const char *TagName = BrOnExn->getOperand(1).getSymbolName();
313 if (std::strcmp(TagName, "__cpp_exception") != 0)
314 llvm_unreachable("Only C++ exception is supported");
315 ReturnType = WebAssembly::ExprType::I32;
316 }
317
Heejin Ahn18c56a02019-02-04 19:13:39 +0000318 auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet);
Heejin Ahn92401cc2018-04-14 00:12:12 +0000319 MachineInstr *Begin =
320 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
321 TII.get(WebAssembly::BLOCK))
Heejin Ahnd6f48782019-01-30 03:21:57 +0000322 .addImm(int64_t(ReturnType));
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000323
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000324 // Decide where in Header to put the END_BLOCK.
325 BeforeSet.clear();
326 AfterSet.clear();
327 for (auto &MI : MBB) {
328#ifndef NDEBUG
329 // END_BLOCK should precede existing LOOP and TRY markers.
330 if (MI.getOpcode() == WebAssembly::LOOP ||
331 MI.getOpcode() == WebAssembly::TRY)
332 AfterSet.insert(&MI);
333#endif
334
335 // If there is a previously placed END_LOOP marker and the header of the
336 // loop is above this block's header, the END_LOOP should be placed after
337 // the BLOCK, because the loop contains this block. Otherwise the END_LOOP
338 // should be placed before the BLOCK. The same for END_TRY.
339 if (MI.getOpcode() == WebAssembly::END_LOOP ||
340 MI.getOpcode() == WebAssembly::END_TRY) {
341 if (EndToBegin[&MI]->getParent()->getNumber() >= Header->getNumber())
342 BeforeSet.insert(&MI);
343#ifndef NDEBUG
344 else
345 AfterSet.insert(&MI);
346#endif
347 }
348 }
349
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000350 // Mark the end of the block.
Heejin Ahn18c56a02019-02-04 19:13:39 +0000351 InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet);
Derek Schuff10b31352018-03-15 22:06:51 +0000352 MachineInstr *End = BuildMI(MBB, InsertPos, MBB.findPrevDebugLoc(InsertPos),
Dan Gohman2726b882016-10-06 22:29:32 +0000353 TII.get(WebAssembly::END_BLOCK));
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000354 registerScope(Begin, End);
Dan Gohman8fe7e862015-12-14 22:51:54 +0000355
356 // Track the farthest-spanning scope that ends at this point.
357 int Number = MBB.getNumber();
358 if (!ScopeTops[Number] ||
359 ScopeTops[Number]->getNumber() > Header->getNumber())
360 ScopeTops[Number] = Header;
361}
362
363/// Insert a LOOP marker for a loop starting at MBB (if it's a loop header).
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000364void WebAssemblyCFGStackify::placeLoopMarker(MachineBasicBlock &MBB) {
365 MachineFunction &MF = *MBB.getParent();
366 const auto &MLI = getAnalysis<MachineLoopInfo>();
367 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
368
Dan Gohman8fe7e862015-12-14 22:51:54 +0000369 MachineLoop *Loop = MLI.getLoopFor(&MBB);
370 if (!Loop || Loop->getHeader() != &MBB)
371 return;
372
373 // The operand of a LOOP is the first block after the loop. If the loop is the
374 // bottom of the function, insert a dummy block at the end.
Heejin Ahn817811ca2018-06-19 00:32:03 +0000375 MachineBasicBlock *Bottom = WebAssembly::getBottom(Loop);
Benjamin Krameref0a45a2016-09-05 12:06:47 +0000376 auto Iter = std::next(MachineFunction::iterator(Bottom));
Dan Gohman8fe7e862015-12-14 22:51:54 +0000377 if (Iter == MF.end()) {
378 MachineBasicBlock *Label = MF.CreateMachineBasicBlock();
379 // Give it a fake predecessor so that AsmPrinter prints its label.
380 Label->addSuccessor(Label);
381 MF.push_back(Label);
Benjamin Krameref0a45a2016-09-05 12:06:47 +0000382 Iter = std::next(MachineFunction::iterator(Bottom));
Dan Gohman8fe7e862015-12-14 22:51:54 +0000383 }
384 MachineBasicBlock *AfterLoop = &*Iter;
Dan Gohman8fe7e862015-12-14 22:51:54 +0000385
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000386 // Decide where in Header to put the LOOP.
387 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
388 SmallPtrSet<const MachineInstr *, 4> AfterSet;
389 for (const auto &MI : MBB) {
390 // LOOP marker should be after any existing loop that ends here. Otherwise
391 // we assume the instruction belongs to the loop.
392 if (MI.getOpcode() == WebAssembly::END_LOOP)
393 BeforeSet.insert(&MI);
394#ifndef NDEBUG
395 else
396 AfterSet.insert(&MI);
397#endif
398 }
399
400 // Mark the beginning of the loop.
Heejin Ahn18c56a02019-02-04 19:13:39 +0000401 auto InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet);
Derek Schuff10b31352018-03-15 22:06:51 +0000402 MachineInstr *Begin = BuildMI(MBB, InsertPos, MBB.findDebugLoc(InsertPos),
Dan Gohman2726b882016-10-06 22:29:32 +0000403 TII.get(WebAssembly::LOOP))
Derek Schuff10b31352018-03-15 22:06:51 +0000404 .addImm(int64_t(WebAssembly::ExprType::Void));
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000405
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000406 // Decide where in Header to put the END_LOOP.
407 BeforeSet.clear();
408 AfterSet.clear();
409#ifndef NDEBUG
410 for (const auto &MI : MBB)
411 // Existing END_LOOP markers belong to parent loops of this loop
412 if (MI.getOpcode() == WebAssembly::END_LOOP)
413 AfterSet.insert(&MI);
414#endif
415
416 // Mark the end of the loop (using arbitrary debug location that branched to
417 // the loop end as its location).
Heejin Ahn18c56a02019-02-04 19:13:39 +0000418 InsertPos = getEarliestInsertPos(AfterLoop, BeforeSet, AfterSet);
Derek Schuff10b31352018-03-15 22:06:51 +0000419 DebugLoc EndDL = (*AfterLoop->pred_rbegin())->findBranchDebugLoc();
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000420 MachineInstr *End =
421 BuildMI(*AfterLoop, InsertPos, EndDL, TII.get(WebAssembly::END_LOOP));
422 registerScope(Begin, End);
Dan Gohman8fe7e862015-12-14 22:51:54 +0000423
424 assert((!ScopeTops[AfterLoop->getNumber()] ||
425 ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) &&
Dan Gohman442bfce2016-02-16 16:22:41 +0000426 "With block sorting the outermost loop for a block should be first.");
Dan Gohman8fe7e862015-12-14 22:51:54 +0000427 if (!ScopeTops[AfterLoop->getNumber()])
428 ScopeTops[AfterLoop->getNumber()] = &MBB;
Dan Gohman950a13c2015-09-16 16:51:30 +0000429}
430
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000431void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock &MBB) {
432 if (!MBB.isEHPad())
433 return;
434
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000435 MachineFunction &MF = *MBB.getParent();
436 auto &MDT = getAnalysis<MachineDominatorTree>();
437 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
438 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
439 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
440
441 // Compute the nearest common dominator of all unwind predecessors
442 MachineBasicBlock *Header = nullptr;
443 int MBBNumber = MBB.getNumber();
444 for (auto *Pred : MBB.predecessors()) {
445 if (Pred->getNumber() < MBBNumber) {
446 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
Heejin Ahn18c56a02019-02-04 19:13:39 +0000447 assert(!explicitlyBranchesTo(Pred, &MBB) &&
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000448 "Explicit branch to an EH pad!");
449 }
450 }
451 if (!Header)
452 return;
453
454 // If this try is at the bottom of the function, insert a dummy block at the
455 // end.
456 WebAssemblyException *WE = WEI.getExceptionFor(&MBB);
457 assert(WE);
458 MachineBasicBlock *Bottom = WebAssembly::getBottom(WE);
459
460 auto Iter = std::next(MachineFunction::iterator(Bottom));
461 if (Iter == MF.end()) {
462 MachineBasicBlock *Label = MF.CreateMachineBasicBlock();
463 // Give it a fake predecessor so that AsmPrinter prints its label.
464 Label->addSuccessor(Label);
465 MF.push_back(Label);
466 Iter = std::next(MachineFunction::iterator(Bottom));
467 }
Heejin Ahn20cf0742019-02-24 08:30:06 +0000468 MachineBasicBlock *Cont = &*Iter;
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000469
Heejin Ahn20cf0742019-02-24 08:30:06 +0000470 assert(Cont != &MF.front());
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000471 MachineBasicBlock *LayoutPred =
Heejin Ahn20cf0742019-02-24 08:30:06 +0000472 &*std::prev(MachineFunction::iterator(Cont));
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000473
474 // If the nearest common dominator is inside a more deeply nested context,
475 // walk out to the nearest scope which isn't more deeply nested.
476 for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) {
477 if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) {
478 if (ScopeTop->getNumber() > Header->getNumber()) {
479 // Skip over an intervening scope.
480 I = std::next(MachineFunction::iterator(ScopeTop));
481 } else {
482 // We found a scope level at an appropriate depth.
483 Header = ScopeTop;
484 break;
485 }
486 }
487 }
488
489 // Decide where in Header to put the TRY.
490
491 // Instructions that should go before the BLOCK.
492 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
493 // Instructions that should go after the BLOCK.
494 SmallPtrSet<const MachineInstr *, 4> AfterSet;
495 for (const auto &MI : *Header) {
496 // If there is a previously placed LOOP marker and the bottom block of
497 // the loop is above MBB, the LOOP should be after the TRY, because the
498 // loop is nested in this try. Otherwise it should be before the TRY.
499 if (MI.getOpcode() == WebAssembly::LOOP) {
500 if (MBB.getNumber() > Bottom->getNumber())
501 AfterSet.insert(&MI);
502#ifndef NDEBUG
503 else
504 BeforeSet.insert(&MI);
505#endif
506 }
507
508 // All previously inserted TRY markers should be after the TRY because they
509 // are all nested trys.
510 if (MI.getOpcode() == WebAssembly::TRY)
511 AfterSet.insert(&MI);
512
513#ifndef NDEBUG
514 // All END_(LOOP/TRY) markers should be before the TRY.
515 if (MI.getOpcode() == WebAssembly::END_LOOP ||
516 MI.getOpcode() == WebAssembly::END_TRY)
517 BeforeSet.insert(&MI);
518#endif
519
520 // Terminators should go after the TRY.
521 if (MI.isTerminator())
522 AfterSet.insert(&MI);
523 }
524
525 // Local expression tree should go after the TRY.
526 for (auto I = Header->getFirstTerminator(), E = Header->begin(); I != E;
527 --I) {
Yury Delendik409b4392018-10-04 23:31:00 +0000528 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
529 continue;
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000530 if (WebAssembly::isChild(*std::prev(I), MFI))
531 AfterSet.insert(&*std::prev(I));
532 else
533 break;
534 }
535
536 // If Header unwinds to MBB (= Header contains 'invoke'), the try block should
537 // contain the call within it. So the call should go after the TRY. The
538 // exception is when the header's terminator is a rethrow instruction, in
539 // which case that instruction, not a call instruction before it, is gonna
540 // throw.
541 if (MBB.isPredecessor(Header)) {
542 auto TermPos = Header->getFirstTerminator();
Heejin Ahnd6f48782019-01-30 03:21:57 +0000543 if (TermPos == Header->end() ||
544 TermPos->getOpcode() != WebAssembly::RETHROW) {
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000545 for (const auto &MI : reverse(*Header)) {
546 if (MI.isCall()) {
547 AfterSet.insert(&MI);
548 break;
549 }
550 }
551 }
552 }
553
554 // Add the TRY.
Heejin Ahn18c56a02019-02-04 19:13:39 +0000555 auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet);
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000556 MachineInstr *Begin =
557 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
558 TII.get(WebAssembly::TRY))
559 .addImm(int64_t(WebAssembly::ExprType::Void));
560
561 // Decide where in Header to put the END_TRY.
562 BeforeSet.clear();
563 AfterSet.clear();
Heejin Ahn20cf0742019-02-24 08:30:06 +0000564 for (const auto &MI : *Cont) {
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000565#ifndef NDEBUG
566 // END_TRY should precede existing LOOP markers.
567 if (MI.getOpcode() == WebAssembly::LOOP)
568 AfterSet.insert(&MI);
569
570 // All END_TRY markers placed earlier belong to exceptions that contains
571 // this one.
572 if (MI.getOpcode() == WebAssembly::END_TRY)
573 AfterSet.insert(&MI);
574#endif
575
576 // If there is a previously placed END_LOOP marker and its header is after
577 // where TRY marker is, this loop is contained within the 'catch' part, so
578 // the END_TRY marker should go after that. Otherwise, the whole try-catch
579 // is contained within this loop, so the END_TRY should go before that.
580 if (MI.getOpcode() == WebAssembly::END_LOOP) {
581 if (EndToBegin[&MI]->getParent()->getNumber() >= Header->getNumber())
582 BeforeSet.insert(&MI);
583#ifndef NDEBUG
584 else
585 AfterSet.insert(&MI);
586#endif
587 }
588 }
589
590 // Mark the end of the TRY.
Heejin Ahn20cf0742019-02-24 08:30:06 +0000591 InsertPos = getEarliestInsertPos(Cont, BeforeSet, AfterSet);
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000592 MachineInstr *End =
Heejin Ahn20cf0742019-02-24 08:30:06 +0000593 BuildMI(*Cont, InsertPos, Bottom->findBranchDebugLoc(),
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000594 TII.get(WebAssembly::END_TRY));
595 registerTryScope(Begin, End, &MBB);
596
597 // Track the farthest-spanning scope that ends at this point.
Heejin Ahn20cf0742019-02-24 08:30:06 +0000598 int Number = Cont->getNumber();
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000599 if (!ScopeTops[Number] ||
600 ScopeTops[Number]->getNumber() > Header->getNumber())
601 ScopeTops[Number] = Header;
602}
603
Heejin Ahncf699b42019-02-27 00:50:53 +0000604void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) {
605 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
606
607 // When there is an unconditional branch right before a catch instruction and
608 // it branches to the end of end_try marker, we don't need the branch, because
609 // it there is no exception, the control flow transfers to that point anyway.
610 // bb0:
611 // try
612 // ...
613 // br bb2 <- Not necessary
614 // bb1:
615 // catch
616 // ...
617 // bb2:
618 // end
619 for (auto &MBB : MF) {
620 if (!MBB.isEHPad())
621 continue;
622
623 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
624 SmallVector<MachineOperand, 4> Cond;
625 MachineBasicBlock *EHPadLayoutPred =
626 &*std::prev(MachineFunction::iterator(&MBB));
627 MachineBasicBlock *Cont = BeginToEnd[EHPadToTry[&MBB]]->getParent();
628 bool Analyzable = !TII.analyzeBranch(*EHPadLayoutPred, TBB, FBB, Cond);
629 if (Analyzable && ((Cond.empty() && TBB && TBB == Cont) ||
630 (!Cond.empty() && FBB && FBB == Cont)))
631 TII.removeBranch(*EHPadLayoutPred);
632 }
633
634 // When there are block / end_block markers that overlap with try / end_try
635 // markers, and the block and try markers' return types are the same, the
636 // block /end_block markers are not necessary, because try / end_try markers
637 // also can serve as boundaries for branches.
638 // block <- Not necessary
639 // try
640 // ...
641 // catch
642 // ...
643 // end
644 // end <- Not necessary
645 SmallVector<MachineInstr *, 32> ToDelete;
646 for (auto &MBB : MF) {
647 for (auto &MI : MBB) {
648 if (MI.getOpcode() != WebAssembly::TRY)
649 continue;
650
651 MachineInstr *Try = &MI, *EndTry = BeginToEnd[Try];
652 MachineBasicBlock *TryBB = Try->getParent();
653 MachineBasicBlock *Cont = EndTry->getParent();
654 int64_t RetType = Try->getOperand(0).getImm();
655 for (auto B = MachineBasicBlock::iterator(Try),
656 E = std::next(MachineBasicBlock::iterator(EndTry));
657 B != TryBB->begin() && E != Cont->end() &&
658 std::prev(B)->getOpcode() == WebAssembly::BLOCK &&
659 E->getOpcode() == WebAssembly::END_BLOCK &&
660 std::prev(B)->getOperand(0).getImm() == RetType;
661 --B, ++E) {
662 ToDelete.push_back(&*std::prev(B));
663 ToDelete.push_back(&*E);
664 }
665 }
666 }
667 for (auto *MI : ToDelete) {
668 if (MI->getOpcode() == WebAssembly::BLOCK)
669 unregisterScope(MI);
670 MI->eraseFromParent();
671 }
672}
673
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000674static unsigned
Heejin Ahn18c56a02019-02-04 19:13:39 +0000675getDepth(const SmallVectorImpl<const MachineBasicBlock *> &Stack,
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000676 const MachineBasicBlock *MBB) {
677 unsigned Depth = 0;
678 for (auto X : reverse(Stack)) {
679 if (X == MBB)
680 break;
681 ++Depth;
682 }
683 assert(Depth < Stack.size() && "Branch destination should be in scope");
684 return Depth;
685}
686
Dan Gohman2726b882016-10-06 22:29:32 +0000687/// In normal assembly languages, when the end of a function is unreachable,
688/// because the function ends in an infinite loop or a noreturn call or similar,
689/// it isn't necessary to worry about the function return type at the end of
690/// the function, because it's never reached. However, in WebAssembly, blocks
691/// that end at the function end need to have a return type signature that
692/// matches the function signature, even though it's unreachable. This function
693/// checks for such cases and fixes up the signatures.
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000694void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) {
695 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
Dan Gohman2726b882016-10-06 22:29:32 +0000696 assert(MFI.getResults().size() <= 1);
697
698 if (MFI.getResults().empty())
699 return;
700
Heejin Ahn18c56a02019-02-04 19:13:39 +0000701 WebAssembly::ExprType RetType;
Dan Gohman2726b882016-10-06 22:29:32 +0000702 switch (MFI.getResults().front().SimpleTy) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000703 case MVT::i32:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000704 RetType = WebAssembly::ExprType::I32;
Heejin Ahnf208f632018-09-05 01:27:38 +0000705 break;
706 case MVT::i64:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000707 RetType = WebAssembly::ExprType::I64;
Heejin Ahnf208f632018-09-05 01:27:38 +0000708 break;
709 case MVT::f32:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000710 RetType = WebAssembly::ExprType::F32;
Heejin Ahnf208f632018-09-05 01:27:38 +0000711 break;
712 case MVT::f64:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000713 RetType = WebAssembly::ExprType::F64;
Heejin Ahnf208f632018-09-05 01:27:38 +0000714 break;
Derek Schuff2c783852018-08-06 23:16:50 +0000715 case MVT::v16i8:
716 case MVT::v8i16:
717 case MVT::v4i32:
Derek Schuff51ed1312018-08-07 21:24:01 +0000718 case MVT::v2i64:
Derek Schuff2c783852018-08-06 23:16:50 +0000719 case MVT::v4f32:
Derek Schuff51ed1312018-08-07 21:24:01 +0000720 case MVT::v2f64:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000721 RetType = WebAssembly::ExprType::V128;
Derek Schuff2c783852018-08-06 23:16:50 +0000722 break;
Heejin Ahnf208f632018-09-05 01:27:38 +0000723 case MVT::ExceptRef:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000724 RetType = WebAssembly::ExprType::ExceptRef;
Heejin Ahnf208f632018-09-05 01:27:38 +0000725 break;
726 default:
727 llvm_unreachable("unexpected return type");
Dan Gohman2726b882016-10-06 22:29:32 +0000728 }
729
730 for (MachineBasicBlock &MBB : reverse(MF)) {
731 for (MachineInstr &MI : reverse(MBB)) {
Shiva Chen801bf7e2018-05-09 02:42:00 +0000732 if (MI.isPosition() || MI.isDebugInstr())
Dan Gohman2726b882016-10-06 22:29:32 +0000733 continue;
734 if (MI.getOpcode() == WebAssembly::END_BLOCK) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000735 EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType));
Dan Gohman2726b882016-10-06 22:29:32 +0000736 continue;
737 }
738 if (MI.getOpcode() == WebAssembly::END_LOOP) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000739 EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType));
Dan Gohman2726b882016-10-06 22:29:32 +0000740 continue;
741 }
742 // Something other than an `end`. We're done.
743 return;
744 }
745 }
746}
747
Dan Gohmand934cb82017-02-24 23:18:00 +0000748// WebAssembly functions end with an end instruction, as if the function body
749// were a block.
Heejin Ahn18c56a02019-02-04 19:13:39 +0000750static void appendEndToFunction(MachineFunction &MF,
Heejin Ahnf208f632018-09-05 01:27:38 +0000751 const WebAssemblyInstrInfo &TII) {
Derek Schuff10b31352018-03-15 22:06:51 +0000752 BuildMI(MF.back(), MF.back().end(),
753 MF.back().findPrevDebugLoc(MF.back().end()),
Dan Gohmand934cb82017-02-24 23:18:00 +0000754 TII.get(WebAssembly::END_FUNCTION));
755}
756
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000757/// Insert LOOP/TRY/BLOCK markers at appropriate places.
758void WebAssemblyCFGStackify::placeMarkers(MachineFunction &MF) {
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000759 // We allocate one more than the number of blocks in the function to
760 // accommodate for the possible fake block we may insert at the end.
761 ScopeTops.resize(MF.getNumBlockIDs() + 1);
762 // Place the LOOP for MBB if MBB is the header of a loop.
763 for (auto &MBB : MF)
764 placeLoopMarker(MBB);
765 // Place the TRY for MBB if MBB is the EH pad of an exception.
Heejin Ahnd6f48782019-01-30 03:21:57 +0000766 const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo();
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000767 if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm &&
768 MF.getFunction().hasPersonalityFn())
769 for (auto &MBB : MF)
770 placeTryMarker(MBB);
771 // Place the BLOCK for MBB if MBB is branched to from above.
772 for (auto &MBB : MF)
773 placeBlockMarker(MBB);
774}
Dan Gohman8fe7e862015-12-14 22:51:54 +0000775
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000776void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) {
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000777 // Now rewrite references to basic blocks to be depth immediates.
778 SmallVector<const MachineBasicBlock *, 8> Stack;
779 for (auto &MBB : reverse(MF)) {
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000780 for (auto I = MBB.rbegin(), E = MBB.rend(); I != E; ++I) {
781 MachineInstr &MI = *I;
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000782 switch (MI.getOpcode()) {
783 case WebAssembly::BLOCK:
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000784 case WebAssembly::TRY:
785 assert(ScopeTops[Stack.back()->getNumber()]->getNumber() <=
786 MBB.getNumber() &&
787 "Block/try marker should be balanced");
788 Stack.pop_back();
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000789 break;
790
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000791 case WebAssembly::LOOP:
792 assert(Stack.back() == &MBB && "Loop top should be balanced");
793 Stack.pop_back();
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000794 break;
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000795
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000796 case WebAssembly::END_BLOCK:
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000797 case WebAssembly::END_TRY:
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000798 Stack.push_back(&MBB);
799 break;
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000800
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000801 case WebAssembly::END_LOOP:
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000802 Stack.push_back(EndToBegin[&MI]->getParent());
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000803 break;
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000804
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000805 default:
806 if (MI.isTerminator()) {
807 // Rewrite MBB operands to be depth immediates.
808 SmallVector<MachineOperand, 4> Ops(MI.operands());
809 while (MI.getNumOperands() > 0)
810 MI.RemoveOperand(MI.getNumOperands() - 1);
811 for (auto MO : Ops) {
812 if (MO.isMBB())
Heejin Ahn18c56a02019-02-04 19:13:39 +0000813 MO = MachineOperand::CreateImm(getDepth(Stack, MO.getMBB()));
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000814 MI.addOperand(MF, MO);
815 }
816 }
817 break;
818 }
819 }
820 }
821 assert(Stack.empty() && "Control flow should be balanced");
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000822}
Dan Gohman2726b882016-10-06 22:29:32 +0000823
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000824void WebAssemblyCFGStackify::releaseMemory() {
825 ScopeTops.clear();
826 BeginToEnd.clear();
827 EndToBegin.clear();
828 TryToEHPad.clear();
829 EHPadToTry.clear();
Dan Gohman32807932015-11-23 16:19:56 +0000830}
Dan Gohman32807932015-11-23 16:19:56 +0000831
Dan Gohman950a13c2015-09-16 16:51:30 +0000832bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000833 LLVM_DEBUG(dbgs() << "********** CFG Stackifying **********\n"
834 "********** Function: "
835 << MF.getName() << '\n');
Heejin Ahncf699b42019-02-27 00:50:53 +0000836 const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo();
Dan Gohman950a13c2015-09-16 16:51:30 +0000837
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000838 releaseMemory();
839
Dan Gohmane0405332016-10-03 22:43:53 +0000840 // Liveness is not tracked for VALUE_STACK physreg.
Derek Schuff9c3bf312016-01-13 17:10:28 +0000841 MF.getRegInfo().invalidateLiveness();
Dan Gohman950a13c2015-09-16 16:51:30 +0000842
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000843 // Place the BLOCK/LOOP/TRY markers to indicate the beginnings of scopes.
844 placeMarkers(MF);
845
Heejin Ahncf699b42019-02-27 00:50:53 +0000846 if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm &&
847 MF.getFunction().hasPersonalityFn())
848 // Remove unnecessary instructions.
849 removeUnnecessaryInstrs(MF);
850
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000851 // Convert MBB operands in terminators to relative depth immediates.
852 rewriteDepthImmediates(MF);
853
854 // Fix up block/loop/try signatures at the end of the function to conform to
855 // WebAssembly's rules.
856 fixEndsAtEndOfFunction(MF);
857
858 // Add an end instruction at the end of the function body.
859 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
860 if (!MF.getSubtarget<WebAssemblySubtarget>()
861 .getTargetTriple()
862 .isOSBinFormatELF())
Heejin Ahn18c56a02019-02-04 19:13:39 +0000863 appendEndToFunction(MF, TII);
Dan Gohman32807932015-11-23 16:19:56 +0000864
Dan Gohman950a13c2015-09-16 16:51:30 +0000865 return true;
866}