blob: 244fb84d0b3621dde0ea6376159a9d8ee7b8d4db [file] [log] [blame]
Heejin Ahn78d19102018-08-21 21:23:07 +00001//===-- WebAssemblyEHRestoreStackPointer.cpp - __stack_pointer restoration ===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// After the stack is unwound due to a thrown exception, the __stack_pointer
12/// global can point to an invalid address. This inserts instructions that
13/// restore __stack_pointer global.
14///
15//===----------------------------------------------------------------------===//
16
17#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
18#include "WebAssembly.h"
19#include "WebAssemblySubtarget.h"
20#include "WebAssemblyUtilities.h"
21#include "llvm/CodeGen/MachineFrameInfo.h"
22#include "llvm/MC/MCAsmInfo.h"
23using namespace llvm;
24
25#define DEBUG_TYPE "wasm-eh-restore-stack-pointer"
26
27namespace {
28class WebAssemblyEHRestoreStackPointer final : public MachineFunctionPass {
29public:
30 static char ID; // Pass identification, replacement for typeid
31 WebAssemblyEHRestoreStackPointer() : MachineFunctionPass(ID) {}
32
33 StringRef getPassName() const override {
34 return "WebAssembly Restore Stack Pointer for Exception Handling";
35 }
36
37 void getAnalysisUsage(AnalysisUsage &AU) const override {
38 AU.setPreservesCFG();
39 MachineFunctionPass::getAnalysisUsage(AU);
40 }
41
42 bool runOnMachineFunction(MachineFunction &MF) override;
43};
44} // end anonymous namespace
45
46char WebAssemblyEHRestoreStackPointer::ID = 0;
47INITIALIZE_PASS(WebAssemblyEHRestoreStackPointer, DEBUG_TYPE,
48 "Restore Stack Pointer for Exception Handling", true, false)
49
50FunctionPass *llvm::createWebAssemblyEHRestoreStackPointer() {
51 return new WebAssemblyEHRestoreStackPointer();
52}
53
54bool WebAssemblyEHRestoreStackPointer::runOnMachineFunction(
55 MachineFunction &MF) {
56 const auto *FrameLowering = static_cast<const WebAssemblyFrameLowering *>(
57 MF.getSubtarget().getFrameLowering());
58 if (!FrameLowering->needsPrologForEH(MF))
59 return false;
60 bool Changed = false;
61
62 for (auto &MBB : MF) {
63 if (!MBB.isEHPad())
64 continue;
65 Changed = true;
66
67 // Insert __stack_pointer restoring instructions at the beginning of each EH
68 // pad, after the catch instruction. (Catch instructions may have been
69 // reordered, and catch_all instructions have not been inserted yet, but
70 // those cases are handled in LateEHPrepare).
71 auto InsertPos = MBB.begin();
72 if (WebAssembly::isCatch(*MBB.begin()))
73 InsertPos++;
74 FrameLowering->writeSPToGlobal(WebAssembly::SP32, MF, MBB, InsertPos,
75 MBB.begin()->getDebugLoc());
76 }
77 return Changed;
78}