Open juj opened 11 months ago
When building with Wasm exception handling -fwasm-exceptions
, should any compiled code that is using setjmp/longjmp ever emit a dependency to emscripten_longjmp
, or is emscripten_longjmp
strictly a Emscripten/JS exceptions mode feature?
I am seeing a .o
file that I built with -fwasm-exceptions
to have U emscripten_longjmp
dependency, and when generating the final .html file, that is erroring as undefined, and I am wondering where things are going wrong here.
Answering myself, I believe that according to emscripten\main\system\lib\compiler-rt\emscripten_setjmp.c
, there's
#if !defined(__USING_WASM_SJLJ__)
#include "emscripten_internal.h"
void emscripten_longjmp(uintptr_t env, int val) {
setThrew(env, val);
_emscripten_throw_longjmp();
}
#endif
suggesting that emscripten_longjmp
is supposed to be strictly an Emscripten EH thing, and not present when building with -fwasm-exceptions
?
Still for some odd reason I am getting emscripten_longjmp
dependency into the build even when I have -fwasm-exceptions
(at both compile and link time... very odd)
Now I see the issue.
Passing emcc code_using_longjmp.c -c -o a.o -fwasm-exceptions -fno-exceptions
will result in emitting Emscripten longjmp instead of Wasm longjmp, and then as result the link with emcc a.o -o a.js -fwasm-exceptions
will fail with emscripten_longjmp
being missing.
Are -fwasm-exceptions
and -fno-exceptions
intended to be mutually exclusive flags?
Are -fwasm-exceptions and -fno-exceptions intended to be mutually exclusive flags?
That surprises me, but I'm not sure. @aheejin ?
Sorry for the delayed reply.
It is unclear if wasm and native exception handling could be mixed (probably not?),
I don't think they can.
though the above error message does not immediately make it clear to the user why they are getting that error. (imagine a large project, where one or more of hundreds of built files missed the
-fwasm-exceptions
compile flag)
We error out when two conflicting flags are given at the same time: https://github.com/emscripten-core/emscripten/blob/ac8d9f0a53b2e6a3fdb7db92371fd702c0598613/emcc.py#L1683-L1684 But yeah, we don't error out in the cases like you described, where each object file is compiled with Emscripten EH and then linked with Wasm EH. To give a helpful error message on this kind of case I guess we need a separate phase to check whether each undefined symbol belongs to the generated symbols with one of the EH schemes and then if it violates the current EH flag given to the linker... which doesn't sound simple.
When building with Wasm exception handling
-fwasm-exceptions
, should any compiled code that is using setjmp/longjmp ever emit a dependency toemscripten_longjmp
, or isemscripten_longjmp
strictly a Emscripten/JS exceptions mode feature?
It is strictly a Emscripten/JS mode feature.
I am seeing a
.o
file that I built with-fwasm-exceptions
to haveU emscripten_longjmp
dependency, and when generating the final .html file, that is erroring as undefined, and I am wondering where things are going wrong here.
I can think of one possibility; it might be using Wasm EH with Emscripten SjLj. Now we default SjLj mode to that of EH mode, so if you just use -fwasm-exceptions
and nothing else, you get to use Wasm EH & Wasm SjLj. But that was only after #18692, after Feb 2023, so object files built before that with -fwasm-exceptions
could use Wasm EH with Emscripten SjLj. Even after Feb 2023, if you explicitly specify the combination using -fwasm-exceptions -sSUPPORT_LONGJMP=emscripten
, you can be using these two at the same time.
I'm writing as I'm reading your comments in order, and just saw the -fno-exceptions
thing. Will continue on that after investigating.
Passing
emcc code_using_longjmp.c -c -o a.o -fwasm-exceptions -fno-exceptions
will result in emitting Emscripten longjmp instead of Wasm longjmp, and then as result the link withemcc a.o -o a.js -fwasm-exceptions
will fail withemscripten_longjmp
being missing.Are
-fwasm-exceptions
and-fno-exceptions
intended to be mutually exclusive flags?
I think what's happening here is emcc just passes these flags verbatim to clang, and in clang the last flag takes effect when conflicting flags are given. So -fwasm-exceptions -fno-exceptions
is equivalent to -fno-exceptions
, and -fno-exceptions -fwasm-exceptions
is equivalent to -fwasm-exceptions
. And with -fno-exceptions
, with no EH mode to defualt to, Emscripten by default chooses Emscripten EH. That's why emscripten_longjmp
ends up there.
Not sure whether we should error out -fwasm-exceptions -fno-exceptions
or vice versa. Clang's convention for this situation is to use the last one, and I think it is good if emcc has the same convention.
Not sure whether we should error out
-fwasm-exceptions -fno-exceptions
or vice versa. Clang's convention for this situation is to use the last one, and I think it is good if emcc has the same convention.
That actually seems like it might be useful to specify those two options together. For example, if I want to use wasm-exceptions for SJLJ but I want to fully disable C++ exception handling.
Not sure whether we should error out
-fwasm-exceptions -fno-exceptions
or vice versa. Clang's convention for this situation is to use the last one, and I think it is good if emcc has the same convention.That actually seems like it might be useful to specify those two options together. For example, if I want to use wasm-exceptions for SJLJ but I want to fully disable C++ exception handling.
But it doesn't work that way currently. Clang just takes the last one if the two flags are given together. (The same with -fexceptions -fno-exceptions
. -fwasm-exceptions
are just one of those family) If we give the combination another meaning that can be confusing because the behavior would be different from that of clang.
So how you currently disable C++ exceptions while opting into wasm exceptions for SJLJ? If thats not possible today we should find a way to allow it.
You can use -sSUPPORT_LONGJMP=wasm
to do that.
a.cpp
main.cpp
produces
It is unclear if wasm and native exception handling could be mixed (probably not?), though the above error message does not immediately make it clear to the user why they are getting that error. (imagine a large project, where one or more of hundreds of built files missed the
-fwasm-exceptions
compile flag)