-
Notifications
You must be signed in to change notification settings - Fork 36
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
Encoding Exceptional CFGs #185
Comments
I am aware of that issue @conrad-watt mentioned, and we haven't fixed it yet, but we have a open bug filed for it and it's on our list of things to fix. I think it can be fixed by either cloning involved BBs or placing a |
I know you are aware of the specific example above, but that example is illustrative of a larger issue, and the fact that the bug has been open for half a year makes me concerned that the implications of the larger issue are not being recognized. Let's consider an EH representations like exception tables. With an exception table, every entry specifies a range of code and the relevant handler to be used if an exception occurs within that range (and often a condition, e.g. an exception type, or a classification, e.g. "cleanup" or "catch"). These closely correspond to how exceptions are often implemented (i.e. the runtime checks whether the return address is within a range specified in the exception table). LLVM lowers to exception tables, and its own representation is essentially a "floating" take on exception tables, meaning instructions are free to move around in order to make code transformations easier. An important aspect of exception tables is that the exception handling code can itself be included in the ranges covered by the exception table. This is important for handling nested exception handling, like in Java or C++. We saw one such feature when the Go team presented This behavior is easy to represent with exception tables. You simply have the last (i.e. lowest priority) entry in the table indicate that the entire function body should use the loop described above as its exception-cleanup code. In particular, even the loop itself is included in that range, which means that exceptions thrown by any deferred function call will simply jump to the start of the loop, which will get you the desired behavior (provided you pop a deferred function off the deferred-function stack before calling it). I cannot figure out how to encode this example cleanup feature using |
This seems too strong an objection. From a distance, I'd expect that the
My understanding (and @aheejin please feel free to correct me) is that the LLVM exception-handling approach used when targeting Wasm does guarantee a nested structure (see here and here), and that Wasm isn't the only target which requires/enforces this structure (see here). |
Ah, I had missed the last paragraph of LLVM's funclets. That's in line with a common complaint language implementers express about LLVM's exception-handling design: it's overspecialized to C++. This same complaint has been made (by myself and others) about this proposal. So how would you support Go's |
I expect that in the context of running the |
Try to do that in a way that accommodates the same use cases as the proposal provides for C++:
I can't get the current proposal to support either of these due to the combination of the restrictions on |
Here's why I can't get the current proposal to support this: Suppose the main body of the function throws a JS exception or panics. In this case, you went the deferred functions to run, so you at least need to put the main body inside a So with the current proposal, you seem to need an infinite function body to support this. This is even the case if you forgo handling JS exceptions and just handle panics but still want debugging support for uncaught panics. |
Oh yeah, good point that unknown exceptions can’t be moved into user space because |
Unfortunately |
WebAssembly does not directly support standard low-level representations of control flow, like control-flow graphs, but as part of its design and release there was both a high-level algorithm for and an integrated implementation of CFG-to-wasm conversion. From WebAssembly/design#796 I get the impression that there are many WebAssembly users that heavily rely on this conversion. This proposal similarly does not support standard low-level representations of exceptions, such as LLVM's per-call-site unwind destinations or JVM's exception tables. Is there a high-level algorithm for converting (one of) these standard representations into this proposal? I would have expected LLVM's unwind destinations to be supported, but this C++ example Conrad presented a while ago seems to produce invalid wasm because LLVM's optimizer makes the IR stray from the specific control-flow pattern the current implementation of CFGStackify seems to expect. Is this an oversight, or is it instead expected that some people heavily relying on CFG-to-wasm conversion should not use exceptions?
The text was updated successfully, but these errors were encountered: