[WebAssembly] Forbid use of EM_ASM with setjmp/longjmp

Summary:
We tried to support EM_ASM with setjmp/longjmp in binaryen. But with dynamic
linking thrown into the mix, the code is no longer understandable and cannot
be maintained. We also discovered more bugs in the EM_ASM handling code.

To ensure maintainability and correctness of the binaryen code, EM_ASM will
no longer be supported with setjmp/longjmp. This is probably fine since the
support was added recently and haven't be published.

Reviewers: tlively, sbc100, jgravelle-google, kripken

Reviewed By: tlively, kripken

Subscribers: dschuff, hiraditya, aheejin, sunfish, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D66356

llvm-svn: 369137
This commit is contained in:
Guanzhong Chen 2019-08-16 18:21:08 +00:00
parent 63b78b678b
commit b1cb9fd1aa
1 changed files with 24 additions and 0 deletions

View File

@ -274,6 +274,7 @@ class WebAssemblyLowerEmscriptenEHSjLj final : public ModulePass {
bool areAllExceptionsAllowed() const { return EHWhitelistSet.empty(); } bool areAllExceptionsAllowed() const { return EHWhitelistSet.empty(); }
bool canLongjmp(Module &M, const Value *Callee) const; bool canLongjmp(Module &M, const Value *Callee) const;
bool isEmAsmCall(Module &M, const Value *Callee) const;
void rebuildSSA(Function &F); void rebuildSSA(Function &F);
@ -537,6 +538,23 @@ bool WebAssemblyLowerEmscriptenEHSjLj::canLongjmp(Module &M,
return true; return true;
} }
bool WebAssemblyLowerEmscriptenEHSjLj::isEmAsmCall(Module &M,
const Value *Callee) const {
// This is an exhaustive list from Emscripten's <emscripten/em_asm.h>.
Function *EmAsmConstIntF = M.getFunction("emscripten_asm_const_int");
Function *EmAsmConstDoubleF = M.getFunction("emscripten_asm_const_double");
Function *EmAsmConstIntSyncMainF =
M.getFunction("emscripten_asm_const_int_sync_on_main_thread");
Function *EmAsmConstDoubleSyncMainF =
M.getFunction("emscripten_asm_const_double_sync_on_main_thread");
Function *EmAsmConstAsyncMainF =
M.getFunction("emscripten_asm_const_async_on_main_thread");
return Callee == EmAsmConstIntF || Callee == EmAsmConstDoubleF ||
Callee == EmAsmConstIntSyncMainF ||
Callee == EmAsmConstDoubleSyncMainF || Callee == EmAsmConstAsyncMainF;
}
// Generate testSetjmp function call seqence with preamble and postamble. // Generate testSetjmp function call seqence with preamble and postamble.
// The code this generates is equivalent to the following JavaScript code: // The code this generates is equivalent to the following JavaScript code:
// if (%__THREW__.val != 0 & threwValue != 0) { // if (%__THREW__.val != 0 & threwValue != 0) {
@ -983,6 +1001,12 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) {
const Value *Callee = CI->getCalledValue(); const Value *Callee = CI->getCalledValue();
if (!canLongjmp(M, Callee)) if (!canLongjmp(M, Callee))
continue; continue;
if (isEmAsmCall(M, Callee))
report_fatal_error("Cannot use EM_ASM* alongside setjmp/longjmp in " +
F.getName() +
". Please consider using EM_JS, or move the "
"EM_ASM into another function.",
false);
Value *Threw = nullptr; Value *Threw = nullptr;
BasicBlock *Tail; BasicBlock *Tail;