When Emscripten EH mixes with Emscripten SjLj, we are not currently
handling some of them correctly. There are three cases:
- The current function calls setjmp and there is an invoke to a function that can either throw or longjmp. In this case, we have to check both for exception and longjmp. We are currently handling this case correctly: https://github.com/llvm/llvm-project/blob/0c0eb76782d5224b8d81a5afbb9a152bcf7c94c7/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp#L1058-L1090 When inserting routines for functions that can longjmp, which we do only for setjmp-calling functions, we check if the function was previously an invoke and handle it correctly.
- The current function does NOT call setjmp and there is an invoke to a function that can either throw or longjmp. Because there is no setjmp call, we haven't been doing any check for functions that can longjmp. But in that case, for invoke, we only check for an exception and if it is not an exception we reset __THREW__ to 0, which can silently swallow the longjmp: https://github.com/llvm/llvm-project/blob/0c0eb76782d5224b8d81a5afbb9a152bcf7c94c7/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp#L70-L80 This CL fixes this.
- The current function calls setjmp and there is no invoke. Because it is not an invoke, we haven't been doing any check for functions that can throw, and only insert longjmp-checking routines for functions that can longjmp. But in that case, if a longjmpable function throws, we only check for a longjmp so if it is not a longjmp we reset __THREW__ to 0, which can silently swallow the exception: https://github.com/llvm/llvm-project/blob/0c0eb76782d5224b8d81a5afbb9a152bcf7c94c7/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp#L156-L169 This CL fixes this.
To do that, this moves around some code, so we register necessary
functions for both EH and SjLj and precompute some data (the set of
functions that contains setjmp) before doing actual EH or SjLj
transformation.
We are using DoSjLj and EnableSjLj for different meanings in the pass. EnableSjLj is true by default in Emscripten setting, but DoSjLj is true only when setjmp or longjmp is really used. This was confusing so I changed it to Enable.