[LLVMdev] RFC: Exception Handling Proposal II

John McCall rjmccall at apple.com
Sun Nov 28 02:59:53 PST 2010


On Nov 28, 2010, at 2:20 AM, Bill Wendling wrote:

> On Nov 27, 2010, at 4:57 PM, John McCall wrote:
> 
>> On Nov 25, 2010, at 3:03 AM, Duncan Sands wrote:
>>> I'm pointing out that if the invoke instruction
>>> is removed and catch information is attached to entire basic blocks, then if no
>>> care is taken then it is perfectly possible to use %x before it is defined as
>>> explained in my previous email, blowing up the entire LLVM system.  Clearly the
>>> solution is to not allow this by not allowing values defined in a basic block
>>> to be used in a handler for that block;
>> 
>> If we take this route — and I think we should, although I'd like to see region
>> chaining in first — I see two reasonable solutions.  The first is what you've
>> said, that effectively there's an edge from the beginning of the block;  the
>> second is a slight twist, that the edge leaves from the end of the phis.  I
>> think the latter will greatly simplify every transformation which ever inserts
>> a phi, and in particular mem2reg.  Since phis can't throw, it should be
>> equivalent anyway.
> 
> Wouldn't this route make otherwise value programs invalid? For instance:
> 
> entry:
>  %x = alloca i32
>  br label try
> 
> try: unwinds to %landing.pad
>  %x1 = add i32 37, 927
>  call @foo()
>  br label %normal.edge
> 
> landing.pad: landingpad
>  ; Code that prints the value of %x1
> 
> We expect the value printed to be 964, but if we don't allow %x1 to be accessible then we get garbage or an assert...

What do you mean by "otherwise valid"?  Just that we can prove that %x1 has been computed by the time a throw can occur?  We really want SSA well-formedness to be a simple structural condition;  having to examine instruction-specific semantics to compute dominance would make it absurdly expensive to compute and keep valid.  For example, if any instruction were valid to reference up to the first throwing instruction, then re-ordering the loads in the following code would break SSA:

bb: unwinds to %lp
  %x1 = throwing load i32* %v1
  %x2 = throwing load i32* %v2
  ...
lp:
  call void @print_int(i32 %x1)

Put another way, this would change SSA well-formedness from a local problem to a global one.

Of course, this will be a very challenging change regardless of dominance criteria because of the imprecision of edges.  For example, we would not be able to mem2reg %v in the following example without splitting %bb:

define void @foo()
entry:
  %v = alloca i32
  br label %bb
bb: unwinds to %lp
  store i32 0, i32* %v
  call void @bar()
  store i32 1, i32* %v
  call void @bar()
  ret void
lp:
  %x = load i32* %v
  ...

That's inherent in the design, unfortunately.

John.



More information about the llvm-dev mailing list