<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)">
<!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><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:Consolas;
panose-1:2 11 6 9 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:"Segoe UI";
panose-1:2 11 5 2 4 2 4 2 2 3;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
h1
{mso-style-priority:9;
mso-style-link:"Heading 1 Char";
mso-margin-top-alt:auto;
margin-right:0in;
mso-margin-bottom-alt:auto;
margin-left:0in;
font-size:24.0pt;
font-family:"Calibri",sans-serif;
font-weight:bold;}
h2
{mso-style-priority:9;
mso-style-link:"Heading 2 Char";
mso-margin-top-alt:auto;
margin-right:0in;
mso-margin-bottom-alt:auto;
margin-left:0in;
font-size:18.0pt;
font-family:"Calibri",sans-serif;
font-weight:bold;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:#0563C1;
text-decoration:underline;}
code
{mso-style-priority:99;
font-family:"Courier New";}
pre
{mso-style-priority:99;
mso-style-link:"HTML Preformatted Char";
margin:0in;
margin-bottom:.0001pt;
font-size:10.0pt;
font-family:"Courier New";}
span.Heading1Char
{mso-style-name:"Heading 1 Char";
mso-style-priority:9;
mso-style-link:"Heading 1";
font-family:"Calibri",sans-serif;
font-weight:bold;}
span.Heading2Char
{mso-style-name:"Heading 2 Char";
mso-style-priority:9;
mso-style-link:"Heading 2";
font-family:"Calibri",sans-serif;
font-weight:bold;}
span.HTMLPreformattedChar
{mso-style-name:"HTML Preformatted Char";
mso-style-priority:99;
mso-style-link:"HTML Preformatted";
font-family:"Courier New";}
span.EmailStyle26
{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:425687909;
mso-list-template-ids:1137708628;}
@list l0:level1
{mso-level-number-format:bullet;
mso-level-text:\F0B7;
mso-level-tab-stop:.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Symbol;}
@list l0:level2
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:1.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:"Courier New";
mso-bidi-font-family:"Times New Roman";}
@list l0:level3
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:1.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l0:level4
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:2.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l0:level5
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:2.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l0:level6
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:3.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l0:level7
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:3.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l0:level8
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:4.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l0:level9
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:4.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l1
{mso-list-id:782500857;
mso-list-template-ids:290343202;}
@list l1:level1
{mso-level-number-format:bullet;
mso-level-text:\F0B7;
mso-level-tab-stop:.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Symbol;}
@list l1:level2
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:1.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:"Courier New";
mso-bidi-font-family:"Times New Roman";}
@list l1:level3
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:1.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l1:level4
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:2.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l1:level5
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:2.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l1:level6
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:3.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l1:level7
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:3.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l1:level8
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:4.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l1:level9
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:4.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l2
{mso-list-id:1093277979;
mso-list-template-ids:-970583330;}
@list l2:level1
{mso-level-tab-stop:.5in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l2:level2
{mso-level-tab-stop:1.0in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l2:level3
{mso-level-tab-stop:1.5in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l2:level4
{mso-level-tab-stop:2.0in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l2:level5
{mso-level-tab-stop:2.5in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l2:level6
{mso-level-tab-stop:3.0in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l2:level7
{mso-level-tab-stop:3.5in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l2:level8
{mso-level-tab-stop:4.0in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l2:level9
{mso-level-tab-stop:4.5in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l3
{mso-list-id:1109397057;
mso-list-template-ids:749636470;}
@list l3:level1
{mso-level-number-format:bullet;
mso-level-text:\F0B7;
mso-level-tab-stop:.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Symbol;}
@list l3:level2
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:1.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:"Courier New";
mso-bidi-font-family:"Times New Roman";}
@list l3:level3
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:1.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l3:level4
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:2.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l3:level5
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:2.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l3:level6
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:3.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l3:level7
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:3.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l3:level8
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:4.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l3:level9
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:4.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l4
{mso-list-id:1507550541;
mso-list-template-ids:-157230040;}
@list l4:level1
{mso-level-number-format:bullet;
mso-level-text:\F0B7;
mso-level-tab-stop:.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Symbol;}
@list l4:level2
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:1.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:"Courier New";
mso-bidi-font-family:"Times New Roman";}
@list l4:level3
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:1.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l4:level4
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:2.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l4:level5
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:2.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l4:level6
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:3.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l4:level7
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:3.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l4:level8
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:4.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l4:level9
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:4.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l5
{mso-list-id:1539463238;
mso-list-template-ids:1851063386;}
@list l5:level1
{mso-level-number-format:bullet;
mso-level-text:\F0B7;
mso-level-tab-stop:.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Symbol;}
@list l5:level2
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:1.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:"Courier New";
mso-bidi-font-family:"Times New Roman";}
@list l5:level3
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:1.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l5:level4
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:2.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l5:level5
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:2.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l5:level6
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:3.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l5:level7
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:3.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l5:level8
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:4.0in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
font-family:Wingdings;}
@list l5:level9
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:4.5in;
mso-level-number-position:left;
text-indent:-.25in;
mso-ansi-font-size:10.0pt;
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">Hi, all,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">The intend of this thread is to complete the support for Windows SEH.
<o:p></o:p></p>
<p class="MsoNormal">Currently there are two major missing features: Jumping out of a _finally and Hardware exception handling. <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">The document below is my proposed design and implementation to fully support SEH on LLVM.
<o:p></o:p></p>
<p class="MsoNormal">I have completely implemented this design on a branch in repo: <a href="https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftentzen%2Fllvm-project&data=02%7C01%7Ctentzen%40microsoft.com%7Ced638e497aa74798b3f808d7d5e46775%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637213049272295023&sdata=Pd6gK%2B7JsIlfcyJLB%2FajWKdrbgqsITsseBfeB2Z5lgg%3D&reserved=0">https://github.com/tentzen/llvm-project</a>.
<o:p></o:p></p>
<p class="MsoNormal">It now passes MSVC’s in-house SEH suite. <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Sorry for this long write-up. For better readability, please read it on
<a href="https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftentzen%2Fllvm-project%2Fwiki&data=02%7C01%7Ctentzen%40microsoft.com%7Ced638e497aa74798b3f808d7d5e46775%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637213049272305020&sdata=SN9XBN6InU79U%2FEXnReyi9H1uPbVwTHgXhMkKODnA%2FM%3D&reserved=0">
https://github.com/tentzen/llvm-project/wiki</a><o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Special thanks to Joseph Tremoulet for his earlier comments and suggestions.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Note: I just subscribed llvm-dev, probably not in the list yet. So please reply with my email address (<a href="mailto:tentzen@microsoft.com">tentzen@microsoft.com</a>) explicitly in To-list. <o:p></o:p></p>
<p class="MsoNormal">Thanks,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">--Ten<o:p></o:p></p>
<div style="border:none;border-bottom:solid #EAECEF 1.0pt;padding:0in 0in 4.0pt 0in">
<h1 style="mso-margin-top-alt:.25in;margin-right:0in;margin-bottom:12.0pt;margin-left:0in">
<span style="font-size:22.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">Windows SEH Support in LLVM<o:p></o:p></span></h1>
<h2 style="mso-margin-top-alt:.25in;margin-right:0in;margin-bottom:12.0pt;margin-left:0in;box-sizing: border-box;orphans: 2;-webkit-text-stroke-width: 0px;word-spacing:0px">
<span style="font-size:16.5pt;font-family:"Segoe UI",sans-serif;color:#24292E">INTRODUCTION<o:p></o:p></span></h2>
</div>
<p style="mso-margin-top-alt:0in;margin-right:0in;margin-bottom:12.0pt;margin-left:0in;box-sizing: border-box;orphans: 2;-webkit-text-stroke-width: 0px;word-spacing:0px">
<span style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">An exception is an event that occurs during the execution of a program. It requires the execution of code outside the normal flow of control. There are two kinds of exceptions: hardware
exceptions and software exceptions. Hardware exceptions are initiated by the CPU, such as division by zero or an attempt to access an invalid memory address. Software exceptions are initiated explicitly by applications or the operating system. Windows SEH
(Structured exception handling) is a mechanism for handling both hardware and software exceptions. Windows C++ Exception Handling is almost fully supported in LLVM. Detailed design and new FuncletPad IR can be seen in
<a href="https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fllvm.org%2Fdocs%2FExceptionHandling.html%23exception-handling-using-the-windows-runtime&data=02%7C01%7Ctentzen%40microsoft.com%7Ced638e497aa74798b3f808d7d5e46775%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637213049272305020&sdata=skHY8qjtHYdwUzJ9uln4vc2di20e5Sa8%2B4%2FmFS2tQ0M%3D&reserved=0">
<span style="color:#0366D6">https://llvm.org/docs/ExceptionHandling.html#exception-handling-using-the-windows-runtime</span></a>.<br>
However, for SEH, LLVM today is missing two major features. This project intents to extend current model to achieve two missing features.<o:p></o:p></span></p>
<ol start="1" type="1">
<li class="MsoNormal" style="color:#24292E;mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l2 level1 lfo1;box-sizing: border-box">
<span style="font-size:12.0pt;font-family:"Segoe UI",sans-serif">Local Unwind (AKA: Jumping out of _finally)<o:p></o:p></span></li><li class="MsoNormal" style="color:#24292E;margin-top:3.0pt;mso-margin-bottom-alt:auto;mso-list:l2 level1 lfo1;box-sizing: border-box">
<span style="font-size:12.0pt;font-family:"Segoe UI",sans-serif">Hardware Exception Handling (AKA: MSVC++ option -EHa)<o:p></o:p></span></li></ol>
<div style="border:none;border-bottom:solid #EAECEF 1.0pt;padding:0in 0in 4.0pt 0in">
<h2 style="mso-margin-top-alt:.25in;margin-right:0in;margin-bottom:12.0pt;margin-left:0in;box-sizing: border-box;orphans: 2;-webkit-text-stroke-width: 0px;word-spacing:0px">
<span style="font-size:16.5pt;font-family:"Segoe UI",sans-serif;color:#24292E">LOCAL UNWIND<o:p></o:p></span></h2>
</div>
<p style="mso-margin-top-alt:0in;margin-right:0in;margin-bottom:12.0pt;margin-left:0in;box-sizing: border-box;orphans: 2;-webkit-text-stroke-width: 0px;word-spacing:0px">
<span style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">In Windows SEH when a goto statement (or whatever statement, like break/continue/leave/return, that changes control flow) in a _finally targeting a label outside of the _finally
clause, a “local-unwind” must be triggered to properly invoke _finally clauses alone the path from the goto statement to the target label. Since _finally clause can be executed in either “normal execution path” as well as “exception path”, the _local_unwind
can take place in both paths too.<br>
Let’s demonstrate all possible paths in the following example.<o:p></o:p></span></p>
<pre style="background:#F6F8FA;border-bottom-left-radius: 3px;border-bottom-right-radius: 3px;border-top-left-radius: 3px;border-top-right-radius: 3px;box-sizing: border-box;orphans: 2;overflow-wrap: normal;-webkit-text-stroke-width: 0px;overflow:auto;word-spacing:0px"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in">try {</span></code><code><span style="font-size:9.5pt;font-family:Consolas;border:none windowtext 1.0pt;padding:0in"><o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> try {<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> try {<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> /* set counter = 1 */<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> Counter += 1;<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> if (ex)<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> RtlRaiseException(&ExceptionRecord);<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> } finally {<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> Counter += 1;<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> if (abnormal_termination()) {<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> printf(" inner finally: exception path \n\r");<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> }<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> else {<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> printf(" inner finally: normal path \n\r");<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> }<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> if (lu) {<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> printf(" inner finally: local unwind \n\r");<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> goto t10;<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> }<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> printf(" inner finally: normal return \n\r");<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> }<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> } finally {<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> Counter += 1;<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> printf(" outer finally: \n\r");<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> }<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in">}<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in">except(Counter) {<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> /* set counter = 3 */<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> printf(" except handler: \n\r");<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> Counter += 1;<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in">}<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in">printf(" after outer try_except: \n\r");<o:p></o:p></span></code></pre>
<pre style="background:#F6F8FA"><code><span style="font-size:9.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in">t10:;<o:p></o:p></span></code></pre>
<ul type="disc">
<li class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l0 level1 lfo2;box-sizing: border-box">
<span style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">Normal execution (ex is false), normal return (lu is false): both _finallys are executed normally, but _except_handler should not be executed. Output is:</span><span style="font-size:12.0pt;font-family:"Segoe UI",sans-serif"><o:p></o:p></span></li></ul>
<p style="margin:0in;margin-bottom:.0001pt;box-sizing: border-box"><span style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">inner finally: normal path:<br>
inner finally: normal return:<br>
outer finally:<br>
after outer try_except:<o:p></o:p></span></p>
<ul type="disc">
<li class="MsoNormal" style="color:#24292E;mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l4 level1 lfo3;box-sizing: border-box">
<span style="font-size:12.0pt;font-family:"Segoe UI",sans-serif">Normal execution (ex is false), local-unwind (lu is true): both _finallys are executed, due to local-unwind, control jumps to $t10, “after outer try_except” is not printed.<o:p></o:p></span></li></ul>
<p style="margin:0in;margin-bottom:.0001pt;box-sizing: border-box"><span style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">inner finally: normal path:<br>
inner finally: local unwind:<br>
outer finally:<o:p></o:p></span></p>
<ul type="disc">
<li class="MsoNormal" style="color:#24292E;mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;mso-list:l3 level1 lfo4;box-sizing: border-box">
<span style="font-size:12.0pt;font-family:"Segoe UI",sans-serif">Exception execution (ex is true), normal return (lu is false): Windows runtime found the handler. It invokes inner _finally and outer _finally, then except-handler and jump to continue address,
end of outer-try.<o:p></o:p></span></li></ul>
<p style="margin:0in;margin-bottom:.0001pt;box-sizing: border-box"><span style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">inner finally: exception path:<br>
inner finally: normal return:<br>
outer finally:<br>
except handler:<br>
after outer try_except:<o:p></o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:30.0pt;text-indent:-.25in;mso-list:l5 level1 lfo5">
<![if !supportLists]><span lang="EN" style="font-size:10.0pt;font-family:Symbol;color:#24292E"><span style="mso-list:Ignore">·<span style="font:7.0pt "Times New Roman"">
</span></span></span><![endif]><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">Exception execution (ex is true), local-unwind (lu is true): Windows runtime found the handler. It invokes inner _finally where _local_unwind
is kicked off. It unwinds to outer _finally then jump to target label, $t10. Again, “after outer try_except” is not printed.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">inner finally: exception path:<br>
inner finally: local unwind:<br>
outer finally:<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">To perform local unwind, Windows provides a _local_unwind() runtime function that requires two input parameters: the target
label address and the stack frame. Note that the 2nd parameter is ‘Establisher’s stack pointer, not a frame-pointer/base-pointer. With that all we need is to turn a goto statement into a _local_unwind() invoke. Since the target label is beyond function (_funclet)
boundary, the target label must also be declared as a static global label (a MCSymbol in LLVM) that need be fixed up by Linker.<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:.25in;margin-right:0in;margin-bottom:12.0pt;margin-left:0in">
<b><span lang="EN" style="font-size:15.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">IR modeling for Optimizer:<o:p></o:p></span></b></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">While transferring a goto statement into a runtime function call/invoke is straight forward, another more complicate issue
is how to model _local_unwind in IR so that Optimizer can see its control flows. In #2 case of above example, the control flowing from normal execution inner _finlly, passing through outer _finally, and landing in $t10 cannot be represented by LLVM IR today.
Similarly in #4, the control starting from RtlRaiseException() passing through both _finally funclets then landing in $t10 was not seen.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">To precisely represent _local_unwind flow, our proposed solution is:<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:30.0pt;text-indent:-.25in;mso-list:l1 level1 lfo6">
<![if !supportLists]><span lang="EN" style="font-size:10.0pt;font-family:Symbol;color:#24292E"><span style="mso-list:Ignore">·<span style="font:7.0pt "Times New Roman"">
</span></span></span><![endif]><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">Add one more catchpad/catchret pair that forwards control to local_unwind target. I.e., this extra Catchpad is the reentrance point for the
_local_unwind() runtime.<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:30.0pt;text-indent:-.25in;mso-list:l1 level1 lfo6">
<![if !supportLists]><span lang="EN" style="font-size:10.0pt;font-family:Symbol;color:#24292E"><span style="mso-list:Ignore">·<span style="font:7.0pt "Times New Roman"">
</span></span></span><![endif]><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">This catchpad address is used to pass to _local_unwind() runtime, instead of the original goto target address.<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:30.0pt;text-indent:-.25in;mso-list:l1 level1 lfo6">
<![if !supportLists]><span lang="EN" style="font-size:10.0pt;font-family:Symbol;color:#24292E"><span style="mso-list:Ignore">·<span style="font:7.0pt "Times New Roman"">
</span></span></span><![endif]><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">The local_unwind catchpad will be handled the same way as _except-handler; it will not become a funclet, instead it’s demoted to a normal
label in parent function.<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:30.0pt;text-indent:-.25in;mso-list:l1 level1 lfo6">
<![if !supportLists]><span lang="EN" style="font-size:10.0pt;font-family:Symbol;color:#24292E"><span style="mso-list:Ignore">·<span style="font:7.0pt "Times New Roman"">
</span></span></span><![endif]><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">During LLVM BE code-gen and code layout pass, the Catchpad (local_unwind dispatching) block must be assigned the same EH state as the original
goto target so that the local unwinding can be correctly landing at the right EH scope.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">For example, the IR of above example today is briefly listed below.<o:p></o:p></span></p>
<div style="margin-top:.25in;margin-bottom:.25in">
<div class="MsoNormal" align="center" style="text-align:center"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">
<hr size="2" width="100%" align="center">
</span></div>
</div>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">define dso_local i32 @main() #0 personality i8* bitcast (i32 (...)* @__C_specific_handler<br>
..<br>
%28 = invoke i32 bitcast (i32 (...)* @RtlRaiseException to<br>
to label %29 unwind label %35,<br>
; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:29: ; preds = %27<br>
br label %30,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:30:
; preds = %29, %15<br>
%31 = call i8* @llvm.localaddress(),<br>
invoke void @"?fin@0@main@@"(i8 0, i8* %31) #7<br>
to label %32 unwind label %39,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:32:
; preds = %30<br>
%33 = call i8* @llvm.localaddress(),<br>
invoke void @"?fin@0@main@@"(i8 0, i8* %33) #7<br>
to label %34 unwind label %43,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:34:
; preds = %32<br>
br label %53,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:35:
; preds = %27<br>
%36 = cleanuppad within none [],<br>
%37 = call i8* @llvm.localaddress(),<br>
invoke void @"?fin@0@main@@"(i8 1, i8* %37) #7 [ "funclet"(token %36) ]<br>
to label %38 unwind label %39,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:38:
; preds = %35<br>
cleanupret from %36 unwind label %39,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:39:
; preds = %38, %35, %30<br>
%40 = cleanuppad within none [],<br>
%41 = call i8* @llvm.localaddress(),<br>
invoke void @"?fin@0@main@@"(i8 1, i8* %41) #7 [ "funclet"(token %40) ]<br>
to label %42 unwind label %43,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:42:
; preds = %39<br>
cleanupret from %40 unwind label %43,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:43:
; preds = %42, %39, %32<br>
%44 = catchswitch within none [label %45] unwind to caller,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:45:
; preds = %43<br>
%46 = catchpad within %44 [i8* bitcast (i32 (i8*, i8*)* @"?filt@0@main@@" to i8*)],<br>
catchret from %46 to label %47,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:47:
; preds = %45<br>
// except handler block<br>
..<br>
br label %53, !dbg !155<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:53:
; preds = %47, %34<br>
// after outer _try block<br>
.. br label %56, !dbg !156<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:t10:<br>
.. ..<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">define internal void @"?fin@0@main@@"(i8, i8* %1) #2 {<br>
..<br>
%2 = blockaddress($main, $t10)<br>
call void @"?local_unwind@@"(i8* %1, i8* %2)<o:p></o:p></span></p>
<div style="margin-top:.25in;margin-bottom:.25in">
<div class="MsoNormal" align="center" style="text-align:center"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">
<hr size="2" width="100%" align="center">
</span></div>
</div>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">The new IR is illustrated below. Changes are highlighted in
<b>bold</b>:<o:p></o:p></span></p>
<div style="margin-top:.25in;margin-bottom:.25in">
<div class="MsoNormal" align="center" style="text-align:center"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">
<hr size="2" width="100%" align="center">
</span></div>
</div>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">define dso_local i32 @main() #0 personality i8* bitcast (i32 (...)* @__C_specific_handler<br>
..<br>
%28 = invoke i32 bitcast (i32 (...)* @RtlRaiseException to<br>
to label %29 unwind label %35,<br>
; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:29: ; preds = %27<br>
br label %30,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:30:
; preds = %29, %15<br>
%31 = call i8* @llvm.localaddress(),<br>
invoke void @"?fin@0@main@@"(i8 0, i8* %31) #7<br>
to label %32 unwind label %39,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:32:
; preds = %30<br>
%33 = call i8* @llvm.localaddress(),<br>
invoke void @"?fin@0@main@@"(i8 0, i8* %33) #7<br>
to label %34 unwind label %43,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:34:
; preds = %32<br>
br label %53,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:35:
; preds = %27<br>
%36 = cleanuppad within none [],<br>
%37 = call i8* @llvm.localaddress(),<br>
invoke void @"?fin@0@main@@"(i8 1, i8* %37) #7 [ "funclet"(token %36) ]<br>
to label %38 unwind label %39,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:38:
; preds = %35<br>
cleanupret from %36 unwind label %39,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:39:
; preds = %38, %35, %30<br>
%40 = cleanuppad within none [],<br>
%41 = call i8* @llvm.localaddress(),<br>
invoke void @"?fin@0@main@@"(i8 1, i8* %41) #7 [ "funclet"(token %40) ]<br>
to label %42 unwind label %43,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:42:
; preds = %39<br>
cleanupret from %40 unwind label %43,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:43:
; preds = %42, %39, %32<br>
%44 = catchswitch within none [label %45, <b>label %60</b>] unwind to caller,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:45:
; preds = %43<br>
%46 = catchpad within %44 [i8* bitcast (i32 (i8*, i8*)* @"?filt@0@main@@" to i8*)],<br>
catchret from %46 to label %47,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">;
<b><</b></span><b><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span></b><b><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:60: ; preds = %43</span></b><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D"><br>
<b>%61 = catchpad within %44</b> [i8* bitcast (i32 (i8*, i8*)* @"?IsLocalUnwind@0@main@@" to i8*)]<br>
<b>catchret from %61 to label %t10</b><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:47:
; preds = %45<br>
// except handler block<br>
..<br>
br label %53,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:53:
; preds = %47, %34<br>
// after outer _try block<br>
..<br>
br label %56,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:t10:<br>
.. ..<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">define internal void @"?fin@0@main@@"(i8, i8* %1) #2 {<br>
..<br>
%2 = blockaddress($main, <b>%60</b>)<br>
call void @"?local_unwind@@"(i8* %1, i8* %2)<o:p></o:p></span></p>
<div style="margin-top:.25in;margin-bottom:.25in">
<div class="MsoNormal" align="center" style="text-align:center"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">
<hr size="2" width="100%" align="center">
</span></div>
</div>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">Note that @"?IsLocalUnwind@0@main@@" is a funclet, similar to @"?filt$0@0@main@@" of _except handler. The difference is
that "?IsLocalUnwind@0@main@@" is a dummy one which is never being called/checked by any runtime. It's there to make IR more readable and consistent with existing model. However, unlike ?filt$0@0@main@@ that will be referenced by EH table (for 1st pass, virtual
unwind), "?IsLocalUnwind@0@main@@" will be discarded by BE. At the end, there will not be a funclet generated in the output object file.<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:.25in;margin-right:0in;margin-bottom:12.0pt;margin-left:0in">
<b><span lang="EN" style="font-size:15.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">Dispatch on Try-Finally<o:p></o:p></span></b></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">When the outermost _try is a _finally, not an _excecpt construct, a pseudo _try/_except is added to dispatch _local_unwind.
This try-except has one constant filter EXCEPTION_CONTINUE_SEARCH, so from functional perspective, it’s virtually a NOP _try. Its only purpose is to model _local_unwind() exception path.<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:.25in;margin-right:0in;margin-bottom:12.0pt;margin-left:0in">
<b><span lang="EN" style="font-size:15.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">Multiple Local-Unwinds<o:p></o:p></span></b></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">If there exists two or more local_unwind targets, one catchpad/catchret pair is injected for each target. The catchpad/catchret
must be added at the same _try scope as its corresponding target label. For example,<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in">Try {
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> try {
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> try { /* inner try */
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> if (ex)
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> RtlRaiseException(&ExceptionRecord);
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> } finally {
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> if (lu)
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> goto t10;
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> else if (lu2)
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> goto t20;
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> else if (lu3)
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> goto t30
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> printf(" inner finally: normal return \n\r");
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> }
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> } except(Counter) {
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> /* inner handler */
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> }
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> // after inner handler
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> t10:
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> …
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> t20:
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> ..
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in">except(1) {
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in"> /* outer handler */
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in">}
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in">// after outer try
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in">t30:
<o:p></o:p></span></p>
<p class="MsoNormal" style="background:#F6F8FA"><span lang="EN" style="font-size:8.5pt;font-family:Consolas;color:#24292E;border:none windowtext 1.0pt;padding:0in">// after t30
<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">The corresponding IR is listed below. It must be the
<b>2nd _try</b> to dispatch the local unwind to t10 and t20.<o:p></o:p></span></p>
<div style="margin-top:.25in;margin-bottom:.25in">
<div class="MsoNormal" align="center" style="text-align:center"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">
<hr size="2" width="100%" align="center">
</span></div>
</div>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">%12 = invoke i32 bitcast (i32 (...)* @RtlRaiseException to i32<br>
to label %13 unwind label %16,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:13:
; preds = %0<br>
%14 = call i8* @llvm.localaddress(),<br>
invoke void @"?fin@0@main@@"(i8 0, i8* %14) #7<br>
to label %15 unwind label %20,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:15:
; preds = %13<br>
br label %31,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:16:
; preds = %0<br>
%17 = cleanuppad within none [],<br>
%18 = call i8* @llvm.localaddress(),<br>
invoke void @"?fin@0@main@@"(i8 1, i8* %18) #7 [ "funclet"(token %17) ]<br>
to label %19 unwind label %20,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:19:
; preds = %16<br>
cleanupret from %17 unwind label %20,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:20:
; preds = %19, %16, %13<br>
%21 = catchswitch within none [label %22, <b>label %110, label %120</b>] unwind label %34,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:22:
; preds = %20<br>
%23 = catchpad within %21 [i8* bitcast (i32 (i8*, i8*)* @"?filt@0@main@@" to i8*)],<br>
catchret from %23 to label %24,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">;
<b><</b></span><b><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span></b><b><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:110:</span></b><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">
; preds = %20<br>
<b>%23 = catchpad within %21</b> [i8* bitcast (i32 (i8*, i8*)* @"?IslocalUnwindt10@0@main@@" to i8*)],<br>
<b>catchret from %23 to label %t10</b><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">;
<b><</b></span><b><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span></b><b><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:120:</span></b><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">
; preds = %20<br>
<b>%23 = catchpad within %21</b> [i8* bitcast (i32 (i8*, i8*)* @"?IslocalUnwindt20@0@main@@" to i8*)],<br>
<b>catchret from %23 to label %t20</b><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:24:
; preds = %22<br>
// inner handler<br>
%27 = invoke i32 (i8*, ...) @printf(i8* getelementptr inbounds ([31 x i8], [31 x i8]*<br>
to label %28 unwind label %34,<br>
; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:28: ; preds = %24<br>
.. ..<br>
br label %31,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:31:
; preds = %28, %15<br>
// after inner handler<br>
%33 = invoke i32 (i8*, ...) @printf(i8* ..<br>
to label %49 unwind label %34,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:34:
; preds = %31, %24, %20<br>
%35 = catchswitch within none [label %36, <b>label %130</b>] unwind to caller,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:36:
; preds = %34<br>
%37 = catchpad within %35 [i8* null],<br>
catchret from %37 to label %38,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">;
<b><</b></span><b><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span></b><b><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:130:</span></b><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">
; preds = %34<br>
<b>%37 = catchpad within %35</b> [i8* bitcast (i32 (i8*, i8*)* @"?IslocalUnwindt30@0@main@@" to],<br>
<b>catchret from %37 to label %t30</b><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:38:
; preds = %36 // outer handler %41 = call i32 (i8*, ...) @printf(i8*..<br>
br label %42,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:42:
; preds = %38, %53<br>
// after outer try<br>
%44 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]*<br>
br label %t30,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:t30:
; preds = %42<br>
// after t30<br>
ret<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:49:
; preds = %31<br>
br label %t10,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:t10:
; preds = %49<br>
%51 = load i32, i32* %3, align 4,<br>
%52 = add nsw i32 %51, 10,<br>
store i32 %52, i32* %3, align 4,<br>
br label %t20,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">; <</span><span lang="EN" style="font-size:10.0pt;font-family:Consolas;color:#6A737D">label</span><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">>:t20:
; preds = %t10<br>
%54 = load i32, i32* %3, align 4,<br>
%55 = add nsw i32 %54, 20,<br>
store i32 %55, i32* %3, align 4,<br>
br label %42, !dbg !143<br>
}<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#6A737D">define internal void @"?fin@0@main@@"(i8, i8* %1) #2 {<br>
..<br>
%2 = blockaddress($main, <b>%110</b>)<br>
call void @"?local_unwind@@"(i8* %1, i8* %2)<br>
..<br>
%2 = blockaddress($main, <b>%120</b>)<br>
call void @"?local_unwind@@"(i8* %1, i8* %2)<br>
..<br>
%2 = blockaddress($main, <b>%130</b>)<br>
call void @"?local_unwind@@"(i8* %1, i8* %2)<br>
..<o:p></o:p></span></p>
<div style="margin-top:.25in;margin-bottom:.25in">
<div class="MsoNormal" align="center" style="text-align:center"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">
<hr size="2" width="100%" align="center">
</span></div>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:.25in;margin-right:0in;margin-bottom:12.0pt;margin-left:0in">
<b><span lang="EN" style="font-size:15.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">Implementation:<o:p></o:p></span></b></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">The first primary task of the design above is to determine the right place to add this pseudo 'catchwitch' construct in
order to dispatch a local unwind to its target. One straight forward way is to add this new level immediately on top of the outermost _try that
<b>encloses the local-unwind statement and locates in the same EH scope as the unwind target</b>.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">Since semantic analysis and scope information are well constructed and performed in Clang’s Parser/Semantic-analyzer, the
implementation just need to slightly extend existent code to identifies local unwind statements and record LU targets in the outermost SEHTryStmt during Parser/Semantic phase.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">For Break/Continue/Leave/Return local unwind, please see Sema::ActOnBreakStmt() and Sema::ActOnContinueStmt() and Parser::ParseSEHTryBlock().
For Goto local unwind, it's more complicated as it could be a forward reference. Our code utilizes JumpDiagnostics.cpp where Goto out of _finally is detected and reported. Please see the change in JumpScopeChecker::CheckJump().<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">The second task is in FE CodeGen. Before entering the Try, an extra EHCatchScope level is pushed into EHStack. Based on
LU information recorded on SEHTryStmt by earlier Parser & Semantic phases, a handler (Catchpad) is created to dispatch local-unwind for each target associated with this Try statement. This handler block will be used as the target-address for MSVC's _local_unwind()
runtime. See CodeGenFunction::pushSEHLocalUnwind() and CodeGenFunction::popSEHLocalUnwind().<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">Finally in LLVM calculateSEHStateNumbers() (see the change in WinEHPrepare.cpp), all _IsLocalUnwind**() filters in pseudo
CatchSwitches are discarded and all LU dispatch handlers are assigned to its parent scope’s EH state.<o:p></o:p></span></p>
<div style="border:none;border-bottom:solid #EAECEF 1.0pt;padding:0in 0in 4.0pt 0in">
<p class="MsoNormal" style="mso-margin-top-alt:.25in;margin-right:0in;margin-bottom:12.0pt;margin-left:0in">
<b><span lang="EN" style="font-size:18.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">HARDWARE EXCEPTION HANDLING (-EHA)<o:p></o:p></span></b></p>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:.25in;margin-right:0in;margin-bottom:12.0pt;margin-left:0in">
<b><span lang="EN" style="font-size:15.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">The rules for C code:<o:p></o:p></span></b></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">For C-code, one way (MSVC approach) to achieve SEH -EHa semantic is to follow three rules. First, no exception can move
in or out of _try region., i.e., no "potential faulty instruction can be moved across _try boundary. Second, the order of exceptions for instructions 'directly' under a _try must be preserved (not applied to those in callees). Finally, global states (local/global/heap
variables) that can be read outside of _try region must be updated in memory (not just in register) before the subsequent exception occurs.<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:.25in;margin-right:0in;margin-bottom:12.0pt;margin-left:0in">
<b><span lang="EN" style="font-size:15.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">The impact to C++ code:<o:p></o:p></span></b></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">Although SEH is a feature for C code, -EHa does have a profound effect on C++ side. When a C++ function (in the same compilation
unit with option -EHa ) is called by a SEH C function, a hardware exception occurs in C++ code can also be handled properly by an upstream SEH _try-handler or a C++ catch(…). As such, when that happens in the middle of an object’s life scope, the dtor must
be invoked the same way as C++ Synchronous Exception during unwinding process.<o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:.25in;margin-right:0in;margin-bottom:12.0pt;margin-left:0in">
<b><span lang="EN" style="font-size:15.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">Design and Implementation:<o:p></o:p></span></b></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">A natural way to achieve the rules above in LLVM today is to allow an EH edge added on memory/computation instruction (previous
iload/istore idea) so that exception path is modeled in Flow graph preciously. However, tracking every single memory instruction and potential faulty instruction can create many Invokes, complicate flow graph and possibly result in negative performance impact
for downstream optimization and code generation. Making all optimizations be aware of the new semantic is also substantial.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">This design does not intend to model exception path at instruction level. Instead, the proposed design tracks and reports
EH state <b>at BLOCK-level</b> to reduce the complexity of flow graph and minimize the performance-impact on CPP code under -EHa option. Detailed implementation described below.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">-- Two intrinsic are created to track CPP object scopes;
<b>eha_scope_begin() and eha_scope_end()</b>. _scope_begin() is immediately added after ctor() is called and EHStack is pushed. So it must be an invoke, not a call. With that it's also guaranteed an EH-cleanup-pad is created regardless whether there exists
a call in this scope. _scope_end is added before dtor(). These two intrinsics make the computation of Block-State possible in downstream code gen pass, even in the presence of ctor/dtor inlining.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">-- Two intrinsic,
<b>seh_try_begin() and seh_try_end()</b>, are added for C-code to mark _try boundary and to prevent from exceptions being moved across _try boundary.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">-- All memory instructions inside a _try are considered as 'volatile' to assure 2nd and 3rd rules for C-code above. This
is a little sub-optimized. But it's acceptable as the amount of code directly under _try is very small.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">-- For both C++ & C-code, the state of each block is computed at the same place in BE (WinEHPreparing pass) where all other
EH tables/maps are calculated. In addition to _scope_begin & _scope_end, the computation of block state also rely on the existing State tracking code (UnwindMap and InvokeStateMap).<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">-- For both C++ & C-code, the state of each block with potential trap instruction is marked and reported in DAG Instruction
Selection pass, the same place where the state for -EHsc (synchronous exceptions) is done.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">-- If the first instruction in a reported block scope can trap, a Nop is injected before this instruction. This nop is
needed to accommodate LLVM Windows EH implementation, in which the address in IPToState table is offset by +1. (note the purpose of that is to ensure the return address of a call is in the same scope as the call address.<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-bottom:7.5pt"><span lang="EN" style="font-size:12.0pt;font-family:"Segoe UI",sans-serif;color:#24292E">-- The handler for catch(...) for -EHa must handle HW exception. So it is 'adjective' flag is reset (it cannot be IsStdDotDot
(0x40) that only catches C++ exceptions).<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN"><o:p> </o:p></span></p>
</div>
</body>
</html>