[LLVMdev] Exception filter IR model

Reid Kleckner rnk at google.com
Thu Apr 16 10:35:10 PDT 2015


The current model is that any variable used by an SEH filter is escaped in
the entry block, and any external function that can throw should also be
able to write to escaped memory. You can see the call to @llvm.frameescape
in the entry block and to @llvm.framerecover in the filter function that
implement this.

This isn't a very accurate model, and it doesn't lend itself to
optimization or program analysis, but it was motivated by the idea that SEH
filters are rare and changing LLVM's EH model is expensive. Our assessment
of rarity comes from experience in Chromium, however, which may not be
representative of other programs. :) SEH is also already an enormous
barrier to optimization, so we figured it would be OK if we just don't do a
good job optimizing functions with SEH filters.

We've been discussing other designs that might avoid the early outlining
that prevents precise analysis and optimization, but it's not clear if
we've found a winner yet. Part of the problem is that, as you've indicated,
filters run in EH phase 1, *before* running cleanups and finally blocks.
The current stack-driven EH emission strategy in Clang doesn't really
handle that, and even if it could, the CFG would be a complete mess.

On Thu, Apr 16, 2015 at 10:05 AM, Joseph Tremoulet <jotrem at microsoft.com>
wrote:

>  Hi,
>
>
>
> I have a question about the IR model for SEH filters (as I want to use the
> same model for CLR filters).  In particular, when an outer filter is
> invoked before entering an inner finally, which piece of IR reflects the
> filter's side-effects?  To take a concrete example, consider this C code:
>
>
>
>
>
> void foo() {
>
>   int x;
>
>   __try {
>
>     x = 0;
>
>     __try {
>
>       x = 2;
>
>       may_throw();
>
>     }
>
>     __finally {
>
>       if (x == 1) {
>
>         printf("correct\n");
>
>       }
>
>       else {
>
>         printf("incorrect\n");
>
>       }
>
>     }
>
>   }
>
>   __except (x = 1) {
>
>   }
>
> }
>
>
>
>
>
>
>
> The IR for the path from "x = 2" to the load of x in the __finally (via
> the exception edge) looks like so:
>
>
>
>
>
>   store i32 2, i32* %x, align 4
>
>   invoke void bitcast (void (...)* @may_throw to void ()*)() #4
>
>           to label %invoke.cont unwind label %lpad
>
>
>
> lpad:                                             ; preds = %entry
>
>   %1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)*
> @__C_specific_handler to i8*)
>
>           cleanup
>
>           catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0 at 0@foo@@" to i8*)
>
>   %2 = extractvalue { i8*, i32 } %1, 0
>
>   store i8* %2, i8** %exn.slot
>
>   %3 = extractvalue { i8*, i32 } %1, 1
>
>   store i32 %3, i32* %ehselector.slot
>
>   store i8 1, i8* %abnormal.termination.slot
>
>   br label %__finally
>
>
>
> __finally:                                        ; preds = %lpad,
> %invoke.cont
>
>   %0 = load i32, i32* %x, align 4
>
>
>
>
>
>
>
> What I'm wondering is where exactly this models the call to @"\01?filt$0 at 0
> @foo@@" and its store to x.  Is it implicitly part of the execution of
> the landingpad instruction itself?  Or of the invoke?
>
>
>
> Thanks
>
> -Joseph
>
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150416/b0223854/attachment.html>


More information about the llvm-dev mailing list