blob: dc0f05c4536b2887e65353eb3f71354611a7d467 [file] [log] [blame]
Heejin Ahn78d19102018-08-21 21:23:07 +00001//===-- WebAssemblyEHRestoreStackPointer.cpp - __stack_pointer restoration ===//
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
Heejin Ahn78d19102018-08-21 21:23:07 +00006//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// After the stack is unwound due to a thrown exception, the __stack_pointer
11/// global can point to an invalid address. This inserts instructions that
12/// restore __stack_pointer global.
13///
14//===----------------------------------------------------------------------===//
15
16#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
17#include "WebAssembly.h"
18#include "WebAssemblySubtarget.h"
19#include "WebAssemblyUtilities.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/MC/MCAsmInfo.h"
22using namespace llvm;
23
24#define DEBUG_TYPE "wasm-eh-restore-stack-pointer"
25
26namespace {
27class WebAssemblyEHRestoreStackPointer final : public MachineFunctionPass {
28public:
29 static char ID; // Pass identification, replacement for typeid
30 WebAssemblyEHRestoreStackPointer() : MachineFunctionPass(ID) {}
31
32 StringRef getPassName() const override {
33 return "WebAssembly Restore Stack Pointer for Exception Handling";
34 }
35
36 void getAnalysisUsage(AnalysisUsage &AU) const override {
37 AU.setPreservesCFG();
38 MachineFunctionPass::getAnalysisUsage(AU);
39 }
40
41 bool runOnMachineFunction(MachineFunction &MF) override;
42};
43} // end anonymous namespace
44
45char WebAssemblyEHRestoreStackPointer::ID = 0;
46INITIALIZE_PASS(WebAssemblyEHRestoreStackPointer, DEBUG_TYPE,
47 "Restore Stack Pointer for Exception Handling", true, false)
48
49FunctionPass *llvm::createWebAssemblyEHRestoreStackPointer() {
50 return new WebAssemblyEHRestoreStackPointer();
51}
52
53bool WebAssemblyEHRestoreStackPointer::runOnMachineFunction(
54 MachineFunction &MF) {
Heejin Ahn569f0902019-01-09 23:05:21 +000055 LLVM_DEBUG(dbgs() << "********** EH Restore Stack Pointer **********\n"
56 "********** Function: "
57 << MF.getName() << '\n');
58
Heejin Ahn78d19102018-08-21 21:23:07 +000059 const auto *FrameLowering = static_cast<const WebAssemblyFrameLowering *>(
60 MF.getSubtarget().getFrameLowering());
61 if (!FrameLowering->needsPrologForEH(MF))
62 return false;
63 bool Changed = false;
64
65 for (auto &MBB : MF) {
66 if (!MBB.isEHPad())
67 continue;
68 Changed = true;
69
70 // Insert __stack_pointer restoring instructions at the beginning of each EH
71 // pad, after the catch instruction. (Catch instructions may have been
72 // reordered, and catch_all instructions have not been inserted yet, but
73 // those cases are handled in LateEHPrepare).
Heejin Ahn972fc352018-08-22 21:13:49 +000074 //
75 // Here it is safe to assume that SP32 holds the latest value of
76 // __stack_pointer, because the only exception for this case is when a
77 // function uses the red zone, but that only happens with leaf functions,
78 // and we don't restore __stack_pointer in leaf functions anyway.
Heejin Ahn78d19102018-08-21 21:23:07 +000079 auto InsertPos = MBB.begin();
80 if (WebAssembly::isCatch(*MBB.begin()))
81 InsertPos++;
82 FrameLowering->writeSPToGlobal(WebAssembly::SP32, MF, MBB, InsertPos,
83 MBB.begin()->getDebugLoc());
84 }
85 return Changed;
86}