<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Nov 24, 2014 at 12:12 PM, Kaylor, Andrew <span dir="ltr"><<a href="mailto:andrew.kaylor@intel.com" target="_blank">andrew.kaylor@intel.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">
<div lang="EN-US" link="blue" vlink="purple">
<div>
<div>
<div>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">Hi Reid,<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">I've been working on the outlining code and have a prototype that produces what I want for a simple case.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">Now I'm thinking about the heuristics for recognizing the various logical pieces for C++ exception handling code and removing them once they’ve been cloned.
I've been working from various comments you've made earlier in this thread, and I'd like to run something by you to make sure we're on the same page.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">Starting from a C++ function that looks like this:</span></p></div></div></div></div></div></div></blockquote><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"><div lang="EN-US" link="blue" vlink="purple"><div><div><div><div><div>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">I'll have IR that looks more or less like this:</span></p></div></div></div></div></div></div></blockquote><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"><div lang="EN-US" link="blue" vlink="purple"><div><div><div><div><div>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">If I've understood your intentions correctly, we'll have an outlining pass that transforms the above IR to this:</span><span style="color:rgb(31,73,125);font-family:Calibri,sans-serif;font-size:11pt"> </span></p></div></div></div></div></div></div></blockquote><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"><div lang="EN-US" link="blue" vlink="purple"><div><div><div><div><div>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">Does that look about like what you’d expect?</span></p></div></div></div></div></div></div></blockquote><div><br></div><div>Yep! That's basically what I had in mind, but I still have concerns with this model listed below.</div><div><br></div><div>We should also think about how to call std::terminate when cleanup dtors throw. The current representation for Itanium is inefficient. As a strawman, I propose making @__clang_call_terminate an intrinsic:</div><div><br></div><div> ...</div><div> invoke void @dtor(i8* %this) to label %cont unwind label %terminate.lpad</div><div>cont:</div><div> ret void</div><div>terminate.lpad:</div><div> landingpad ... catch i8* null</div><div> call void @llvm.eh.terminate()</div><div> unreachable</div><div><br></div><div>This would be good for Itanium EH, as we can actually completely elide table entries for landing pads that just catch-all and terminate.</div><div><span style="color:rgb(31,73,125);font-family:Calibri,sans-serif;font-size:11pt"> </span></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"><div lang="EN-US" link="blue" vlink="purple"><div><div><div><div><div>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">I just have a few questions.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">I'm pretty much just guessing at how you intended the llvm.eh.set_capture_block intrinsic to work. It wasn't clear to me if I just needed to set it where the
structure was created or if it would need to be set anywhere an exception might be thrown. The answer is probably related to my next question.</span></p></div></div></div></div></div></div></blockquote><div><br></div><div>I was imagining it would be called once in the entry block.</div><div><br></div><div>Chandler expressed strong concerns about this design, however, as @llvm.eh.get_capture_block adds an ordering constraint on CodeGen. Once you add this intrinsic, we *have* to do frame layout of @_Z13do_some_thingRi *before* we can emit code for all the callers of @llvm.eh.get_capture_block. Today, this is easy, because module order defines emission order, but in the great glorious future, codegen will hopefully be parallelized, and then we've inflicted this horrible constraint on the innocent.</div><div><br></div><div>His suggestion to break the ordering dependence was to lock down the frame offset of the capture block to always be some fixed offset known by the target (ie ebp - 4 on x86, if we like that).</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"><div lang="EN-US" link="blue" vlink="purple"><div><div><div><div><div>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">In the above example I created a single capture block for the entire function. That works reasonably well for a simple case like this and corresponds to the
co-location of the allocas in the original IR, but for functions with more complex structures and multiple try blocks it could get ugly. Do you have ideas for how to handle that?</span></p></div></div></div></div></div></div></blockquote><div><br></div><div>Not really, it would just get ugly. All allocas used from landing pad code would get mushed into one allocation. =/</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"><div lang="EN-US" link="blue" vlink="purple"><div><div><div><div><div>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">For C++ exception handling, we need cleanup code that executes before the catch handlers and cleanup code that excutes in the case on uncaught exceptions.
I think both of these need to be outlined for the MSVC environment. Do you think we need a stub handler to be inserted in cases where no actual cleanup is performed?</span></p></div></div></div></div></div></div></blockquote><div><br></div><div>I think it's actually harder than that, once you consider nested trys:</div><div>void f() {</div><div> try {</div><div> Outer outer;</div><div> try {</div><div> Inner inner;</div><div> g();</div><div> } catch (int) {</div><div> // ~Inner gets run first<br> }</div><div> } catch (float) {</div><div> // ~Inner gets run first</div><div> // ~Outer gets run next<br> }</div><div> // uncaught exception? Run ~Inner then ~Outer.<br>}</div><div><br></div><div>It's easy to hit this case after inlining as well.</div><div><br></div><div>We'd have to generalize @llvm.eh.outlined_handlers more to handle this case. However, if we generalize further it starts to perfectly replicate the landing pad structure, with cleanup, catch, and then we'd want to think about how to represent filter. Termination on exception spec violation seems to be unimplemented in MSVC, so we'd need our own personality function to implement filters, but it'd be good to support them in the IR.</div><div><br></div><div>We also have to decide how much code duplication of cleanups we're willing to tolerate, and whether we want to try to annotate the beginning and end of cleanups like ~Inner and ~Outer.</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"><div lang="EN-US" link="blue" vlink="purple">
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">I didn't do that in the mock-up above, but it seems like it would simplify things. Basically, I'm imagining a final pattern that looks like this:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">lpad:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"> %eh_vals = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)<u></u><u></u></span></p><span class="">
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"> cleanup<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"> catch i8* @typeid1<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"> catch i8* @typeid2<u></u><u></u></span></p>
</span><p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"> ...<u></u><u></u></span></p><span class="">
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"> %label = call i8* (...)* @llvm.eh.outlined_handlers(<u></u><u></u></span></p>
</span><p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"> void (i8*, i8*)* @<pre-catch cleanup function>,<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"> i8* @typeid1, i8* (i8*, i8*)* @<typeid1 catch function>,<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"> i8* @typeid2, i8* (i8*, i8*)* @<typeid2 catch function>,<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"> ...<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"> void (i8*, i8*)* @<uncaught exception cleanup function>)<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"> indirectbr i8* %label<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">Finally, how do you see this meshing with SEH? As I understand it, both the exception handlers and the cleanup code in that case execute in the original function
context and only the filter handlers need to be outlined. I suppose the outlining pass can look at the personality function and change its behavior accordingly. Is that what you were thinking?</span></p></div></blockquote><div><br></div><div>Pretty much. The outlining pass would behave differently based on the personality function. SEH cleanups (__finally blocks) actually do need to get outlined as well as filters, but catches (__except blocks) do not need to be outlined. That's the main difference. I think it reflects the fact that you can rethrow a C++ exception, but you can't faithfully "rethrow" a trap caught by SEH.</div></div></div></div>