forked from OSchip/llvm-project
[WebAssembly] Add -emscripten-cxx-exceptions-whitelist option
This patch adds -emscripten-cxx-exceptions-whitelist option to WebAssemblyLowerEmscriptenExceptions pass. This options is the list of function names in which Emscripten-style exception handling is enabled. This is to support emscripten's EXCEPTION_CATCHING_WHITELIST which exists because of the performance impact of emscripten's non-zero-cost EH method. Patch by Heejin Ahn Differential Revision: https://reviews.llvm.org/D23292 llvm-svn: 278171
This commit is contained in:
parent
e7c2875dc3
commit
66641322ce
|
@ -109,6 +109,13 @@ using namespace llvm;
|
|||
|
||||
#define DEBUG_TYPE "wasm-lower-em-exceptions"
|
||||
|
||||
static cl::list<std::string>
|
||||
Whitelist("emscripten-cxx-exceptions-whitelist",
|
||||
cl::desc("The list of function names in which Emscripten-style "
|
||||
"exception handling is enabled (see emscripten "
|
||||
"EMSCRIPTEN_CATCHING_WHITELIST options)"),
|
||||
cl::CommaSeparated);
|
||||
|
||||
namespace {
|
||||
class WebAssemblyLowerEmscriptenExceptions final : public ModulePass {
|
||||
const char *getPassName() const override {
|
||||
|
@ -124,6 +131,7 @@ class WebAssemblyLowerEmscriptenExceptions final : public ModulePass {
|
|||
Function *getFindMatchingCatch(Module &M, unsigned NumClauses);
|
||||
|
||||
Function *getInvokeWrapper(Module &M, InvokeInst *II);
|
||||
bool areAllExceptionsAllowed() const { return WhitelistSet.empty(); }
|
||||
|
||||
GlobalVariable *ThrewGV; // __THREW__
|
||||
GlobalVariable *ThrewValueGV; // threwValue
|
||||
|
@ -135,13 +143,17 @@ class WebAssemblyLowerEmscriptenExceptions final : public ModulePass {
|
|||
DenseMap<int, Function *> FindMatchingCatches;
|
||||
// Map of <function signature string, invoke_ wrappers>
|
||||
StringMap<Function *> InvokeWrappers;
|
||||
// Set of whitelisted function names
|
||||
std::set<std::string> WhitelistSet;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
WebAssemblyLowerEmscriptenExceptions()
|
||||
: ModulePass(ID), ThrewGV(nullptr), ThrewValueGV(nullptr),
|
||||
TempRet0GV(nullptr) {}
|
||||
TempRet0GV(nullptr) {
|
||||
WhitelistSet.insert(Whitelist.begin(), Whitelist.end());
|
||||
}
|
||||
bool runOnModule(Module &M) override;
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
@ -332,7 +344,8 @@ bool WebAssemblyLowerEmscriptenExceptions::runOnFunction(Function &F) {
|
|||
bool Changed = false;
|
||||
SmallVector<Instruction *, 64> ToErase;
|
||||
SmallPtrSet<LandingPadInst *, 32> LandingPads;
|
||||
bool AllowExceptions = true; // will later change based on whitelist option
|
||||
bool AllowExceptions =
|
||||
areAllExceptionsAllowed() || WhitelistSet.count(F.getName());
|
||||
|
||||
for (BasicBlock &BB : F) {
|
||||
auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
; RUN: opt < %s -wasm-lower-em-exceptions -emscripten-cxx-exceptions-whitelist=do_catch -S | FileCheck %s
|
||||
|
||||
define void @dont_catch() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
||||
; CHECK-LABEL: @dont_catch(
|
||||
entry:
|
||||
invoke void @foo()
|
||||
to label %invoke.cont unwind label %lpad
|
||||
; CHECK: entry:
|
||||
; CHECK-NEXT: call void @foo()
|
||||
; CHECK-NEXT: br label %invoke.cont
|
||||
|
||||
invoke.cont: ; preds = %entry
|
||||
br label %try.cont
|
||||
|
||||
lpad: ; preds = %entry
|
||||
%0 = landingpad { i8*, i32 }
|
||||
catch i8* null
|
||||
%1 = extractvalue { i8*, i32 } %0, 0
|
||||
%2 = extractvalue { i8*, i32 } %0, 1
|
||||
br label %catch
|
||||
|
||||
catch: ; preds = %lpad
|
||||
%3 = call i8* @__cxa_begin_catch(i8* %1)
|
||||
call void @__cxa_end_catch()
|
||||
br label %try.cont
|
||||
|
||||
try.cont: ; preds = %catch, %invoke.cont
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @do_catch() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
||||
; CHECK-LABEL: @do_catch(
|
||||
entry:
|
||||
invoke void @foo()
|
||||
to label %invoke.cont unwind label %lpad
|
||||
; CHECK: entry:
|
||||
; CHECK-NEXT: store i1 false, i1*
|
||||
; CHECK-NEXT: call void @__invoke_void(void ()* @foo)
|
||||
|
||||
invoke.cont: ; preds = %entry
|
||||
br label %try.cont
|
||||
|
||||
lpad: ; preds = %entry
|
||||
%0 = landingpad { i8*, i32 }
|
||||
catch i8* null
|
||||
%1 = extractvalue { i8*, i32 } %0, 0
|
||||
%2 = extractvalue { i8*, i32 } %0, 1
|
||||
br label %catch
|
||||
|
||||
catch: ; preds = %lpad
|
||||
%3 = call i8* @__cxa_begin_catch(i8* %1)
|
||||
call void @__cxa_end_catch()
|
||||
br label %try.cont
|
||||
|
||||
try.cont: ; preds = %catch, %invoke.cont
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @foo()
|
||||
declare i32 @__gxx_personality_v0(...)
|
||||
declare i8* @__cxa_begin_catch(i8*)
|
||||
declare void @__cxa_end_catch()
|
Loading…
Reference in New Issue