[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