[llvm-commits] [llvm] r129235 - in /llvm/trunk: include/llvm/BasicBlock.h include/llvm/Bitcode/LLVMBitCodes.h lib/AsmParser/LLLexer.cpp lib/AsmParser/LLParser.cpp lib/AsmParser/LLToken.h lib/Bitcode/Reader/BitcodeReader.cpp lib/Bitcode/Writer/BitcodeWriter.cpp lib/VMCore/AsmWriter.cpp lib/VMCore/BasicBlock.cpp test/Feature/bb_attrs.ll

Chris Lattner clattner at apple.com
Sun Apr 10 10:53:28 PDT 2011


On Apr 9, 2011, at 9:38 PM, Bill Wendling wrote:

> On Apr 9, 2011, at 7:50 PM, Chris Lattner wrote:
> 
>> Hi Bill,
>> 
>> This sounds very interesting.  Do you have a description of what you're angling for?  I'd really like to understand and digest the model before you write too much code.
>> 
> Hi Chris,
> 
> Here was the initial proposal (replicated below):
> 
> 	http://lists.cs.uiuc.edu/pipermail/llvmdev/2010-December/036692.html
> 
> There were many comments on it, some fixes, and some clarifications. But in general, what I sent out originally is the basic idea.

Ok, it will take me a little while to digest this.  Can you please revert (but keep!) your first patch until we come to an agreement on the design?

-Chris



> 
> A quick summary: It involves creating a new "dispatch" instruction, that in essence takes the place of the current llvm.eh.selector/llvm.eh.typeid.for/etc. calls. Because it's an IR-level instruction, all of the passes can reason about it much better than they can with intrinsic calls. Also, it has a direct link back to the landing pad basic block (the patch I submitted). This one-to-one-ness makes inlining and culling the AST for EH information much easier.
> 
> -bw
> 
> 
> This is a revision of the second exception handling proposal I sent out. You can see it here:
> 
> 	http://lists.cs.uiuc.edu/pipermail/llvmdev/2010-November/036484.html
> 
> After much discussion, there are some changes to the proposal – some significant and some minor. One major point, this proposal does not address the issue of catching an exception thrown from a non-invoke instruction. However if done properly, it should form the foundation for that.
> 
> General Model
> =============
> 
> The unwind edge from an invoke instruction jumps to a landing pad. That landing pad contains code which performs optional cleanups, and then determines which catch handler to call (if any). If no catch handlers are applicable, the exception resumes propagation either to the next enclosing region or out of the function.
> 
> 
> Basic Block Attributes
> ======================
> 
> A basic block can be given an attribute.
> 
> General Syntax:
> 
> label: attr1 attr2 ... attrn
> 
> For exception handling, we introduce the `landingpad' attribute.
> 
> lp: landingpad
> 
> A basic block that has the `landingpad' attribute is considered a (surprise!) "landing pad".
> 
> • It may be branched to only by the unwind edge of an invoke instruction or by
> the resume edge of a dispatch instruction.
> 
> • A landing pad must have exactly one dispatch instruction associated with it,
> and it must dominate that instruction.
> 
> • If a landing pad is split, only the section containing the start of the basic
> block retains the `landingpad' attribute.
> 
> • The critical edges may not be split.
> 
> • The attribute may not be removed.
> 
> 
> Dispatch Instruction
> ====================
> 
> The dispatch instruction is the work horse of the exception handling design. It replaces the llvm.eh.selector and llvm.eh.typeid.for intrinsics.
> 
> Syntax:
> 
> dispatch resume to label <resumedest>
>   catches [
>     <type> <val>, label <dest1>
>     ...
>   ]
>   catchall [ <type> <val>, label <dest> ]
>   personality [<type> <value>]
>   filters [
>     <type> <val>, <type> <val>, ...
>   ]
> 
> The `catches', `catchall', and `filters' clauses are optional. If neither `catches' nor `catchall' is specified, then the landing pad is implicitly a cleanup.
> 
> • The `<resumedest>' basic block is the destination to unwind to if the
> exception cannot be handled by this landing pad.
> 
> • The `catches' clause is a list of types which the landing pad can handle and
> the destinations to jump to for each type.
> 
> • The `catchall' clause is the place to jump to if the exception type doesn't
> match any of the types in the `catches' clause.
> 
> • The `personality' clause indicates the personality function for the landing
> pad.
> 
> • The `filters' clause lists the types of exceptions which may be thrown by the
> region.
> 
> 
> Invoke Instruction
> ==================
> 
> The "invoke" instruction will not change. :-)
> 
> 
> Examples
> ========
> 
> Consider this program:
> 
> $ cat t.cpp
> #include <cstdio>
> 
> extern void foo();
> 
> struct A { ~A(); };
> struct B { ~B(); };
> struct C { ~C(); };
> 
> void bar() {
> try {
>   foo();
>   A a;
>   foo();
>   B b;
>   foo();
>   C c;
>   foo();
> } catch (int i) {
>   printf("caught int: %d\n", i);
> } catch (const char *c) {
>   printf("caught string: %s\n", c);
> } catch (...) {
>   printf("catchall\n");
> }
> }
> 
> Here's a simplified example of what code would be generated for this (there may be subtle errors...it's handcrafted):
> 
> $ llvm-g++ -o - -emit-llvm -S t.cpp -Os
> 
> @.str = private constant [16 x i8] c"caught int: %d\0A\00", align 1
> @.str1 = private constant [19 x i8] c"caught string: %s\0A\00", align 1
> @.str2 = private constant [9 x i8] c"catchall\00", align 1
> @_ZTIi = external constant %struct.__fundamental_type_info_pseudo
> @_ZTIPKc = external constant %struct.__pointer_type_info_pseudo
> 
> define void @_Z3barv() optsize ssp {
> entry:
> %a = alloca %struct.A, align 8
> %b = alloca %struct.B, align 8
> %c = alloca %struct.C, align 8
> invoke void @_Z3foov()
>         to label %invcont unwind label %catch.handlers
> 
> invcont:
> invoke void @_Z3foov()
>         to label %invcont1 unwind label %a.dtor
> 
> invcont1:
> invoke void @_Z3foov()
>         to label %invcont2 unwind label %b.dtor
> 
> invcont2:
> invoke void @_Z3foov()
>         to label %bb1 unwind label %c.dtor
> 
> bb1:
> invoke void @_ZN1CD1Ev(%struct.C* %c)
>         to label %bb2 unwind label %b.dtor
> 
> bb2:
> invoke void @_ZN1BD1Ev(%struct.B* %b)
>         to label %bb3 unwind label %a.dtor
> 
> bb3:
> invoke void @_ZN1AD1Ev(%struct.A* %a)
>         to label %return unwind label %catch.handlers
> 
> return:
> ret void
> 
> ;; Catch Handlers
> catch.handlers: landingpad
> %eh_ptr = call i8* @llvm.eh.exception()
> dispatch resume to label %...
>   catches [
>     %struct.__fundamental_type_info_pseudo* @_ZTIi, label %ch.int
>     %struct.__pointer_type_info_pseudo* @_ZTIPKc, label %ch.str
>   ]
>   catchall [i8* null, label % ch.ca]
> 
> ch.int:
> %t0 = call i8* @__cxa_begin_catch(i8* %eh_ptr) nounwind
> %t1 = bitcast i8* %t0 to i32*
> %t2 = load i32* %t1, align 4
> %t3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([16 x i8]* @.str, i64 0, i64 0), i32 %t2)
> call void @__cxa_end_catch()
> ret void
> 
> ch.string:
> %t4 = call i8* @__cxa_begin_catch(i8* %eh_ptr) nounwind
> %t5 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([19 x i8]* @.str1, i64 0, i64 0), i8* %t4)
> call void @__cxa_end_catch()
> ret void
> 
> ch.ca:
> %t6 = call i8* @__cxa_begin_catch(i8* %eh_ptr) nounwind
> %t7 = call i32 @puts(i8* getelementptr inbounds ([9 x i8]* @.str2, i64 0, i64 0))
> call void @__cxa_end_catch()
> ret void
> 
> ;; C's d'tor
> c.dtor:
> invoke void @_ZN1CD1Ev(%struct.C* %c)
>         to label %b.dtor unwind label %lpad.c.dtor
> 
> ;; B's d'tor
> b.dtor:
> invoke void @_ZN1BD1Ev(%struct.B* %b)
>         to label %a.dtor unwind label %lpad.b.dtor
> 
> ;; A's d'tor
> a.dtor: landingpad
> invoke void @_ZN1AD1Ev(%struct.A* %a)
>         to label %onto.catch.handlers unwind label %lpad.a.dtor
> 
> onto.catch.handlers:
> dispatch resume to %lpad
> 
> ;; Desperate times...
> lpad.c.dtor: landingpad
> dispatch resume to %yikes
> 
> lpad.b.dtor: landingpad
> dispatch resume to %yikes
> 
> lpad.a.dtor: landingpad
> dispatch resume to %yikes
> 
> yikes:
> call void @_ZSt9terminatev() noreturn nounwind
> unreachable
> }
> 
> Because of the invariant that a landing pad must dominate a dispatch and because a landing pad may be branched to only by an invoke and dispatch instructions, the CFG now has enough information in it to collect the information needed to create the exception handling tables.
> 
> Well? What do you think? Pretty cool, eh? :-)
> 
> -bw
> 
> 
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev





More information about the llvm-commits mailing list