Subject: Re: g++ exceptions and gprof profiling
To: None <port-arm32@NetBSD.ORG>
From: Adam Gundy <adam@impala.demon.co.uk>
List: port-arm32
Date: 07/08/1997 21:28:19
In message <f1ae28a647@tonyh.tcp.co.uk> you wrote:

> In message <19970707.210450.56@impala.demon.co.uk>
>           Adam Gundy <adam@impala.demon.co.uk> wrote:
> 
> > Hi. After much late night work, grepping of the gcc source code,
> > and reading the .info files (and some swearing), I've written the
> > attached (small) patch which allows exceptions to be used with
> > g++/arm32 - the frame pointer and link register weren't being
> > located correctly by __builtin_return_address().
> >
> > (as an aside, don't expect much joy with optimisation -
> > we'll have to wait for 2.8.0)
> 
> Would it be possible to get exceptions working in the RISC OS version in
> a similar way?

good question. When you compile code with -fhandle-exceptions the
compiler generates clean up code for any constructed objects in each
function:

myfunc()
{
  CString string1;

  /* code 1 */
  
  CString string2;

  /* code 2 */
}

{
  /* cleanup string2 */
  rethrow;
}

{
  /* cleanup string1 */
  rethrow;
}

Two sets of cleanup code will be generated (in reverse order).
Any exceptions thrown in "code 1" will execute the cleanup for
string 1, any exceptions in "code 2" will execute cleanup for
string 2 and 'fall through', via the rethrow, into the cleanup for
string1. The rethrow in "string1 cleanup" will unwind the stack a
level.

These pieces of cleanup code could I guess be thought of as
catch () { /* cleanup */ }.

When an exception is thrown, any 'catch-all' cleanup handlers are
called in the function that is doing the throwing:

myfunc()
{
  CString string1;
  
  throw( CError( "Something broke" ) );
}

{
  /* cleanup string 1 */
  rethrow;
}

would call the cleanup for string 1, then unwind the stack to the
next exception handler that can be found on the stack.
If myfunc() is called by test(), and test() has constructed objects
(but no try() block) , it _implicitly_ has at least one exception
handler which has to be called.

This then proceeds back up the stack until a try() block is discovered
which won't rethrow (unless it's coded to ;-) - if no try block
is encountered, there's a catch all in _eh.o which essentially
wraps main() and aborts.

The actual stack unwinding shouldn't be a problem in this case,
because the normal function return (or something similar) is called for
each function in the dynamic chain - which should free() stack blocks
if necessary on RISC OS.

The only problem I can see, is that there is a possibility that
functions in the chain with no constructed objects will simply be
skipped (leaving blocks of stack on the heap). I'd have to look
further into that, but I'd guess that the current exception solution
probably just generates cleanup for all functions - perhaps better
exception code would be bad in this case :-(.

Seeya,
 Adam.
-- 
As the year 2000 approaches, the carefully planned Millenium 'bug'
begins to manifest itself in the computing job market...
Real programmers don't comment their code. If it was hard to write, it
should be harder to modify. These are all my own opinions.