-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[wasm][wasm-exceptions][c++] Destructors called too early when throwing call is in inline assembly #65116
Comments
@llvm/issue-subscribers-backend-webassembly |
Note that using |
Actually I'm not sure this is wasm-specific. I don't see a way with either clang or gcc to write x86-64 inline asm that calls a C++ function that may throw and have that be evident to the C++ compiler. I would believe "this isn't possible"/"don't do that"/"put the inline asm function in a separate translation unit" as possible resolutions. Feel free to close if that's the case. |
Why should the call to
I don't think it's wasm specific either. This happens within the common passes in the middle end. And So yeah I don't think only By the way I'm curious, why are you doing this in inline assembly? What's the usecase for this that cannot be done in C++? |
the The same example is problematic if you remove all of the try/catch_all/rethrow stuff in
Everything I'm saying is also true about Here's a full example for linux x64 https://github.com/lambdageek/llvm-65116 output: leksey@buran:~/hacking/inline-asm$ ./exampleWorks
in foo 1 times
in foo 2 times
caught something: throwingFunc called
GOOD: there were 2 calls to countCalls()
aleksey@buran:~/hacking/inline-asm$ ./exampleNoDtor
in foo 1 times
caught something: throwingFunc called
BAD: there were 1 calls to countCalls(), expected 2 the only difference is whether the call in I agree this is a hard problem as I don't think gcc or clang really look at the content of
Well so my dayjob is to work on a language runtime that runs on WASM. One of the things we're investigating is using the wasm exceptions mechanism for our exceptions. So we would be using a tag other than I think in reality we'd probably just write some .wat directly (so from the point of view of clang it would be like my TL;DR - this isn't a blocking issue for me. and "this is not supported; don't do it like that" is a perfectly reasonable answer. |
I don't understand. Yes, I haven't checked your another example yet; I think I need to understand your thoughts on this first.
Oh, can I ask what runtime is this? Also if you are thinking about implementing EH, please see WebAssembly/exception-handling#280 that we are planning some changes in the spec.
Custom tags should work. We currently use 0 and 1 for C++ exceptions and C longjmps respectively so other numbers should be fine. But if you really want to do some low level experiments, I recommend using
I generally would not recommend using inline assembly unless it is absolutely unavoidable, more so if you use control flow instructions like |
I'm not sure we're talking about the same thing. Suppose
Yes, if
I agree
Yes I agree with this also.
It should not. The body of But the body of Here's what you get for int
baz(){
int x = 0;
try {
x = 1 + bar ();
} catch (...) {
throw;
}
return x;
}
int square(int num) {
X x{};
return baz();
} We get
Note there's two places that call Now compare with what happens if int
baz(){
int x = 0;
__asm volatile(
"try i32; "
"call _bar;"
"catch_all;"
" rethrow 0;"
" "
"end_try;"
"i32.const 1;"
"i32.add;"
"local.set %0;"
: "=r"(x)
);
return x;
}
int square(int num) {
X x{}; // call to foo() happens here
return baz();
// expected the call to foo to happen after baz returns
} In this case we get
Note that the code for Does that make sense? What matters is the code generated for
It's Mono's "jiterpreter". Currently we just piggyback on C++ exceptions - the generated code is called from a caller that has a C++ try/catch, and when the generated code needs to throw it invokes a C++ helper that throws a C++ exception. But I was curious if we could use a separate tag. (We would like to avoid the C++ wrapper try/catch and to generate our own try/catchall clauses into the JITed module, and it would be slightly cleaner if we didn't have to ask Emscripten to export the cpp_exception tag and if we just used our own.)
Yep, we're keeping an eye on the spec changes. Thanks for the heads up. |
Oh sorry, yeah now I understand what you're saying. Yes it's weird that |
Repro: https://godbolt.org/z/8W8Eb9nr3
When I compile this with
-O -fexceptions -fwasm-exceptions
I expect the destructor forx
to be called afterbaz()
returns (or when we're unwinding because it throws). Indeed that is the case if you change#if 1
to#if 0
and compile the C++ version of the code. On the other hand when the exception is in the inline asm code, the destructor is called before the call tobaz()
.Am I doing something wrong? Is there some way to tell clang that the inline wasm may throw?
The text was updated successfully, but these errors were encountered: