<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=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@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;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri","sans-serif";}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></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="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Hi,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Thanks for sending this out.  We're looking forward to seeing this come about, since we need funclet separation for LLILC as well (and I have cycles to spend
 on it, if that would be helpful).<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Some questions about the new proposal:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">- Do the new forms of resume have any implied read/write side-effects, or do they work just like a branch?  In particular, I'm wondering what prevents reordering
 a call across a resume.  Is this just something that code motion optimizations are expected to check for explicitly to avoid introducing UB per the "Executing such an invoke [or call] that does not transitively unwind to the correct catchend block has undefined
 behavior" rule?<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">- Does LLVM already have other examples of terminators that are glued to the top of their basic blocks, or will these be the first?  I ask because it's a somewhat
 nonstandard thing (a block in the CFG that can't have instructions added to it) that any code placement algorithms (PRE, PGO probe insertion, Phi elimination, RA spill/copy placement, etc.) may need to be adjusted for.  The adjustments aren't terrible (conceptually
 it's no worse than having unsplittable edges from each of the block's preds to each of its succs), but it's something to be aware of.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">- Since this will require auditing any code with special processing of resume instructions to make sure it handles the new resume forms correctly, I wonder
 if it might be helpful to give resume (or the new forms of it) a different name, since then it would be immediately clear which code has/hasn't been updated to the new model.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">- Is the idea that a resume (of the sort that resumes normal execution) ends only one catch/cleanup, or that it can end any number of them?  Did you consider
 having it end a single one, and giving it a source that references (in a non-flow-edge-inducing way) the related catchend?  If you did that, then:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">+ The code to find a funclet region could terminate with confidence when it reaches this sort of resume, and<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">+ Resumes which exit different catches would have different sources and thus couldn't be merged, reducing the need to undo tail-merging with code duplication
 in EH preparation (by blocking the tail-merging in the first place)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">- What is the plan for cleanup/__finally code that may be executed on either normal paths or EH paths?  One could imagine a number of options here:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">+ require the IR producer to duplicate code for EH vs non-EH paths<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">+ duplicate code for EH vs non-EH paths during EH preparation<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">+ use resume to exit these even on the non-EH paths; code doesn't need to be duplicated (but could and often would be as an optimization for hot/non-EH paths),
 and normal paths could call the funclet at the end of the day<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">and it isn't clear to me which you're suggesting.  Requiring duplication can worst-case quadratically expand the code (in that if you have n levels of cleanup-inside-cleanup-inside-cleanup-…,
 and each cleanup has k code bytes outside the next-inner cleanup, after duplication you'll have k*n + k*(n-1) + … or O(k*n^2) bytes total [compared to k*n before duplication]), which I'd think could potentially be a problem in pathological inputs.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Thanks<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">-Joseph<o:p></o:p></span></p>
<p class="MsoNormal"><a name="_MailEndCompose"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></a></p>
<p class="MsoNormal"><b><span style="font-size:11.0pt;font-family:"Calibri","sans-serif"">From:</span></b><span style="font-size:11.0pt;font-family:"Calibri","sans-serif""> llvmdev-bounces@cs.uiuc.edu [mailto:llvmdev-bounces@cs.uiuc.edu]
<b>On Behalf Of </b>Reid Kleckner<br>
<b>Sent:</b> Friday, May 15, 2015 6:38 PM<br>
<b>To:</b> LLVM Developers Mailing List; Bill Wendling; Nick Lewycky; Kaylor, Andrew<br>
<b>Subject:</b> [LLVMdev] RFC: New EH representation for MSVC compatibility<o:p></o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div>
<p class="MsoNormal">After a long tale of sorrow and woe, my colleagues and I stand here before you defeated. The Itanium EH representation is not amenable to implementing MSVC-compatible exceptions. We need a new representation that preserves information about
 how try-catch blocks are nested.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">WinEH background<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">-------------------------------<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Skip this if you already know a lot about Windows exceptions. On Windows, every exceptional action that you can imagine is a function call. Throwing an exception is a call. Destructor cleanups and finally blocks are calls to outlined functions
 that run the cleanup code. Even catching an exception is implemented as an outlined catch handler function which returns the address of the basic block at which normal execution should continue.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">This is *not* how Itanium landingpads work, where cleanups and catches are executed after unwinding and clearing old function frames off the stack. The transition to a landingpad is *not* like a function call, and this is the only special
 control transfer used for Itanium EH. In retrospect, having exactly one kind of control transfer turns out to be a great design simplification. Go Itanium!<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Instead, all MSVC EH personality functions (x86, x64, ARM) cross (C++, SEH) are implemented with interval tables that express the nesting levels of various source constructs like destructors, try ranges, catch ranges, etc. When you rinse
 your program through LLVM IR today, this structure is what gets lost.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">New information<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">-------------------------<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Recently, we have discovered that the tables for __CxxFrameHandler3 have the additional constraint that the EH states assigned to a catch body must immediately follow the state numbers assigned to the try body. The natural scoping rules
 of C++ make it so that doing this numbering at the source level is trivial, but once we go to LLVM IR CFG soup, scopes are gone. If you want to know exactly what corner cases break down, search the bug database and mailing lists. The explanations are too long
 for this RFC.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">New representation<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">------------------------------<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">I propose adding the following new instructions, all of which (except for resume) are glued to the top of their basic blocks, just like landingpads. They all have an optional ‘unwind’ label operand, which provides the IR with a tree-like
 structure of what EH action to take after this EH action completes. The unwind label only participates in the formation of the CFG when used in a catch block, and in other blocks it is considered opaque, personality-specific information. If the unwind label
 is missing, then control leaves the function after the EH action is completed. If a function is inlined, EH blocks with missing unwind labels are wired up to the unwind label used by the inlined call site.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">The new representation is designed to be able to represent Itanium EH in case we want to converge on a single EH representation in LLVM and Clang. An IR pass can convert these actions to landingpads, typeid selector comparisons, and branches,
 which means we can phase this representation in on Windows at first and experiment with it slowly on other platforms. Over time, we can move the landingpad conversion lower and lower in the stack until it’s moved into DwarfEHPrepare. We’ll need to support
 landingpads at least until LLVM 4.0, but we may want to keep them because they are the natural representation for Itanium-style EH, and have a relatively low support burden.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">resume<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">-------------<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">; Old form still works, still means control is leaving the function.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">resume <valty> %val<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">; New form overloaded for intra-frame unwinding or resuming normal execution<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">resume <valty> %val, label %nextaction<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">; New form for EH personalities that produce no value<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">resume void<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Now resume takes an optional label operand which is the next EH action to run. The label must point to a block starting with an EH action. The various EH action blocks impose personality-specific rules about what the targets of the resume
 can be.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">catchblock<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">---------------<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">%val = catchblock <valty> [i8* @<a href="http://typeid.int">typeid.int</a>, i32 7, i32* %e.addr]<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    to label %<a href="http://catch.int">catch.int</a> unwind label %nextaction<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">The catchblock is a terminator that conditionally selects which block to execute based on the opaque operands interpreted by the personality function. If the exception is caught, the ‘to’ block is executed. If unwinding should continue,
 the ‘unwind’ block is executed. Because the catchblock is a terminator, no instructions can be inserted into a catchblock. The MSVC personality function requires more than just a pointer to RTTI data, so a variable list of operands is accepted. For an Itanium
 personality, only one RTTI operand is needed. The ‘unwind’ label of a catchblock must point to a catchend.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">catchendblock<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">----------------<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">catchend unwind label %nextaction<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">The catchend is a terminator that unconditionally unwinds to the next action. It is merely a placeholder to help reconstruct which invokes were part of the catch blocks of a try. Invokes that are reached after a catchblock without following
 any unwind edges must transitively unwind to the first catchend block that the catchblock unwinds to. Executing such an invoke that does not transitively unwind to the correct catchend block has undefined behavior.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">cleanupblock<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">--------------------<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">%val = cleanupblock <valty> unwind label %nextaction<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">This is not a terminator, and control is expected to flow into a resume instruction which indicates which EH block runs next. If the resume instruction and the unwind label disagree, behavior is undefined.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">terminateblock<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">----------------------<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">; for noexcept<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">terminateblock [void ()* @std.terminate] unwind label %nextaction<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">; for exception specifications, throw(int)<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">terminateblock [void ()* @__cxa_unexpected, @<a href="http://typeid.int">typeid.int</a>, ...] unwind label %nextaction<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">This is a terminator, and the unwind label is where execution will continue if the program continues execution. It also has an opaque, personality-specific list of constant operands interpreted by the backend of LLVM. The convention is
 that the first operand is the function to call to end the program, and the rest determine if the program should end.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">sehfilterblock?<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">------------------<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">One big hole in the new representation is SEH filter expressions. They present a major complication because they do not follow a stack discipline. Any EH action is reachable after an SEH filter runs. Because the CFG is so useless for optimization
 purposes, it’s better to outline the filter in the frontend and assume the filter can run during any potentially throwing function call.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">MSVC EH implementation strategy<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">----------------------------------------------<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Skim this if you just need the semantics of the representation above, and not the implementation details.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">The new EH block representation allows WinEHPrepare to get a lot simpler. EH blocks should now look a lot more familiar, they are single entry, multi-exit regions of code. This is exactly equivalent to a function, and we can call them funclets.
 The plan is to generate code for the parent function first, skipping all exceptional blocks, and then generate separate MachineFunctions for each subfunction in turn. I repeat, we can stop doing outlining in IR. This was just a mistake, because I was afraid
 of grappling with CodeGen.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">WinEHPrepare will have two jobs now:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">1. Mark down which basic blocks are reachable from which handler. Duplicate any blocks that are reachable from two handlers until each block belongs to exactly one funclet, pruning as many unreachable CFG edges as possible.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">2. Demote SSA values that are defined in a funclet and used in another funclet.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">The instruction selection pass is the pass that builds MachineFunctions from IR Functions. This is the pass that will be responsible for the split. It will maintain information about the offsets of static allocas in FunctionLoweringInfo,
 and will throw it away when all funclets have been generated for this function. This means we don’t need to insert framerecover calls anymore.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Generating EH state numbers for the TryBlockMap and StateUnwindTable is a matter of building a tree of EH blocks and invokes. Every unwind edge from an invoke or an EH block represents that the instruction is a child of the target block.
 If the unwind edge is empty, it is a child of the parent function, which is the root node of the tree. State numbers can be assigned by doing a DFS traversal where invokes are visited before EH blocks, and EH blocks can be visited in an arbitrary-but-deterministic
 order that vaguely corresponds to source order. Invokes are immediately assigned the current state number. Upon visiting an EH block, the state number is recorded as the “low” state of the block. All invokes are assigned this state number. The state number
 is incremented, and each child EH block is visited, passing in the state number and producing a new state number. The final state number is returned to the parent node.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Example IR from Clang<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">----------------------------------------<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">The C++:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">struct Obj { ~Obj(); };<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">void f(int);<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">void foo() noexcept {<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  try {<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    f(1);<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    Obj o;<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    f(2);<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  } catch (int e) {<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    f(3);<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    try {<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">      f(4);<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    } catch (...) {<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">      f(5);<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    }<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  }<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">}<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">The IR for __CxxFrameHandler3:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">define void @foo() personality i32 (...)* @__CxxFrameHandler3 {<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  %e.addr = alloca i32<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  invoke void @f(i32 1)<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    to label %cont1 unwind label %<a href="http://maycatch.int">maycatch.int</a><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">cont1:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  invoke void @f(i32 2)<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    to label %cont2 unwind label %cleanup.Obj<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">cont2:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  call void @~Obj()<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  br label %return<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">return:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  ret void<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">cleanup.Obj:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  cleanupblock unwind label %<a href="http://maycatch.int">maycatch.int</a><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  call void @~Obj()<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  resume label %<a href="http://maycatch.int">maycatch.int</a><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal"><a href="http://maycatch.int">maycatch.int</a>:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  catchblock void [i8* @<a href="http://typeid.int">typeid.int</a>, i32 7, i32* %e.addr]<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    to label %<a href="http://catch.int">catch.int</a> unwind label %catchend1<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><a href="http://catch.int">catch.int</a>:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  invoke void @f(i32 3)<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    to label %cont3 unwind label %catchend1<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">cont3:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  invoke void @f(i32 4)<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    to label %cont4 unwind label %maycatch.all<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">cont4:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  resume label %return<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">maycatch.all:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  catchblock void [i8* null, i32 0, i8* null]<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    to label %catch.all unwind label %catchend2<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">catch.all:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  invoke void @f(i32 5)<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    to label %cont5 unwind label %catchend2<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">cont5:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  resume label %cont4<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">catchend2:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  catchendblock unwind label %catchend1<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">catchend1:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  catchendblock unwind label %callterminate<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">callterminate:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">  terminateblock [void ()* @std.terminate]<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">}<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">From this IR, we can recover the original scoped nesting form that the table formation requires.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">I think that covers it. Feedback welcome. :)<o:p></o:p></p>
</div>
</div>
</div>
</body>
</html>