On Wed, Dec 1, 2010 at 11:37 AM, Renato Golin <rengolin at systemcall.org> wrote:> On 1 December 2010 09:46, Bill Wendling <wendling at apple.com> wrote: >> Nor these. Basically, I want the basic block that's labeled a "landing pad" to be jumped to by only a dispatch resume or unwind edge of invoke. We could do this with the c.dtor and ch.int here, but it would mean inserting useless "cleanup dispatches" that only resume to the block (see onto.catch.handlers for an example). > > Hi Bill, > > All cleanups come from invoke's unwinds (from foo's call) and all > catch handlers come from the main catch dispatch, so for that rule, > they all should have it. Or that's what I understood... ;) > > Also, now I noticed a few things in your IR, could be just typos... > (ie. I'm not being an ass, just checking I got it right) ;)I think I can answer a couple of those...> 1. Your BB flow seem odd in the try block. You call foo() four times > and then call the Ctors, rather than interpolating them as in the > source code (otherwise, all calls to foo should unwind to the catch > area, not cleanups).Those are destructor calls for the case where none of the foo()s throw. There are no ctor calls because the classes have trivial constructors, which are no-ops.> 4. Your catch handlers return void, shouldn't then branch to %return > instead? In this case, a front-end would probably call that label a > "%finally" and that would branch to %return, or return directly.He did say it was simplified IR. Just imagine -simplify-cfg already did some tail duplication here.> Which brings me to my final question: In languages where the finally > HAS to run, like Java, would that be a simple cleanup regions or do we > need something special from catch's dispatch's resume AND %finally > block?Presumably that would just be encoded as a catch-all to the finally code followed by some encoding of a rethrow (e.g. an "unwind resume" to the next enclosing region, an 'unwind' instruction or some form of "resume_unwind()" call). If there were also catches, they'd probably need to explicitly execute the finally code (or if they again throw, have their unwind edges point to a dispatch with a catch-all to the finally code).
On 1 December 2010 11:11, Frits van Bommel <fvbommel at gmail.com> wrote:> Those are destructor calls for the case where none of the foo()s > throw. There are no ctor calls because the classes have trivial > constructors, which are no-ops.Indeed! Thanks! ;)> If there were also catches, they'd probably need to explicitly execute > the finally code (or if they again throw, have their unwind edges > point to a dispatch with a catch-all to the finally code).The problem is that, the code has to be run regardless of throwing or not, but the exit of the finally block change depending on its predecessor... So either you have two identical blocks (like the clean-up code) or you have a special way of defining the exit condition based on the predecessor (like PHI nodes for EH, which is horrible!). Example pseudo-IR: try: invoke func() to label %finally unwind to %catch catch: dispatch resume to %lpad catches [ ... ] catch1: ... br %finally lpad: br %finally (??) or cleanup code & continue unwinding? finally: cleanup code return (or continue unwinding?) cheers, --renato
On Wed, Dec 1, 2010 at 12:40 PM, Renato Golin <rengolin at systemcall.org> wrote:> On 1 December 2010 11:11, Frits van Bommel <fvbommel at gmail.com> wrote: >> If there were also catches, they'd probably need to explicitly execute >> the finally code (or if they again throw, have their unwind edges >> point to a dispatch with a catch-all to the finally code). > > The problem is that, the code has to be run regardless of throwing or > not, but the exit of the finally block change depending on its > predecessor... > > So either you have two identical blocks (like the clean-up code) orIIRC that's how LDC deals with it (D has 'finally' blocks).> you have a special way of defining the exit condition based on the > predecessor (like PHI nodes for EH, which is horrible!).You could do this too. I don't think there's any need for a special way to define it though. Just use a switch on a phi. If you use "unwind resume" for rethrowing you may still need to duplicate the code once per EH region though, to make sure it's dominated by the landing pad. Jump threading should be able to clean this up just fine by duplicating the finally code if it considers doing so profitable enough (i.e. if the duplicated code is small enough). And if not, apparently not duplicating was the right thing to do :). You could even use an indirect branch on a phi of blockaddresses, but I wouldn't recommend it. And not just because jump threading can't handle it. indirectbr is gross, and should probably be avoided unless the program you're compiling explicitly asks for it (with computed gotos).