[PATCH] D11097: New EH representation for MSVC compatibility
rnk at google.com
Tue Jul 21 17:45:10 PDT 2015
rnk added a comment.
In http://reviews.llvm.org/D11097#209400, @reames wrote:
> In http://reviews.llvm.org/D11097#209367, @majnemer wrote:
> > @reames thinking about it a little more, would you be happier with `CatchPadInst` instead of `CatchBlockInst`, etc. and `isEHPad` instead of `isEHBlock`?
I like the pad terminology. The block terminology came about because we're really imbuing some special properties on the whole BasicBlock. Currently the landingpad instruction is the only instruction with the power to make an edge unsplittable, for example. Anyway, `pad` sounds good to me.
> That would help. Reusing block causes confusion with the widespread use of "block" to refer to a basic block in the code base.
> More generally, consistency in the terminology would be a good thing. Let me lay out my current understanding:
> - A X-"pad" is a place the exceptional control flow might resume.
> - A catch is a specific type of "pad" which models a language/ABI level catch clause. A catch is exception type specific.
> - A cleanup is a specific type of "pad" which models scope exit without an explicit exception type.
> - Both catch and cleanup are statically scoped. There's a begin and end construct for each.
> In this context, what is a terminateblock? It's clearly a "pad", but why is not just a cleanup?
Currently, Clang expresses noexcept() as a catch-all clause that simply calls terminate. This is inefficient for both Itanium and MSVC because both LSDA tables can express noexcept with a single bit. We do it because it makes it possible to inline one noexcept function into another EH scope without teaching the inliner that it should transform some function attribute into LLVM IR that makes some C++ runtime function call.
Terminatepad solves this all by keeping data as data, allowing late IR preparation passes to expand the IR into code (catch-all or filter) or leave it alone if it can be encoded in the table.
> On the topic of motivation, I still feel like I'm missing a lot. In particular, it feels like the catchpad, cleanuppad, and terminatepad are really close to what's already described by landingpad(*). I get that you need to prevent merging of catch blocks, but why isn't a single "pad fence" at the end of each clause which is unmergeable solve that problem?
> - We might end up changing how you describe a catch clause, but the idea is already there. You do seem to need different arguments then the existing catch clause bits.
Yeah, they are the same set of clauses. :) However, with the new instructions, we won't need to do impossibly error-prone pattern matching.
How would a "pad fence" statically indicate that after running this cleanup, the next EH action is that catch block over there? Right now we try to figure this out by walking the CFG and trying to find the next conditional branch based on a comparison of the EH selector value. I think the primary failure mode of WinEHPrepare today is that we inline a destructor containing control flow, and then this analysis falls over. I'd rather not have to do dataflow analysis to rediscover this very basic nesting property of the C++ source code.
Essentially, the new instructions are exactly that: a really strong "pad fence" that keeps all the data and control flow transfers that we want to know about grouped together.
More information about the llvm-commits