<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"> On Mon, May 18, 2015 at 2:42 PM, Steve Cheng <span dir="ltr"><<a href="mailto:steve.ckp@gmail.com" target="_blank">steve.ckp@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Hi Reid,<span class=""><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
Right, __CxxFrameHandler3 is a lot more constraining than __C_specific_handler. The SEH personality doesn't let you rethrow exceptions, so once you catch the exception you're done, you're in the parent function. My understanding is that C++ works by having an active catch handler on the stack.<br>
</blockquote>
<br></span>
Okay, I checked the Wine source code for __CxxFrameHandler3. I stand corrected.<br>
<br>
While we are on the topic of Windows EH, I like to know your (and others', of course) thoughts on the following. It's my wishlist as a frontend implementor :)<br>
<br>
- Win32 (x86) frame-based SEH<br>
<br>
For __CxxFrameHandler3, since destructors and catch blocks execute as funclets while the throwing function's stack frame is still active, it's not going to be a problem right?<br></blockquote><div><br></div><div>My understanding is that __CxxFrameHandler3 does something like the following:</div><div><br></div><div>for (void (*Cleanup)(bool, void*) : Cleanups) {</div><div>  __try {</div><div>    Cleanup(/*AbnormalTermination=*/true, EstablisherFrame);<br>  } __except(1) {</div><div>    std::terminate(); // can't rethrow<br>  }<br>}</div><div>__try {</div><div>  CallCatchBlock();<br>} __except(__CxxDetectRethrow(), EXCEPTION_CONTINUE_SEARCH) {<br>}</div><div><br></div><div>So I guess it's not really that the catch block has an active frame, and more that __CxxFrameHandler3 is there saying "hey, I saw a rethrow exception go by during phase 1, here's what that exception was supposed to be".</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
But for __C_specific_handler, I see a potential issue versus x86-64, in that RtlUnwind can't restore non-volatile registers, so when registers are garbage when control is transferred to the landing pad.  When I read the Itanium ABI documentation, it says that landing pads do get non-volatile registers restored, so I guess that's probably the working assumption of LLVM.<br></blockquote><div><br></div><div>That's pretty frustrating, given that the xdata unwinder already knows where the non-volatile registers are saved. Anyway, I think it can be overcome in the backend with the right register allocation constraints.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
__C_specific_handler's registration frame saves down EBP, but no other registers, even ESP. If we use dynamic alloca or frame pointer omission, we are dead in the water, right?<br></blockquote><div><br></div><div>Are you sure the unwinder doesn't restore RSP? Anyway, the address of a dynamic alloca can easily be spilled to the stack and reloaded.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
- Writing one's own personality functions<br>
<br>
This makes a lot of sense if one is implementing a different language than C++ that has exceptions, and is prepared to provide their own run-time support.<br>
<br>
Say, if the language supports resuming from exceptions, or can query type information in more flexible ways than C++'s std::type_info matching. Does it really make sense for the backend, LLVM, to hard-code knowledge about the language-specific data area (LSDA)? Even in the Itanium ABI it's explicitly stated that the personality is specific to the source language, yet multiple personalities can interoperate in the same program. Ideally, I would prefer the backend to take control of everything to do with arranging the landing pads, branches within landing pads, and so on, but NOT the language-dependent exception matching.<br>
<br>
Taken to the extreme, LLVM would have to expose tables that the LLVM client would have to translate to their own formats, like the garbage collection "unwind" tables. If that's too complicated at least it would be nice to supply custom filter functions for catch clauses. Inspired by SEH filters obviously, but we might devise a slightly more portable version.<br></blockquote><div><br></div><div>I think LLVM has to know about the table format and landingpad PC values, because that's its business. The RTTI data, though, is completely between the frontend and the EH personality. I could imagine a personality that uses an Itanium LSDA, but the RTTI pointers are really pointers to functions that get called during phase 1 to implement SEH filters. The new representation will actually allow you to pass more data here to support passing in "adjectives" as required for MSVC, but LLVM will have to know where to put it in the table and there's no way to avoid that.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
Even for C++ I actually wouldn't mind being able to arbitrarily replace the personality, and/or the runtime functions for throwing and resuming. In my C++ source code I always throw exceptions wrapped in a macro, because I want to instrument all my throw statements. In particular, I can construct a reliable stack trace on the spot with RtlVirtualUnwind (or walking the EBP chain on x86). It would be a nice bonus if we could implement this kind of instrumentation with Clang. Encouragement to switch from MSVC :)</blockquote><div><br></div></div></div></div>