Skip to content
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

MSVC: Implement 32-bit Unwinding #25869

Closed
4 tasks done
alexcrichton opened this issue May 29, 2015 · 13 comments · Fixed by #30448
Closed
4 tasks done

MSVC: Implement 32-bit Unwinding #25869

alexcrichton opened this issue May 29, 2015 · 13 comments · Fixed by #30448
Assignees
Labels
O-windows-msvc Toolchain: MSVC, Operating system: Windows

Comments

@alexcrichton
Copy link
Member

Updated report

Original Report

Right now the MSVC target turns all calls to panic! into a process-wide abort as unwinding is not implemented.

WIP branch: https://github.com/alexcrichton/rust/tree/msvc-llvm-update (now merged)

@alexcrichton alexcrichton added O-windows Operating system: Windows T-tools labels May 29, 2015
@alexcrichton alexcrichton self-assigned this May 29, 2015
@alexcrichton
Copy link
Member Author

LLVM has been upgrade, this is now blocked on https://llvm.org/bugs/show_bug.cgi?id=23884 I believe.

@briansmith
Copy link
Contributor

A question about this: Last time we talked, Alex mentioned that this was blocked on getting SEH-compatible unwinding to work on 32-bit Windows. According to Microsoft's documentation, in MSVC C++ mode, they recommend not to use the SEH-compatible unwinding for reasons of correctness and performance. See https://msdn.microsoft.com/en-us/library/1deeycx5.aspx.

Which MSVC /EH option is most similar to Rust's (proposed) handling of unwinding? And, is SEH-compatible unwinding really necessary?

@retep998
Copy link
Member

@briansmith That article is recommending to not use a flag which would let C++ exceptions catch arbitrary SEH exceptions, things like stack overflow and divide by zero. Internally all the exceptions and unwinding in the msvc world are using SEH. Basically you're confused between the class of exceptions referred to as SEH exceptions and SEH as the unwinding/exception mechanism.

@alexcrichton
Copy link
Member Author

Ah thanks for the ping @briansmith, I should give a status update on this. Currently unwinding on 64-bit MSVC is fully implemented using DWARF side tables like the GNU triple uses and we implement the necessary runtime support to parse these side tables. Unwinding on 32-bit MSVC is unimplemented, however. I have not investigated too closely what it would mean to implement DWARF unwinding for 32-bit like we have for 64-bit (I believe @vadimcn knows more about this than I do).

My current idea for implementing 32-bit is to wait for LLVM's exception handling intrinsics to be fully implemented. I'm under the impression they're relatively experimental for now and are unlikely to work for us (but I haven't checked in awhile). Once those exist we can switch to those for 32 and 64 bit MSVC, tweak some runtime support, and in theory "Just Work".

In any case, however, unwinding from C++ to Rust is undefined behavior no matter what happens (and vice versa), so exceptions/panics must always be caught at FFI boundaries. In that sense SEH compatible unwinding isn't necessary, but we need a solution for 32-bit still.

@alexcrichton alexcrichton changed the title MSVC: Implement Unwinding MSVC: Implement 32-bit Unwinding Sep 20, 2015
@briansmith
Copy link
Contributor

SEH compatible unwinding isn't necessary, but we need a solution for 32-bit still.

Right. Maybe I misunderstood, but my impression is that people felt that resolving this was blocked on SEH-compatible unwinding. My point is that a lot of people targetting -msvc don't need or want SEH-compatible unwinding, especially if it has negative perf/size implications. That is, if this bug were resolved with (only) a SEH-compatible unwinder, then there should be a follow-up issue to track more efficient unwinding.

I believe the LLVM work is intended to support mixing MSVC-compiled C++ code with clang-compiled C++ code with exceptions that traverse stacks of code implemented with each compiler; i.e. 100% interop with the MSVC C++ ABI. That's quite a different problem from what Rust needs, AFAICT.

AFAICT, the requirements for the unwinder are just that implementations of Drop have their drop method called, and that a panic terminates the thread in a way that the thing that spawned the thread can recover from. Relative to the other things mentioned above, these seem like much simpler things to address.

@vadimcn
Copy link
Contributor

vadimcn commented Sep 21, 2015

