This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: new-exceptions cfg weirdness


>> Consider
>> 
>>    void bar();
>>    void baz();
>>    
>>    void foo()
>>    {
>>      try {
>>        bar();
>>      } catch(...) {
>>        baz();
>>      }
>>    }
>> 
>> I'm seeing some weird EH cycles wrt the two __rethrow calls
>> emitted for this.  Flow is using the REG_EH_RETHROW note it
>> finds therein, but something's wrong.
>> 
>> I see a cycle between bb 2 (the start of the catch) and bb 8
>> (being the rethrow out), and similar between bb 6 and bb 7.
>> It seems unlikely to me that the rethrow should be arcing
>> back into the eh region its just leaving.
>> 
>> So is the EH_RETHROW tag wrong, or should I be doing something
>> else with it?

The rethrow tag (This gets weird) indicates the exception region 
which the rethrow should throw out of, pretending that it isn't going to get 
caught by that region. Meaning there should be an edge from the
rethrow to the catch handlers of any exception region nested outside the
specified region.

Take 2: Basically, rethrow picks up the parameter passed to it, and begins 
preocessing a throw as if the address it is throwing from is within the region 
specified, but cannot be caught by that region. 

ie,
   BEGIN EH REGION 2
     BEGIN EH REGION 4
        BEGIN EH REGION 6
        END EH REGION 6
     END EH REGION 4
   END EH REGION 2

So a rethrow with a tag of 6 would have as successors all handlers for
regions 4 and 2.  A rethrow with tag 4 would have all handlers of 2
as successors.

Its necessary to do this since a rethrow from a catch block may not be obvious
from its location.

   BEGIN EH REGION 2
     BEGIN EH REGION 4
        BEGIN EH REGION 6
        END EH REGION 6
     END EH REGION 4
   END EH REGION 2

If the handler for 6 decides to rethrow, it has to throw as if it were 
executing code within region 6, but not caught by 6. Since 4 is the next
outer region, the rethrow tag will be region 4.
       BEGIN CATCH 6
       RETHROW 4
       END CATCH 6

So the only way to get the right succesors is to build the list of region
nestings. I meant to provide a routine to build that at some point, but
I was building it on the fly in the old flow code.
   When you see the RETHROW X, you have to make successors of all the handlers
for the regions nested outside of X.

The REG_EH_REGION tag on the other hand indicates that if this instruction
throws, its going to be handled by the region specified, so you simply add 
the handlers for that region, and its nested regions. 

We need to add all the nested regions outside of the region you are adding
handlers for too. If a region has 2 handlers, for 'int' and 'char *' say,
and a 'float' is thrown, throw will go looking for the first 'float' catch,
so it will bypass that region, and go to the next outermost region.
 Theoretically, when you find a region which has a CATCH_ALL clause, you 
can stop there since you're guaranteed not to throw beyond that, but I 
believe the old code was pessimistic and didn't look for that case. It
just added edges to handlers all the way out.

Clear as mud?? :-)  It took a long time to get the rethrow tags right all
the time... it gets pretty hairy to find the right spot from our trees.

I plan(ned) to provide a routine which builds the nesting levels, as well
as a routine which you could call which would return a list of all possible
handlers that could be reached by a throw from region X. This routine could
then start to trim down the list a bit. (ie, only the inner handler
of type 'TYPE' needs to be a successor, since the outer one can't be
reached except by a rethrow from the inner one.) Other things got in
the way :-(, and I've never gotten back to it.  

Andrew


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]