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]
Other format: [Raw text]

Re: bad dead code detection ?


Le Samedi 5 Juillet 2003 00:26, Fergus Henderson a écrit :
> On 25-Jun-2003, David Jobet <david.jobet@free.fr> wrote:
> > I try to write an exception handling library, and I'm forced to play with
> > gcc inline assembly.
>
> I don't see why.  For an example of an exception handling
> library which does not use any inline assembly, see
> <http://www.cs.mu.oz.au/~fjh/CXCPT/>.

Writing an exception handling library with stjmp/longjmp is quite easy. But it 
does not support all the semantic I'd like to bring in : destruction of live 
local variables.

For example :

void f()
{
 try
 {
   A a = new A();
   g();
 }
 catch (Exception e)
 {
 }
}

void g()
{
  A a = new A();
  h();
}

void h()
{
  A a = new A();
  // some code
  throw new Exception();
}

Of course I can jump from h() to f() using setjmp, but I will not be able to 
destroy all live variable contained in the stack.

Registering g as an exception handler only to clean up local variables will be 
too much of an overhead I think.

What I want to do is to offer the same kind of semantic c++ offers. 
Using setjmp/longjmp is too much of an overhead. 
Cleaning up the stack using stack unwinding is not possible because I can't 
predict the variables offset from the stack frame (I have a prototype that 
works, but not with -o3 for example). 
What I wanted to do is write cleanup code in each methods regarless of wether 
it throws, catch or is passed through by an exception. Then have all 
addresses being registered somewhere in a global table.
Then, when an exception is thrown, jump to it in some way.
(basically, I push the address of the local variable in 4(%ebp) and issue a 
normal "c" return)

> > The trick is to register address of local labels in a global static
> > table. Later when an exception is launched, I manage to jump to this
> > label to do clean up. The problem is gcc detects the label cannot be
> > reached and dead code elimination completely remove the exception
> > handling code from the executable when compiled with -O3.
>
> ...
>
> > I'm wondering if it's a bug, or if there is a way to prevent this.
>
> It's not a bug... but there are ways to prevent it.
>
> To prevent dead code elimination from eliminating a label,
> you need to do two things:
>
> 1.  Make sure that the address of each label is taken *and appears to
>     GCC to be used*, e.g. by storing it in a volatile global variable,
>
> 	extern void *volatile volatile_global;
> 	...
> 	volatile_global = &&label;
>
>     or passing it to a volatile asm statement.
>
> 	__asm__ __volatile__("" : : "g"(&&label))
>
>     The latter approach is better since it doesn't generate any code.
>
>     Of course this use of &&label needs to occur in *reachable* code,
>     e.g. at the start of the function.
>
> 2.  You also need to make sure that the function contains at least one
>     reachable jump to an unknown-to-GCC location, e.g. by putting
>     the following at the start of the function, immediately after the
>     above-mentioned code to take and apparently use the addresses of
> labels.
>
>     For example, add
>
> 	goto *identity_function(&&start);
> 	start:
>
>     where identity_function() is a function whose body is not visible to
> GCC that just returns its argument.
>
>     I suppose that
>
> 	volatile_global = &&start;
> 	goto *volatile_global;
>
>     ought to have a similar effect too, although I haven't tested that.
>
> > When compiled without -03, the code is not removed, but the label is
> > moved from the *good* location to the return label.
>
> See the thread "equality and label addresses" starting at
> <http://gcc.gnu.org/ml/gcc/2003-01/msg01519.html>, which is
> at least relevant, though I'm not sure it completely addresses
> your concern here.

Thank you for your help. This is one constructive reply at last.

To explain a little bit, I'm writing a compiler for a language called "Nosica" 
(http://www.nosica.net). This is just for fun... I want to offer the same 
kind of exception handling than Java (try ... catch ... finally, along with 
the semantic of c++ for variables : a destructor is called as soon as the 
variable reach end of scope). As I don't want to go into assembly, I'm using 
C as my target language. Perhaps one day I'll try to write a front end to 
gcc.

Kind regards

David


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