@briansmith: The code that unwinds stack using DWARF frame info lives in libgcc. Furthermore, because of the way module registration with the unwinder is implemented, we must link to the dynamic version of libgcc. I am guessing that @alexcrichton did not want to have this dependency in *-pc-windows-msvc executables.
We could re-implement the unwinder ourselves and thus get rid of the libgcc dependency, but given that LLVM will soon have proper 32-bit SEH support, is it a good investment of time?

@briansmith
Copy link
Contributor

We could re-implement the unwinder ourselves and thus get rid of the libgcc dependency, but given that LLVM will soon have proper 32-bit SEH support, is it a good investment of time?

Yes, from my perspective. 32-bit Windows is the most important target in that it is the target that covers the most users. In particular, 32-bit Windows apps work on 64-bit Windows AND 32-bit Windows. From the end-user-of-Rust perspective, it seems very risky to wait for LLVM to eventually fix this, especially when Alex said that LLVM's implementation is likely to not even work for Rust even when it is finished at some unknown point in time in the future. That said, I'm biased because I've invested a lot of time to create infrastructure software in Rust, and in order to convince people to use my software, I have to convince them that Rust isn't super risky, and this is one of the issues that people have mentioned as a concern.

@alexcrichton
Copy link
Member Author

Ah to be clear I just mean that LLVM's implementation right this red hot second is unlikely to work (e.g. the WIP variant), I expect it is certainly aimed at working quite well in the very near future, e.g. the next 3.8 release most likely.

I haven't checked up on the progress in awhile though, but if there's good pressure to get this working robustly on 32-bit MSVC I can certainly shift some time into investigating!

@kosta
Copy link

kosta commented Oct 2, 2015

Seem you deleted the WIP branch https://github.com/alexcrichton/rust/tree/msvc-llvm-update That was for 64bit, right? (Maybe delete or strike it through from the issue above?)

What do you think the timeline is on getting unwinding support for 32bit? This year? Next year?

I agree with @briansmith that Windows 32bit is the platform with the biggest userbase period. I'm working on porting to Rust an existing Windows app where file size matters. So need to use 32 bit to reach both 32 and 64 bit Windows users. No stack unwinding doesn't make it impossible to write the app, but it makes it harder to debug and much harder to convince people that this is a good idea to do.

I'm not compiler hacker, but is there anything I can do to help?

@vadimcn
Copy link
Contributor

vadimcn commented Oct 2, 2015

@kosta, is there a particular reason you can't use the i686-pc-windows-gnu flavor? It has full support for unwinding.

@alexcrichton
Copy link
Member Author

What do you think the timeline is on getting unwinding support for 32bit?

My current thoughts are to hold off until LLVM 3.8 and then try again to use the native MSVC unwinding intrinsics, but that's mostly because I don't know of the status of that implementation in LLVM. If it's ready now then we'd be fine just updating the submodule we've got and using it.

@vadimcn has a point though, does the gnu 32-bit triple not work for you? If you're compiling and linking with an MSVC-compiled native library it may not work out well but otherwise it should work!

@kosta
Copy link

kosta commented Oct 7, 2015

I'm currently re-evaluating using gcc and will reply once I'm done...

@alexcrichton
Copy link
Member Author

The corresponding LLVM bug has been closed now, and it may be the case that LLVM's support for SEH and such is much better now than it was before, so we can perhaps try to start transitioning towards that soon!

bors added a commit that referenced this issue Jan 30, 2016
These commits perform a few high-level changes with the goal of enabling i686 MSVC unwinding:

* LLVM is upgraded to pick up the new exception handling instructions and intrinsics for MSVC. This puts us somewhere along the 3.8 branch, but we should still be compatible with LLVM 3.7 for non-MSVC targets.
* All unwinding for MSVC targets (both 32 and 64-bit) are implemented in terms of this new LLVM support. I would like to also extend this to Windows GNU targets to drop the runtime dependencies we have on MinGW, but I'd like to land this first.
* Some tests were fixed up for i686 MSVC here and there where necessary. The full test suite should be passing now for that target.

In terms of landing this I plan to have this go through first, then verify that i686 MSVC works, then I'll enable `make check` on the bots for that target instead of just `make` as-is today.

Closes #25869
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-windows-msvc Toolchain: MSVC, Operating system: Windows
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants