blob: c86260ba408c552c1299e813fefdbe71863dfcce [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) {
Heejin Ahn569f0902019-01-09 23:05:21 +000056 LLVM_DEBUG(dbgs() << "********** EH Restore Stack Pointer **********\n"
57 "********** Function: "
58 << MF.getName() << '\n');
59
Heejin Ahn78d19102018-08-21 21:23:07 +000060 const auto *FrameLowering = static_cast<const WebAssemblyFrameLowering *>(
61 MF.getSubtarget().getFrameLowering());
62 if (!FrameLowering->needsPrologForEH(MF))
63 return false;
64 bool Changed = false;
65
66 for (auto &MBB : MF) {
67 if (!MBB.isEHPad())
68 continue;
69 Changed = true;
70
71 // Insert __stack_pointer restoring instructions at the beginning of each EH
72 // pad, after the catch instruction. (Catch instructions may have been
73 // reordered, and catch_all instructions have not been inserted yet, but
74 // those cases are handled in LateEHPrepare).
Heejin Ahn972fc352018-08-22 21:13:49 +000075 //
76 // Here it is safe to assume that SP32 holds the latest value of
77 // __stack_pointer, because the only exception for this case is when a
78 // function uses the red zone, but that only happens with leaf functions,
79 // and we don't restore __stack_pointer in leaf functions anyway.
Heejin Ahn78d19102018-08-21 21:23:07 +000080 auto InsertPos = MBB.begin();
81 if (WebAssembly::isCatch(*MBB.begin()))
82 InsertPos++;
83 FrameLowering->writeSPToGlobal(WebAssembly::SP32, MF, MBB, InsertPos,
84 MBB.begin()->getDebugLoc());
85 }
86 return Changed;
87}