On Jul 31, 2011, at 11:06 AM, Duncan Sands wrote:>> //===-------------------------- >> // The 'landingpad' Instruction >> // >> >> The 'landingpad' instruction replaces the current 'llvm.eh.exception' and >> 'llvm.eh.selector' intrinsics. >> >> // Syntax: >> >> %res = landingpad<somety> personality<ty> <pers_fn> <clause>+ >> >> where >> >> <clause> :>> cleanup >> | catch<ty_1>,<ty_2>, ...,<ty_n> >> | filter<ty_1>,<ty_2>, ...,<ty_m> >> >> and the result has the type '<somety>'. The personality functions must be the >> same for all landingpad instructions in a given function. > > Is it intended that "cleanup ty_1, ty_2" potentially be different to > "cleanup ty_1 cleanup ty_2"? Perhaps this is useful for funky personality > functions. >Yeah. One can basically interleave the catches and filters. But having two catch or two filter clauses in a row should be semantically the same as the clauses being merged into one. (E.g., your examples would be equivalent.)> Also, there isn't much point to having multiple "cleanup" entries, but I > guess it makes things more regular to allow it, and perhaps custom personality > functions might want to do something special. >I goofed on the BNF for the cleanup. I fixed it in later versions and in what I'm submitting to the LangRef.html.> If there is only a cleanup, the personality function doesn't really matter > because all standard personality functions treat cleanups the same way. GCC > has an optimization in which you don't have to specify a personality function > in this case (when it comes to codegen time, if there is some personality > function floating around, it uses that; if not it uses the C personality > function; when inlining into something with a catch clause, the personality > function from the catch is used etc). > > Something like this could be nice for LLVM too. For example the LLVM garbage > collector codegen code wants to insert a simple cleanup: run some cleanup code > then resume. It would be nice if it didn't have to specify a personality. For > example by using the null pointer for the personality function. That said I > suppose such code could be required to specify (eg) the C personality function. >There are a few personality function specific optimizations we could do – including setting up the EH tables to have the pers func call std::terminate for us C++ users automatically instead of having to code the call to std::terminate into the CFG. But those are to come later once we get the basic functionality up and running.> Another comment is: rather than using a function pointer for the personality > function (and requiring a declaration for the personality), maybe it could > just be a string? After all, you don't actually do anything much with it: > you just dump the name into the assembler. Perhaps the same goes for catches > and so on: is a global really needed and not its name? >I'm hesitant to do this because the machinery for printing out the correct global value's representation in assembly is already in the code. So it knows how to print: .long ___gxx_personality_v0+4 at GOTPCREL as opposed to .long L___gxx_personality_v0$non_lazy_ptr-. L___gxx_personality_v0$non_lazy_ptr: .indirect_symbol ___gxx_personality_v0 At least for the Mac, it's much easier to do it the GV way... :-)> Finally, rather than baking cleanups, filters etc into the IR, I suppose the > landingpad instruction could just be: > > %res = landingpad<some type> data<ty> > > For standard setups "data" could be a struct type, with fields for the > personality function, a cleanup flag, lists of catches and filters and so on. >True, but this makes the IR less readable for me. I would have to look at a global to understand what this instruction is doing. Plus, we have problems with the "funky personality function" situation. With the proposal, we can interleave the clauses. With the 'data' option, we would have to have a non-IR way of interpreting the struct. So we're kind of back to the situation we have with the intrinsics...>> 5. All landingpad instructions in a function must have the same personality >> function. > > And presumably the same type. >Yes. Good catch. :) -bw
On Aug 1, 2011, at 11:13 PM, Bill Wendling wrote:>>> The 'landingpad' instruction replaces the current 'llvm.eh.exception' and >>> 'llvm.eh.selector' intrinsics. >>> >>> // Syntax: >>> >>> %res = landingpad<somety> personality<ty> <pers_fn> <clause>+ >>> >>> where >>> >>> <clause> :>>> cleanup >>> | catch<ty_1>,<ty_2>, ...,<ty_n> >>> | filter<ty_1>,<ty_2>, ...,<ty_m> >>> >>> and the result has the type '<somety>'. The personality functions must be the >>> same for all landingpad instructions in a given function. >> >> Is it intended that "cleanup ty_1, ty_2" potentially be different to >> "cleanup ty_1 cleanup ty_2"? Perhaps this is useful for funky personality >> functions. >> > Yeah. One can basically interleave the catches and filters. But having two catch or two filter clauses in a row should be semantically the same as the clauses being merged into one. (E.g., your examples would be equivalent.)Let me rephrase the question then. Why not make the grammar be either:>>> <clause> :>>> cleanup >>> | catch <ty_1> >>> | filter <ty_1>.. forcing "catch" or "filter" before each entry. If you don't like that, why not make the grammar be something like:>>> %res = landingpad<somety> personality<ty> <pers_fn> (catch <ty>+)? (filter <ty>+)?Is there anything specific about the ordering of catch or filter clauses that affect semantics? If so, the first alternative seems cleaner. If not, the second does.>> Another comment is: rather than using a function pointer for the personality >> function (and requiring a declaration for the personality), maybe it could >> just be a string? After all, you don't actually do anything much with it: >> you just dump the name into the assembler. Perhaps the same goes for catches >> and so on: is a global really needed and not its name? >> > I'm hesitant to do this because the machinery for printing out the correct global value's representation in assembly is already in the code.IMO, it is clearly the right thing to have a GV here instead of a string.>> Finally, rather than baking cleanups, filters etc into the IR, I suppose the >> landingpad instruction could just be: >> >> %res = landingpad<some type> data<ty> >> >> For standard setups "data" could be a struct type, with fields for the >> personality function, a cleanup flag, lists of catches and filters and so on. >> > True, but this makes the IR less readable for me. I would have to look at a global to understand what this instruction is doing. Plus, we have problems with the "funky personality function" situation. With the proposal, we can interleave the clauses. With the 'data' option, we would have to have a non-IR way of interpreting the struct. So we're kind of back to the situation we have with the intrinsics...I agree with Bill in this case. The reason for landingpad to be an instruction is a) make it clear that it is magic in several ways (e.g. pinned to the start of a block), and b) so that LandingPadInst can have a bunch of useful accessors on it. -Chris
Hi Chris,>>> Is it intended that "cleanup ty_1, ty_2" potentially be different to >>> "cleanup ty_1 cleanup ty_2"? Perhaps this is useful for funky personality >>> functions. >>> >> Yeah. One can basically interleave the catches and filters. But having two catch or two filter clauses in a row should be semantically the same as the clauses being merged into one. (E.g., your examples would be equivalent.) > > Let me rephrase the question then. Why not make the grammar be either: > >>>> <clause> :>>>> cleanup >>>> | catch<ty_1> >>>> | filter<ty_1> > > .. forcing "catch" or "filter" before each entry. If you don't like that, why not make the grammar be something like: > >>>> %res = landingpad<somety> personality<ty> <pers_fn> (catch<ty>+)? (filter<ty>+)? > > Is there anything specific about the ordering of catch or filter clauses that affect semantics? If so, the first alternative seems cleaner. If not, the second does.yes there is something about the order :) When front-ends output code, all catches come before filters, but after inlining you can get: catches, filters, catches, filters etc and this ordering needs to be preserved. Also, filters are different from catches: filter ty_1, ty_2, ..., ty_N matches any exception that would not be caught by any of ty_1, ty_2, ..., ty_N. This is quite different to filter ty_1, filter ty_2, ..., filter ty_N. For example, suppose you throw ty_2. Then the filter ty_1, ty_2, ..., ty_N wouldn't match that, but filter ty_1 would. So filter ty_1, ..., ty_N makes sense; but I don't think catch ty_1, ..., ty_N makes sense.>>> Another comment is: rather than using a function pointer for the personality >>> function (and requiring a declaration for the personality), maybe it could >>> just be a string? After all, you don't actually do anything much with it: >>> you just dump the name into the assembler. Perhaps the same goes for catches >>> and so on: is a global really needed and not its name? >>> >> I'm hesitant to do this because the machinery for printing out the correct global value's representation in assembly is already in the code. > > IMO, it is clearly the right thing to have a GV here instead of a string.I agree :)>>> Finally, rather than baking cleanups, filters etc into the IR, I suppose the >>> landingpad instruction could just be: >>> >>> %res = landingpad<some type> data<ty> >>> >>> For standard setups "data" could be a struct type, with fields for the >>> personality function, a cleanup flag, lists of catches and filters and so on. >>> >> True, but this makes the IR less readable for me. I would have to look at a global to understand what this instruction is doing. Plus, we have problems with the "funky personality function" situation. With the proposal, we can interleave the clauses. With the 'data' option, we would have to have a non-IR way of interpreting the struct. So we're kind of back to the situation we have with the intrinsics... > > I agree with Bill in this case. The reason for landingpad to be an instruction is a) make it clear that it is magic in several ways (e.g. pinned to the start of a block), and b) so that LandingPadInst can have a bunch of useful accessors on it.The idea wasn't to not make it be an instruction, it was to stick all the catches and filters in a global, so that they don't have to be baked into the definition of the instruction. However I now think that that's not a good idea - I'm happy with the original version of the instruction (modulo tweaks like those discussed above). Ciao, Duncan.