Index: lib/Target/WebAssembly/CMakeLists.txt =================================================================== --- lib/Target/WebAssembly/CMakeLists.txt +++ lib/Target/WebAssembly/CMakeLists.txt @@ -21,7 +21,6 @@ WebAssemblyCFGSort.cpp WebAssemblyDebugValueManager.cpp WebAssemblyLateEHPrepare.cpp - WebAssemblyEHRestoreStackPointer.cpp WebAssemblyExceptionInfo.cpp WebAssemblyExplicitLocals.cpp WebAssemblyFastISel.cpp Index: lib/Target/WebAssembly/WebAssembly.h =================================================================== --- lib/Target/WebAssembly/WebAssembly.h +++ lib/Target/WebAssembly/WebAssembly.h @@ -38,7 +38,6 @@ FunctionPass *createWebAssemblySetP2AlignOperands(); // Late passes. -FunctionPass *createWebAssemblyEHRestoreStackPointer(); FunctionPass *createWebAssemblyReplacePhysRegs(); FunctionPass *createWebAssemblyPrepareForLiveIntervals(); FunctionPass *createWebAssemblyOptimizeLiveIntervals(); @@ -63,7 +62,6 @@ void initializeOptimizeReturnedPass(PassRegistry &); void initializeWebAssemblyArgumentMovePass(PassRegistry &); void initializeWebAssemblySetP2AlignOperandsPass(PassRegistry &); -void initializeWebAssemblyEHRestoreStackPointerPass(PassRegistry &); void initializeWebAssemblyReplacePhysRegsPass(PassRegistry &); void initializeWebAssemblyPrepareForLiveIntervalsPass(PassRegistry &); void initializeWebAssemblyOptimizeLiveIntervalsPass(PassRegistry &); Index: lib/Target/WebAssembly/WebAssemblyEHRestoreStackPointer.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyEHRestoreStackPointer.cpp +++ /dev/null @@ -1,86 +0,0 @@ -//===-- WebAssemblyEHRestoreStackPointer.cpp - __stack_pointer restoration ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// After the stack is unwound due to a thrown exception, the __stack_pointer -/// global can point to an invalid address. This inserts instructions that -/// restore __stack_pointer global. -/// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" -#include "WebAssembly.h" -#include "WebAssemblySubtarget.h" -#include "WebAssemblyUtilities.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/MC/MCAsmInfo.h" -using namespace llvm; - -#define DEBUG_TYPE "wasm-eh-restore-stack-pointer" - -namespace { -class WebAssemblyEHRestoreStackPointer final : public MachineFunctionPass { -public: - static char ID; // Pass identification, replacement for typeid - WebAssemblyEHRestoreStackPointer() : MachineFunctionPass(ID) {} - - StringRef getPassName() const override { - return "WebAssembly Restore Stack Pointer for Exception Handling"; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesCFG(); - MachineFunctionPass::getAnalysisUsage(AU); - } - - bool runOnMachineFunction(MachineFunction &MF) override; -}; -} // end anonymous namespace - -char WebAssemblyEHRestoreStackPointer::ID = 0; -INITIALIZE_PASS(WebAssemblyEHRestoreStackPointer, DEBUG_TYPE, - "Restore Stack Pointer for Exception Handling", true, false) - -FunctionPass *llvm::createWebAssemblyEHRestoreStackPointer() { - return new WebAssemblyEHRestoreStackPointer(); -} - -bool WebAssemblyEHRestoreStackPointer::runOnMachineFunction( - MachineFunction &MF) { - LLVM_DEBUG(dbgs() << "********** EH Restore Stack Pointer **********\n" - "********** Function: " - << MF.getName() << '\n'); - - const auto *FrameLowering = static_cast( - MF.getSubtarget().getFrameLowering()); - if (!FrameLowering->needsPrologForEH(MF)) - return false; - bool Changed = false; - - for (auto &MBB : MF) { - if (!MBB.isEHPad()) - continue; - Changed = true; - - // Insert __stack_pointer restoring instructions at the beginning of each EH - // pad, after the catch instruction. (Catch instructions may have been - // reordered, and catch_all instructions have not been inserted yet, but - // those cases are handled in LateEHPrepare). - // - // Here it is safe to assume that SP32 holds the latest value of - // __stack_pointer, because the only exception for this case is when a - // function uses the red zone, but that only happens with leaf functions, - // and we don't restore __stack_pointer in leaf functions anyway. - auto InsertPos = MBB.begin(); - if (MBB.begin()->getOpcode() == WebAssembly::CATCH) - InsertPos++; - FrameLowering->writeSPToGlobal(WebAssembly::SP32, MF, MBB, InsertPos, - MBB.begin()->getDebugLoc()); - } - return Changed; -} Index: lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp +++ lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp @@ -34,6 +34,7 @@ bool replaceFuncletReturns(MachineFunction &MF); bool addCatches(MachineFunction &MF); bool addExceptionExtraction(MachineFunction &MF); + bool restoreStackPointer(MachineFunction &MF); public: static char ID; // Pass identification, replacement for typeid @@ -113,6 +114,7 @@ Changed |= replaceFuncletReturns(MF); Changed |= addCatches(MF); Changed |= addExceptionExtraction(MF); + Changed |= restoreStackPointer(MF); return Changed; } @@ -330,3 +332,33 @@ return true; } + +// After the stack is unwound due to a thrown exception, the __stack_pointer +// global can point to an invalid address. This inserts instructions that +// restore __stack_pointer global. +bool WebAssemblyLateEHPrepare::restoreStackPointer(MachineFunction &MF) { + const auto *FrameLowering = static_cast( + MF.getSubtarget().getFrameLowering()); + if (!FrameLowering->needsPrologForEH(MF)) + return false; + bool Changed = false; + + for (auto &MBB : MF) { + if (!MBB.isEHPad()) + continue; + Changed = true; + + // Insert __stack_pointer restoring instructions at the beginning of each EH + // pad, after the catch instruction. Here it is safe to assume that SP32 + // holds the latest value of __stack_pointer, because the only exception for + // this case is when a function uses the red zone, but that only happens + // with leaf functions, and we don't restore __stack_pointer in leaf + // functions anyway. + auto InsertPos = MBB.begin(); + if (MBB.begin()->getOpcode() == WebAssembly::CATCH) + InsertPos++; + FrameLowering->writeSPToGlobal(WebAssembly::SP32, MF, MBB, InsertPos, + MBB.begin()->getDebugLoc()); + } + return Changed; +} Index: lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -57,7 +57,6 @@ initializeOptimizeReturnedPass(PR); initializeWebAssemblyArgumentMovePass(PR); initializeWebAssemblySetP2AlignOperandsPass(PR); - initializeWebAssemblyEHRestoreStackPointerPass(PR); initializeWebAssemblyReplacePhysRegsPass(PR); initializeWebAssemblyPrepareForLiveIntervalsPass(PR); initializeWebAssemblyOptimizeLiveIntervalsPass(PR); @@ -284,14 +283,6 @@ void WebAssemblyPassConfig::addPreEmitPass() { TargetPassConfig::addPreEmitPass(); - // Restore __stack_pointer global after an exception is thrown. - addPass(createWebAssemblyEHRestoreStackPointer()); - - // Now that we have a prologue and epilogue and all frame indices are - // rewritten, eliminate SP and FP. This allows them to be stackified, - // colored, and numbered with the rest of the registers. - addPass(createWebAssemblyReplacePhysRegs()); - // Rewrite pseudo call_indirect instructions as real instructions. // This needs to run before register stackification, because we change the // order of the arguments. @@ -304,6 +295,11 @@ // Every CFG-changing optimizations should come before this. addPass(createWebAssemblyLateEHPrepare()); + // Now that we have a prologue and epilogue and all frame indices are + // rewritten, eliminate SP and FP. This allows them to be stackified, + // colored, and numbered with the rest of the registers. + addPass(createWebAssemblyReplacePhysRegs()); + // Preparations and optimizations related to register stackification. if (getOptLevel() != CodeGenOpt::None) { // LiveIntervals isn't commonly run this late. Re-establish preconditions. Index: test/CodeGen/WebAssembly/exception.ll =================================================================== --- test/CodeGen/WebAssembly/exception.ll +++ test/CodeGen/WebAssembly/exception.ll @@ -30,12 +30,12 @@ ; CHECK: try ; CHECK: call foo@FUNCTION ; CHECK: catch $[[EXCEPT_REF:[0-9]+]]= +; CHECK: global.set __stack_pointer@GLOBAL ; CHECK: block i32 ; CHECK: br_on_exn 0, __cpp_exception@EVENT, $[[EXCEPT_REF]] ; CHECK: rethrow ; CHECK: end_block ; CHECK: extract_exception $[[EXN:[0-9]+]]= -; CHECK: global.set __stack_pointer@GLOBAL ; CHECK-DAG: i32.store __wasm_lpad_context ; CHECK-DAG: i32.store __wasm_lpad_context+4 ; CHECK: i32.call $drop=, _Unwind_CallPersonality@FUNCTION, $[[EXN]]