Summary: This lowers exception catching-related instructions: 1. Lowers `wasm.catch` intrinsic to `catch` instruction 2. Removes `catchpad` and `cleanuppad` instructions; they are not necessary after isel phase. (`MachineBasicBlock::isEHFuncletEntry()` or `MachineBasicBlock::isEHPad()` can be used instead.) 3. Lowers `catchret` and `cleanupret` instructions to pseudo `catchret` and `cleanupret` instructions in isel, which will be replaced with other instructions in `WebAssemblyExceptionPrepare` pass. 4. Adds 'WebAssemblyExceptionPrepare` pass, which is for running various transformation for EH. Currently this pass only replaces `catchret` and `cleanupret` instructions into appropriate wasm instructions to make this patch successfully run until the end. Currently this does not handle lowering of intrinsics related to LSDA info generation (`wasm.landingpad.index` and `wasm.lsda`), because they cannot be tested without implementing `EHStreamer`'s wasm-specific handlers. They are marked as TODO, which is needed to make isel pass. Also this does not generate `try` and `end_try` markers yet, which will be handled in later patches. This patch is based on the first wasm EH proposal. (https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md) Reviewers: dschuff, majnemer Subscribers: jfb, sbc100, jgravelle-google, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D44090 llvm-svn: 333705
89 lines
2.6 KiB
C++
89 lines
2.6 KiB
C++
//=== WebAssemblyExceptionPrepare.cpp - WebAssembly Exception Preparation -===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// \brief Does various transformations for exception handling.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
|
|
#include "WebAssembly.h"
|
|
#include "WebAssemblySubtarget.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "wasm-exception-prepare"
|
|
|
|
namespace {
|
|
class WebAssemblyExceptionPrepare final : public MachineFunctionPass {
|
|
StringRef getPassName() const override {
|
|
return "WebAssembly Prepare Exception";
|
|
}
|
|
|
|
bool runOnMachineFunction(MachineFunction &MF) override;
|
|
|
|
bool replaceFuncletReturns(MachineFunction &MF);
|
|
|
|
public:
|
|
static char ID; // Pass identification, replacement for typeid
|
|
WebAssemblyExceptionPrepare() : MachineFunctionPass(ID) {}
|
|
};
|
|
} // end anonymous namespace
|
|
|
|
char WebAssemblyExceptionPrepare::ID = 0;
|
|
INITIALIZE_PASS(WebAssemblyExceptionPrepare, DEBUG_TYPE,
|
|
"WebAssembly Exception Preparation", false, false)
|
|
|
|
FunctionPass *llvm::createWebAssemblyExceptionPrepare() {
|
|
return new WebAssemblyExceptionPrepare();
|
|
}
|
|
|
|
bool WebAssemblyExceptionPrepare::runOnMachineFunction(MachineFunction &MF) {
|
|
bool Changed = false;
|
|
if (!MF.getFunction().hasPersonalityFn())
|
|
return false;
|
|
Changed |= replaceFuncletReturns(MF);
|
|
// TODO More transformations will be added
|
|
return Changed;
|
|
}
|
|
|
|
bool WebAssemblyExceptionPrepare::replaceFuncletReturns(MachineFunction &MF) {
|
|
bool Changed = false;
|
|
const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
|
|
|
|
for (auto &MBB : MF) {
|
|
auto Pos = MBB.getFirstTerminator();
|
|
if (Pos == MBB.end())
|
|
continue;
|
|
MachineInstr *TI = &*Pos;
|
|
|
|
switch (TI->getOpcode()) {
|
|
case WebAssembly::CATCHRET: {
|
|
// Replace a catchret with a branch
|
|
MachineBasicBlock *TBB = TI->getOperand(0).getMBB();
|
|
if (!MBB.isLayoutSuccessor(TBB))
|
|
BuildMI(MBB, TI, TI->getDebugLoc(), TII.get(WebAssembly::BR))
|
|
.addMBB(TBB);
|
|
TI->eraseFromParent();
|
|
Changed = true;
|
|
break;
|
|
}
|
|
case WebAssembly::CLEANUPRET: {
|
|
// Replace a cleanupret with a rethrow
|
|
BuildMI(MBB, TI, TI->getDebugLoc(), TII.get(WebAssembly::RETHROW))
|
|
.addImm(0);
|
|
TI->eraseFromParent();
|
|
Changed = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return Changed;
|
|
}
|