<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:Wingdings;
        panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
        {font-family:PMingLiU;
        panose-1:2 2 5 0 0 0 0 0 0 0;}
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:"\@PMingLiU";
        panose-1:2 1 6 1 0 1 1 1 1 1;}
@font-face
        {font-family:"Consolas\,";}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0in;
        margin-right:0in;
        margin-bottom:0in;
        margin-left:.5in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.EmailStyle21
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
/* List Definitions */
@list l0
        {mso-list-id:2099979977;
        mso-list-type:hybrid;
        mso-list-template-ids:-1945739978 1143487470 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l0:level1
        {mso-level-number-format:bullet;
        mso-level-text:\F0D8;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;
        mso-fareast-font-family:PMingLiU;
        mso-bidi-font-family:"Times New Roman";}
@list l0:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l0:level3
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;
        mso-bidi-font-family:Wingdings;}
@list l0:level4
        {mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;
        mso-bidi-font-family:Symbol;}
@list l0:level5
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l0:level6
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;
        mso-bidi-font-family:Wingdings;}
@list l0:level7
        {mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;
        mso-bidi-font-family:Symbol;}
@list l0:level8
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l0:level9
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;
        mso-bidi-font-family:Wingdings;}
ol
        {margin-bottom:0in;}
ul
        {margin-bottom:0in;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal">First of all, I suggest you take some time to read through the first example in my wiki and understand the expected behavior of jumping-out-of-finally in SEH.<o:p></o:p></p>
<p class="MsoNormal">It will make our communication much easier.  <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">More reply inline below; Started with [Ten]<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b>From:</b> Eli Friedman <efriedma@quicinc.com> <br>
<b>Sent:</b> Thursday, April 2, 2020 8:48 PM<br>
<b>To:</b> Ten Tzen <tentzen@microsoft.com>; llvm-dev <llvm-dev@lists.llvm.org><br>
<b>Cc:</b> Aaron Smith <aaron.smith@microsoft.com><br>
<b>Subject:</b> [EXTERNAL] RE: [llvm-dev] [RFC] [Windows SEH] Local_Unwind (Jumping out of a _finally) and -EHa (Hardware Exception Handling)<o:p></o:p></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Reply inline.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="margin-left:.5in"><b>From:</b> Ten Tzen <<a href="mailto:tentzen@microsoft.com">tentzen@microsoft.com</a>>
<br>
<b>Sent:</b> Thursday, April 2, 2020 6:01 PM<br>
<b>To:</b> Eli Friedman <<a href="mailto:efriedma@quicinc.com">efriedma@quicinc.com</a>>; llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>><br>
<b>Cc:</b> <a href="mailto:aaron.smith@microsoft.com">aaron.smith@microsoft.com</a><br>
<b>Subject:</b> [EXT] RE: [llvm-dev] [RFC] [Windows SEH] Local_Unwind (Jumping out of a _finally) and -EHa (Hardware Exception Handling)<o:p></o:p></p>
</div>
</div>
<p class="MsoNormal" style="margin-left:.5in"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-left:.5in"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-left:.5in">Unwinding from SEH’s perspective is to invoke outer _finally.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-left:.5in">For C++ code, At the end of inner catch-handler, control directly passes back to t10:.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">If you have local variables with destructors, it doesn’t.  The destructors have to run first.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-bottom:12.0pt">If you have a local variable with a destructor, clang emits two calls to the destructor: one along the normal path, and one along the unwind path.   The goto jumps to the “normal” path destructor call, it calls
 the destructor, and then the code jumps from there to the final destination.<o:p></o:p></p>
<p class="MsoNormal" style="margin-bottom:12.0pt">[Ten]  right, that is fine. But the code never needs to invoke the outer catch-handler.  For SEH case, a goto out of a _finally needs to invoke outer _finally before landing at target label.  <o:p></o:p></p>
<p class="MsoNormal">Currently, we do the same thing for SEH: there’s a normal path and an unwind path.  We outline the code into a separate function, and call it from both paths.  This is essentially identical to what we do for try/catch.  There isn’t any
 obvious reason we can’t extend this to handle goto the same way.  In fact, clang already supports goto across a finally block:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">[Ten] that is different.  Another way to look at it; a catch-handler is the end of unwind process (assuming no rethrow).  When it’s done, the execution continues from the end of try or from the goto target.  The _finally handler in SEH
 is different. Before it reaches the except handler, a _finally handler is just ONE step of the unwind process.  Hence, if there is a goto out of in a finally, the remaining (outer) _finally handlers must be invoked to complete the unwinding.
<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:blue">void</span><span style="font-family:"Consolas\,";color:black"> f(</span><span style="font-family:"Consolas\,";color:blue">int</span><span style="font-family:"Consolas\,";color:black"> a);<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:blue">void</span><span style="font-family:"Consolas\,";color:black"> f(</span><span style="font-family:"Consolas\,";color:blue">int</span><span style="font-family:"Consolas\,";color:black"> ex, </span><span style="font-family:"Consolas\,";color:blue">int</span><span style="font-family:"Consolas\,";color:black"> lu, </span><span style="font-family:"Consolas\,";color:blue">int</span><span style="font-family:"Consolas\,";color:black"> lu2, </span><span style="font-family:"Consolas\,";color:blue">int</span><span style="font-family:"Consolas\,";color:black"> lu3) {<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:blue">__try</span><span style="font-family:"Consolas\,";color:black"> {  <o:p></o:p></span></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:black">  </span><span style="font-family:"Consolas\,";color:blue">__try</span><span style="font-family:"Consolas\,";color:black"> {<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:black">      f(ex);<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:black">  } </span><span style="font-family:"Consolas\,";color:blue">__except</span><span style="font-family:"Consolas\,";color:black"> (ex){<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:black">      </span><span style="font-family:"Consolas\,";color:blue">if</span><span style="font-family:"Consolas\,";color:black"> (lu3) </span><span style="font-family:"Consolas\,";color:blue">goto</span><span style="font-family:"Consolas\,";color:black"> T;<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:black">      f(lu);<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:black">  }  <o:p></o:p></span></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:black">} </span><span style="font-family:"Consolas\,";color:blue">__finally</span><span style="font-family:"Consolas\,";color:black"> {<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:black">    f(lu);<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:black">}  <o:p></o:p></span></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:black">T:;<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#FFFFFE"><span style="font-family:"Consolas\,";color:black">}<o:p></o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">(If the goto itself is in a finally block, it currently doesn’t work, but that’s a relatively minor detail.)<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">[Ten] it’s totally different.  The except handler is NOT a funclet(). It’s demoted back to host function. As such, the goto from the except handler to label T is visible to Optimizer.  A _finally is a funclet, i.e., a separate function. 
 A goto from a separate function is not visible to Optimizer and its effect is not modeled in IR today.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">This is not the same as what MSVC implements, but it isn’t obviously wrong.  If you’re going to write a bunch of new code to implement something else, you need to justify it.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">[Ten] the proposed design is not the same as MSVC either.  It’s the model developed to leverage and fit with LLVM EH framework.  <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoListParagraph" style="margin-left:1.0in;text-indent:-.25in;mso-list:l0 level1 lfo2">
<![if !supportLists]><span style="font-family:Wingdings"><span style="mso-list:Ignore">Ø<span style="font:7.0pt "Times New Roman""> 
</span></span></span><![endif]>If you call a nounwind function, the invoke will be transformed to a plain call.  And we’re likely to infer nounwind in many cases (for example, functions that don’t call any other functions).  There isn’t any way to stop this
 currently; I guess we could add one.<o:p></o:p></p>
<p class="MsoNormal" style="margin-left:.5in"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-left:.5in">For -EHa where HW exception must be handled, nounwind-attribute is ignored (or reset) for callees directly inside a _try. 
<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">In other words, you need to mark the calls “volatile”.  (You could try to track the region that’s inside the try block for transforms that care, but that’s more complicated for no benefit.)<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">[Ten] No, we can just remove the nounwind attribute for call-sites inside a _try, or add one more nohardware-exception-attribute to distinguish them.   <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Also, even if you block directly removing the unwind edge, passes like IPSCCP could still prove that the edge isn’t feasible and reason based on that.  So you really need to block all interprocedural transforms, not just ones that mess
 with the unwind edge.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">[Ten] Yes good point. More work may be still needed to make IPO optimization be aware of Hardware-exception and -EHa.
<o:p></o:p></p>
<p class="MsoNormal" style="margin-left:.5in"><o:p> </o:p></p>
<p class="MsoListParagraph" style="margin-left:1.0in;text-indent:-.25in;mso-list:l0 level1 lfo2">
<![if !supportLists]><span style="font-family:Wingdings"><span style="mso-list:Ignore">Ø<span style="font:7.0pt "Times New Roman""> 
</span></span></span><![endif]>I’m sort of unhappy with the fact that this is theoretically unsound, but maybe the extra effort isn’t worthwhile, as long as it doesn’t impact any transforms we realistically perform.  How much extra effort it would be sort of
 depends on what conclusion we reach for the “undefined behavior” part of this, which is really the part I’m more concerned about.<o:p></o:p></p>
<p class="MsoNormal" style="margin-left:.5in"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-left:.5in">Which part (-EHa or Local_unwind) is theoretically unsound to you?  Could you be more specific what UB problem could arise in this design?
<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">The unsoundness is the possibility of optimizations introducing local variables, which I mentioned before.  The resulting variables won’t use volatile load/store operations, so they won’t be properly preserved.  Actually, thinking about
 it a bit more, I’m not sure it’s completely theoretical; you could run into trouble with constant hoisting.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">[Ten] The purpose of preserving user variables is that when HW exception occurs, users’ filter & handler can read the correct and up-to-date global states (recorded in Local/Global/Heap).  Compiler temps need not be preserved.  Not sure
 I understand const-hoisting problem. Please be more specific.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">The UB problem is what I outlined in my very first reply.  You need to define some way that isn’t UB to trigger an exception, or else handling the resulting exception is formally meaningless.  If the behavior is undefined, it doesn’t matter
 what happens at that point.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">[Ten] A hardware exception occurs mostly due to users’ bug, like the dereference of a null pointer or divided-by-0.  When it happens today without -EHa, it causes an unhandled exception fault because users cannot handle it.   With -EHa,
 user can either handle it or gracefully terminate the program.  Does this answer your question?   Sorry, I don’t understand what you are asking for about UB.
<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">-Eli<o:p></o:p></p>
</div>
</body>
</html>