<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, May 18, 2015 at 3:28 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>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">I hadn’t noticed the “noexcept” specifier in your example.  That clears up part of my concerns, but I still have some problems.<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)">With regard to the multiple meanings of ‘resume’ I am more concerning about developers who are reading the IR understanding it than about passes operating on
 it.  Apart from making it harder to debug problems related to control flow at resume instructions I think this makes it more likely that code which mishandles it will be introduced down the road.  If I’m reading things correctly, a resume instruction in your
 proposal could mean:<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)">a) We’re done handling this exception, continue normal execution at this 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)">b) We’re done handling this exception, continue execution in an enclosing catch handler at this 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)">c) We’re done executing this termination handler, check the catch handler at this label to see if it can handle the current exception.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">d) We’re done executing this termination handler, now execute the termination handler at this 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)">e) We’re done executing this termination handler, continue handling the exception in the runtime.<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 suppose (a) and (b) are more or less the same and it doesn’t entirely matter whether the destination is in normal code or exception code.  In practical terms
 (c) and (d) may be the same also, but logically, in terms of how the runtime works, they are different.  I’m pretty sure there’s a gap in my understanding of your proposal because I don’t understand how e() is represented at all.</span></p></div></div></blockquote><div><br></div><div>Yeah, Joseph agreed this was overloading resume too much. The new idea is that a-b would be handled by 'endcatch' (I previously called this 'recover', but endcatch will be more readable) and c-e are represented with an 'endcleanup' instruction. The endcleanup will have an unwind label operand indicating which EH action runs next, which handles both c and d, depending on the nature of the block. If the unwind label is missing, then execution continues in the calling function's actions.</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>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">As an exercise, I tried to work through the IR that would be produced in the non-optimized case for the following code:<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 test() {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    Obj o1;<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">      f();<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 (int) {}<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    Obj o2;<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">      g();<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 (int) {}<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    h();<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 (int) {}<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)">Here’s what I came up with:<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)"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">define void @foo() personality i32 (...)* @__CxxFrameHandler3 {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  %e.addr = alloca i32<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  invoke void @f(i32 1)<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)">    to label %cont1 unwind label %cleanup.Obj<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">cont1:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  invoke void @g(i32 2)<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    to label %cont2 unwind label %cleanup.Obj.1<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">cont2:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  invoke void @h(i32 2)<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    to label %cont3 unwind label %cleanup.Obj.2<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">cont3:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  call void @~Obj()<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)">  call void @~Obj()<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  br label %return<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">return:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  ret void<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)">cleanup.Obj:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  cleanupblock unwind label %<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__maycatch.int&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=7_GVTEEMJfaTQCr4L2GC3_qwb89uUWsMWPEDUJdrY-0&s=ys7trgMkxC9BUnHu8RrVDLi9l4GRUZU5SUeIU_mkkV4&e=" target="_blank">maycatch.int</a><u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  call void @~Obj()<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  resume label %<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__maycatch.int&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=7_GVTEEMJfaTQCr4L2GC3_qwb89uUWsMWPEDUJdrY-0&s=ys7trgMkxC9BUnHu8RrVDLi9l4GRUZU5SUeIU_mkkV4&e=" target="_blank">maycatch.int</a><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)"><a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__maycatch.int&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=7_GVTEEMJfaTQCr4L2GC3_qwb89uUWsMWPEDUJdrY-0&s=ys7trgMkxC9BUnHu8RrVDLi9l4GRUZU5SUeIU_mkkV4&e=" target="_blank">maycatch.int</a>:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  catchblock void [i8* @<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__typeid.int&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=7_GVTEEMJfaTQCr4L2GC3_qwb89uUWsMWPEDUJdrY-0&s=DdBRzcvcgnCPNcg8OeD8hJwX3jX1c3lxitmzxRz5JTo&e=" target="_blank">typeid.int</a>, i32 7, i32* %e.addr]<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    to label %<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__catch.int&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=7_GVTEEMJfaTQCr4L2GC3_qwb89uUWsMWPEDUJdrY-0&s=-Oh-Z3xzdhu9fXcjqU74fXUTiJJEfRphlwmHlYpH9DE&e=" target="_blank">catch.int</a> unwind label %catchend<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)"><a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__catch.int&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=7_GVTEEMJfaTQCr4L2GC3_qwb89uUWsMWPEDUJdrY-0&s=-Oh-Z3xzdhu9fXcjqU74fXUTiJJEfRphlwmHlYpH9DE&e=" target="_blank">catch.int</a>:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  resume label %cont1<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">catchend:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  resume<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)">cleanup.Obj.1:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  cleanupblock unwind label %maycatch.int.1<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  call void @~Obj()<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  call void @~Obj()<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  resume label %maycatch.int.1<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)">maycatch.int.1:<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)">  catchblock void [i8* @<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__typeid.int&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=7_GVTEEMJfaTQCr4L2GC3_qwb89uUWsMWPEDUJdrY-0&s=DdBRzcvcgnCPNcg8OeD8hJwX3jX1c3lxitmzxRz5JTo&e=" target="_blank">typeid.int</a>, i32 7, i32* %e.addr]<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)">    to label %catch.int.1 unwind label %catchend.1<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.int.1:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  resume label %cont2<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">catchend.1:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  resume<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)">cleanup.Obj.2:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  cleanupblock unwind label %maycatch.int.2<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  call void @~Obj()<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  call void @~Obj()<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  resume label %maycatch.int.2<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)">maycatch.int.2:<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)">  catchblock void [i8* @<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__typeid.int&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=7_GVTEEMJfaTQCr4L2GC3_qwb89uUWsMWPEDUJdrY-0&s=DdBRzcvcgnCPNcg8OeD8hJwX3jX1c3lxitmzxRz5JTo&e=" target="_blank">typeid.int</a>, i32 7, i32* %e.addr]<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)">    to label %catch.int.2 unwind label %catchend.2<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.int.2:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  resume label %return<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">catchend.2:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  resume<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)">I don’t know if I got that right, but it seems to me that there are a couple of problems with this.  Most obviously, there is a good bit of duplicated code
 here (which the optimization passes will probably want to combine).</span></p></div></div></blockquote><div><br></div><div>First, each destructor gets it's own cleanupblock, and ultimately ends up in it's own outlined funclet. This cuts down on ~Obj duplication.</div><div><br></div><div>Second, you seem to always have the invokes unwinding to cleanups which then unwind to catch handlers, even if the try is more closely nested than the cleanup. If f() throws int, we don't actually run cleanup.Obj, we run the catch and rejoin normal control flow, which will call ~Obj for o1.</div><div><br></div><div>Here's how I'd translate that to IR, assuming Obj is empty and has no ctor:</div><div><br></div><div>define void @foo() personality i32 (...)* @__CxxFrameHandler3 {</div><div>entry:</div><div>  %o1 = alloca i8</div><div>  %o2 = alloca i8</div><div>  invoke void @f()</div><div>    to label %cont1 unwind label %maycatch.int2</div><div>cont1:</div><div>  invoke void @g()</div><div>    to label %cont2 unwind label %maycatch.int3</div><div>cont2:</div><div>  invoke void @h()</div><div>    to label %cont3 unwind label %cleanup.Obj1</div><div>cont3:</div><div>  call void @~Obj(i8* %o2)</div><div>  call void @~Obj(i8* %o1)</div><div>  br label %return</div><div>return:</div><div>  ret void</div><div><br></div><div>maycatch.int2:</div><div>  catchblock [i8* @<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__typeid.int&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=7_GVTEEMJfaTQCr4L2GC3_qwb89uUWsMWPEDUJdrY-0&s=DdBRzcvcgnCPNcg8OeD8hJwX3jX1c3lxitmzxRz5JTo&e=">typeid.int</a>]</div><div>    to label %catch.int2 unwind label %catchendblock2</div><div>catch.int2:</div><div>  endcatch label %cont2</div><div>catchendblock2:</div><div>  catchendblock unwind label %cleanup.Obj1</div><div><br></div><div>maycatch.int3:</div><div>  catchblock [i8* @<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__typeid.int&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=7_GVTEEMJfaTQCr4L2GC3_qwb89uUWsMWPEDUJdrY-0&s=DdBRzcvcgnCPNcg8OeD8hJwX3jX1c3lxitmzxRz5JTo&e=">typeid.int</a>]</div><div>    to label %catch.int3 unwind label %catchendblock3</div><div>catch.int3:</div><div>  endcatch label %cont3</div><div>catchendblock3:</div><div>  catchendblock unwind label %cleanup.Obj2</div><div><br></div><div>cleanup.Obj2:</div><div>  cleanupblock unwind label %cleanup.Obj1</div><div>  call void @~Obj(i8* %o2)</div><div>  endcleanup from label %cleanup.Obj2 unwind label %cleanup.Obj1</div><div><br></div><div>cleanup.Obj1:</div><div>  cleanupblock unwind label %maycatch.int1</div><div>  call void @~Obj(i8* %o1)</div><div>  endcleanup from label %cleanup.Obj1 unwind label %maycatch.int1</div><div><br></div><div>maycatch.int1:</div><div>  catchblock [i8* @<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__typeid.int&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=7_GVTEEMJfaTQCr4L2GC3_qwb89uUWsMWPEDUJdrY-0&s=DdBRzcvcgnCPNcg8OeD8hJwX3jX1c3lxitmzxRz5JTo&e=">typeid.int</a>]</div><div>    to label %catch.int1 unwind label %catchendblock1</div><div>catch.int1:</div><div>  endcatch label %return</div><div>catchendblock1:</div><div>  catchendblock ; no unwind label, uncaught exceptions leave the function</div><div>}</div><div><br></div><div>This has a total of 4 calls to ~Obj, so each cleanup is emitted exactly twice: once for normal flow and once for exceptional flow.</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>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">More significantly though is that it doesn’t correctly describe what happens if a non-int exception is thrown in any of the called functions.  For instance,
 if a non-int exception is thrown from g() that is caught somewhere further down the stack, the runtime should call a terminate handler that destructs o1 and then call a terminate handler that destructs o2.  However, my IR doesn’t describe a terminate handler
 that destructs just o2 and I don’t know how I could get it to do so within the scheme that you have proposed.</span></p></div></div></blockquote><div><br></div><div>The idea is that the program notionally "executes" the EH blocks and each block describes the intended successor. In the Itanium landingpad model, that's pretty close to what actually happens, with an optimization to skip execution of frames that have no cleanups and have no matching catches.</div><div><br></div><div>If h throws a float exception, we should run, in order, maycatch.int3, catchendblock3, cleanup.Obj2, cleanup.Obj1, maycatch.int1, catchendblock4, and then unwind to the parent. Make sense?</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>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">In a mostly unrelated matter, have you thought about what needs to be done to prevent catchblock blocks from being combined?  For example, suppose you have
 code 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)">void test() {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    f();<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 (int) {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    x();<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    y();<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    z();<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)">  try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    g();<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 (…) {<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)">  try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    h();<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 (int) {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    x();<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    y();<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    z();<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)"><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 think it’s very likely that if we don’t do anything to prevent it the IR generated for this will be indistinguishable from the IR generated for 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)">void test() {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    f();<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">      g();<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 (…) {<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)">    h();<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 (int) {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    x();<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    y();<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    z();<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)">}</span></p></div></div></blockquote><div><br></div><div>In the original source, the catch-all block unwinds to the parent frame. In the transformed example, it doesn't. Mid-level optimization passes should keep the catch-all in the first example unwinding out to the parent, otherwise things will break down.</div><div><br></div><div>Practically, the current middle-end will be unable to merge the catchblocks because of catchendblock and this rule: "Invokes that are reached after a catchblock without following any unwind edges must transitively unwind to the first catchend block that the catchblock unwinds to."</div><div><br></div><div>The catchblocks will look like:</div><div><br></div><div>maycatch.int1:</div><div>  catchblock [i8* @<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__typeid.int&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=7_GVTEEMJfaTQCr4L2GC3_qwb89uUWsMWPEDUJdrY-0&s=DdBRzcvcgnCPNcg8OeD8hJwX3jX1c3lxitmzxRz5JTo&e=">typeid.int</a>]</div><div>    to label %catch.int1 ; unwind to parent</div><div>catch.int1:</div><div>  invoke void @x() to label %cont1 unwind label %catchendblock1</div><div>cont1:</div><div>  invoke void @y() to label %cont2 unwind label %catchendblock1<br></div><div>cont2:<br></div><div>  invoke void @z() to label %cont3 unwind label %catchendblock1<br></div><div>cont4:<br></div><div>  endcatch label %...</div><div>catchendblock1:</div><div>  catchendblock ; unwind to parent</div><div><br></div><div>Any code merging optimization would have to ensure that those xyz calls unwind to the catchendblock referenced by the catchblock. Practically, this will require merging the entire catchblock, which *is* a legal transformation, and we can compensate for it in the ip2state tables. Imagine assigning these states:</div><div><br></div><div>call f() // state 0</div><div>call g() // state 2</div><div>catchall // state 3</div><div>call h() // state 0</div><div>catchint // state 1</div><div><br></div><div>So, f and h can have the same states even though they are split across the g call in source order.</div><div><br></div><div>I need to write more about the state numbering algorithm we came up with, it's the primary constraint on the design.</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)">In this case that might be OK, but theoretically the calls to f() and h() should get different states and there are almost certainly cases where failing to
 recognize that will cause problems.  What’s more, the same basic pattern arises for this 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)">void test() {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">  try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    f();<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 (int) {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    x();<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    y();<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    z();<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)">  try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    g();<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 (float) {<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)">  try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    h();<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 (int) {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    x();<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    y();<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">    z();<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)"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">But in this case, if we get the state numbering wrong an int-exception from g() could end up being incorrectly caught by the xyz handler.<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)">BTW, finding cases like this is the primary reason that I’ve been trying to push my current in-flight patch onto the sinking ship that is our current implementation. 
 I mentioned to you before that the test suite I’m using passes with my proposed patch, but that’s only true with optimizations disabled.  With optimizations turned on I’m seeing all kinds of fun things like similar handlers being combined and common instructions
 being hoisted above a shared(!) eh_begincatch call in if-else paired handlers.  I don’t know if it will be worth trying to fix these problems, but seeing them in action has been very instructive.</span></p></div></blockquote><div><br></div><div> </div></div></div></div>