[LLVMdev] Windows EH support

Reid Kleckner rnk at google.com
Fri Dec 19 13:36:00 PST 2014


On Fri, Dec 19, 2014 at 1:13 PM, Kaylor, Andrew <andrew.kaylor at intel.com>
wrote:
>
>     * Add support for unwinding in frames with no exception handlers
>
>
>
> I’m not clear as to what needs to be done for this.  I know clang is
> intentionally generating errors when you compile code with an
> MSVC-environment target.  I’m guessing that just removing this block will
> be sufficient for clang to generate the IR we want.  Then it will be up to
> the back end to produce the correct unwinding support, which I think it may
> already be doing.
>
>
>
> >> Do we not do this already? This shouldn't be hard, we already know how
> to emit the required pdata/xdata call frame information (CFI).
>
>
>
> Like I said, clang spits out an error if you try to compile with
> exceptions enabled for an MSVC-environment target.  If you compile without
> exceptions enabled, it doesn’t generate the IR necessary to cleanup during
> unwind if an exception is thrown across a function.  I tested it by
> compiling functions with MSVC that call through a function compiled with
> clang and then throwing an exception across the clang-compiled function.
> It unwinds correctly, but doesn’t do any cleanup.
>

Ah, OK, I misunderstood what you meant. I guess you're asking about
emitting handlers for C++ destructors when no explicit EH construct (try or
__try) is present.

This shouldn't be hard. This should use the same IR as __finally and should
be outlined in the same way. The only difference is what personality
function gets used.


> I know that llvm has code to handle this with some personality functions
> (mingw, at least), but I don’t think it supports the “native” MSVC
> personality functions yet (__CxxFrameHandler3/4 in this case).  I suppose
> that will come out of the C++EH work with nothing extra to be done
> especially for SEH in the back end.  I just wanted to call it out in case
> there was something else I had overlooked.
>
>
>
> Here’s the test case I have in mind.
>
>
>
> ==========================================
>
>
>
> #include <windows.h>
>
> #include <stdio.h>
>
>
>
> class MyClass {
>
> public:
>
>   MyClass() { printf("Hello\n"); }
>
>   ~MyClass() { printf("Goodbye\n"); }
>
> };
>
>
>
> void bar() {
>
>   RaiseException(1, 0, 0, NULL);
>
> }
>
>
>
> void foo() {
>
>   MyClass Fubar;
>
>   bar();
>
> }
>
>
>
> DWORD filter() {
>
>     printf("In filter\n");
>
>     return EXCEPTION_EXECUTE_HANDLER;
>
> }
>
>
>
> int main() {
>
>     __try {
>
>         __try {
>
>             foo();
>
>         }
>
>         __except (filter()) {
>
>             printf("In exception handler\n");
>
>         }
>
>     }
>
>     __finally {
>
>         printf("Finally!\n\n");
>
>     }
>
>     return 0;
>
> }
>
>
>
> ==========================================
>
>
>
> Compiling that with MSVC, it doesn’t execute the MyClass destructor if I
> compile with no /EH option, but it does execute the destructor with /EHa,
> having called it from __CxxFrameHandler3 while unwinding, on its way to the
> exception handler.  I understand that you aren’t worried about faithfully
> reproducing the behavior of /EHa, but we do at least want to clean up in
> cases like this, right?
>

I think MSVC might default to EHs and not EHa because most code isn't
written to handle recovery from random access violations. The destructors
might clean things up successfully, or they might fault. Once we've gone to
async exceptions land, it's almost safer to not run C++ cleanups and just
run __finally blocks that were explicitly written to clean up after faults.

However, if someone does want to run C++ destructors, it's easy for us to
support it at a best-effort level by using the normal _CxxFrameHandler3/4
personality function and flipping the flag in the EH table that controls
this behavior. Some of the cleanups will get run, but probably not the ones
in the function that trapped. In the case that you've outlined, I think
everything will work as intended because RaiseException() is a potentially
throwing function call.

If we want to support this level of EHa, it's probably worth thinking about
how to represent it for LTO. My first idea is "use a function attribute",
but those can get lost with cross-module inlining. Then again, it reflects
the limitations of the _CxxFrameHandler3 flag, which operates at a
whole-function level.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141219/50aeb531/attachment.html>


More information about the llvm-dev mailing list