Line data Source code
1 : //===-- 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"
23 : using namespace llvm;
24 :
25 : #define DEBUG_TYPE "wasm-eh-restore-stack-pointer"
26 :
27 : namespace {
28 : class WebAssemblyEHRestoreStackPointer final : public MachineFunctionPass {
29 : public:
30 : static char ID; // Pass identification, replacement for typeid
31 305 : WebAssemblyEHRestoreStackPointer() : MachineFunctionPass(ID) {}
32 :
33 305 : StringRef getPassName() const override {
34 305 : return "WebAssembly Restore Stack Pointer for Exception Handling";
35 : }
36 :
37 305 : void getAnalysisUsage(AnalysisUsage &AU) const override {
38 305 : AU.setPreservesCFG();
39 305 : MachineFunctionPass::getAnalysisUsage(AU);
40 305 : }
41 :
42 : bool runOnMachineFunction(MachineFunction &MF) override;
43 : };
44 : } // end anonymous namespace
45 :
46 : char WebAssemblyEHRestoreStackPointer::ID = 0;
47 199030 : INITIALIZE_PASS(WebAssemblyEHRestoreStackPointer, DEBUG_TYPE,
48 : "Restore Stack Pointer for Exception Handling", true, false)
49 :
50 305 : FunctionPass *llvm::createWebAssemblyEHRestoreStackPointer() {
51 305 : return new WebAssemblyEHRestoreStackPointer();
52 : }
53 :
54 2983 : bool WebAssemblyEHRestoreStackPointer::runOnMachineFunction(
55 : MachineFunction &MF) {
56 : const auto *FrameLowering = static_cast<const WebAssemblyFrameLowering *>(
57 2983 : MF.getSubtarget().getFrameLowering());
58 2983 : if (!FrameLowering->needsPrologForEH(MF))
59 : return false;
60 : bool Changed = false;
61 :
62 67 : for (auto &MBB : MF) {
63 59 : if (!MBB.isEHPad())
64 41 : 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 : //
72 : // Here it is safe to assume that SP32 holds the latest value of
73 : // __stack_pointer, because the only exception for this case is when a
74 : // function uses the red zone, but that only happens with leaf functions,
75 : // and we don't restore __stack_pointer in leaf functions anyway.
76 18 : auto InsertPos = MBB.begin();
77 18 : if (WebAssembly::isCatch(*MBB.begin()))
78 : InsertPos++;
79 18 : FrameLowering->writeSPToGlobal(WebAssembly::SP32, MF, MBB, InsertPos,
80 : MBB.begin()->getDebugLoc());
81 : }
82 : return Changed;
83 : }
|