[LLVMdev] RFC: Native Windows C++ exception handling

Kaylor, Andrew andrew.kaylor at intel.com
Tue Jan 27 10:44:28 PST 2015


I was thinking about this last night, and I came up with a third alternative which I think looks very promising.  It’s basically a re-working of the previous alternative to use the landingpad concept rather than arbitrary fake logic, but it uses a single landing pad for the entire function that mimics the logic of the personality function to dispatch unwinding calls and catch handlers.

I believe this is consistent with the semantics and spirit of the existing landingpad mechanism, and it still has the properties that allow the required .xdata information to be easily extracted from the IR.  It will require a new representation after the handlers have been outlined, but I have an idea for that which I’ll send out later today.

If we go this way, the inlining code will need to be taught to merge the landingpad of the inlined function, but I think that will be pretty easy.

So, here it is:

void test()
{
  try {
    Outer outer;
    try {
      Inner inner;
      do_inner_thing();
    } catch (int) {
      handle_int();
    }
  } catch (float) {
    handle_float();
  }
  keep_going();
}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Original
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Function Attrs: uwtable
define void @_Z4testv() #0 {
entry:
  %outer = alloca %class.Outer, align 1
  %inner = alloca %class.Inner, align 1
  call void @llvm.eh.setehstate(i32 0)
  invoke void @_ZN5OuterC1Ev(%class.Outer* %outer)
          to label %invoke.cont unwind label %lpad

invoke.cont:
  call void @llvm.eh.setehstate(i32 1)
  call void @llvm.eh.setehstate(i32 2)
  invoke void @_ZN5InnerC1Ev(%class.Inner* %inner)
          to label %invoke.cont1 unwind label %lpad

invoke.cont.1:
  call void @llvm.eh.setehstate(i32 3)
  invoke void @_Z14do_inner_thingv()
          to label %invoke.cont2 unwind label %lpad

invoke.cont2:
  call void @llvm.eh.setehstate(i32 2)
  invoke void @_ZN5InnerD1Ev(%class.Inner* %inner)
          to label %invoke.cont3 unwind label %lpad

invoke.cont3:
  call void @llvm.eh.setehstate(i32 1)
  invoke void @_ZN5OuterD1Ev(%class.Outer* %outer)
          to label %invoke.cont4 unwind label %lpad

invoke.cont4:
  call void @llvm.eh.setehstate(i32 0)
  call void @llvm.eh.setehstate(i32 -1)
  call void @_Z10keep_goingv()
  ret void

lpad:
  %eh.vals = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
          cleanup
          catch i8* bitcast (i8** @_ZTIi to i8*)
          catch i8* bitcast (i8** @_ZTIf to i8*)
  %eh.ptrs = extractvalue { i8*, i32 } %eh.vals, 0
  %eh.sel  = extractvalue { i8*, i32 } %eh.vals, 1
  br label %unwind.handlers

unwind.handlers:
  %unwind.state = call i32 @llvm.eh.getunwindstate(%eh.ptrs)
  br label %unwind.dispatch

unwind.dispatch:
  %4 = icmp eq i32 %unwind.state, i32 1
  br i1 %4, label %unwind.handler.1, label %unwind.dispatch.1

unwind.handler.1:
  call void @_ZN5OuterD1Ev(%class.Outer* %outer)
  resume { i8*, i32 } %eh.vals

unwind.dispatch:
  %5 = icmp eq i32 %unwind.state, i32 3
  br i1 %5, label %unwind.handler.3, label %catch.handlers

unwind.handler.3:
  call void @_ZN5InnerD1Ev(%class.Inner* %inner)
  resume { i8*, i32 } %eh.vals

catch.handlers:
  %catch.state = call i32 @llvm.eh.getcatchstate(i8* %eh.ptrs)
  br label %catch.dispatch

catch.dispatch.1:
  %6 = icmp sge i32 %catch.state, i32 2
  br i1 %6, label %catch.1.lower.true, label %catch.dispatch.2

catch.1.lower.true
  %7 = icmp sle i32 %catch.state, i32 3
  br i1 %7, label %catch.1.state.matches, label %catch.dispatch.2

catch.1.state.matches:
  %sel.1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
  %matches.1 = icmp eq i32 %sel.1, i32 %eh.sel
  br i1 %matches.1, label %catch.1.handler, label %catch.dispatch.2

catch.1.handler:
  call void @llvm.eh.setehstate(i32 4)
  call void @_Z10handle_intv()
  br label %invoke.cont3

catch.dispatch.2:
  %8 = icmp sge i32 %catch.state, i32 0
  br i1 %8, label %catch.2.lower.true, label %catch.nomatch

catch.2.lower.true
  %9 = icmp sle i32 %catch.state, i32 4
  br i1 %9, label %catch.2.state.matches, label %catch.nomatch

catch.2.state.matches:
  %sel.2 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIf to i8*))
  %matches.2 = icmp eq i32 %sel.2, i32 %eh.sel
  br i1 %matches.2, label %catch.2.handler, label %catch.nonmatch

catch.2.handler:
  call void @llvm.eh.setehstate(i32 5)
  call void @_Z12handle_floatv()
  br label %invoke.cont4

catch.nomatch:
  resume { i8*, i32 } %eh.vals
}

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150127/edff9a72/attachment.html>


More information about the llvm-dev mailing list