| /* { dg-require-effective-target return_address } */ |
| /* { dg-options "-finstrument-functions" } */ |
| /* { dg-xfail-run-if "" { powerpc-ibm-aix* } } */ |
| |
| extern void abort (void); |
| |
| #define ASSERT(X) if (!(X)) abort (); |
| #define NOCHK __attribute__ ((no_instrument_function)) |
| |
| int entry_calls, exit_calls; |
| void (*last_fn_entered)(); |
| void (*last_fn_exited)(); |
| |
| __attribute__ ((noinline)) |
| int main () NOCHK; |
| |
| __attribute__ ((noinline)) |
| void foo () |
| { |
| ASSERT (last_fn_entered == foo); |
| } |
| |
| __attribute__ ((noinline)) |
| static void foo2 () |
| { |
| ASSERT (entry_calls == 1 && exit_calls == 0); |
| ASSERT (last_fn_entered == foo2); |
| foo (); |
| ASSERT (entry_calls == 2 && exit_calls == 1); |
| ASSERT (last_fn_entered == foo); |
| ASSERT (last_fn_exited == foo); |
| } |
| |
| __attribute__ ((noinline)) |
| void nfoo (void) NOCHK; |
| void nfoo () |
| { |
| ASSERT (entry_calls == 2 && exit_calls == 2); |
| ASSERT (last_fn_entered == foo); |
| ASSERT (last_fn_exited == foo2); |
| foo (); |
| ASSERT (entry_calls == 3 && exit_calls == 3); |
| ASSERT (last_fn_entered == foo); |
| ASSERT (last_fn_exited == foo); |
| } |
| |
| int main () |
| { |
| ASSERT (entry_calls == 0 && exit_calls == 0); |
| |
| foo2 (); |
| |
| ASSERT (entry_calls == 2 && exit_calls == 2); |
| ASSERT (last_fn_entered == foo); |
| ASSERT (last_fn_exited == foo2); |
| |
| nfoo (); |
| |
| ASSERT (entry_calls == 3 && exit_calls == 3); |
| ASSERT (last_fn_entered == foo); |
| |
| return 0; |
| } |
| |
| void __cyg_profile_func_enter (void*, void*) NOCHK; |
| void __cyg_profile_func_exit (void*, void*) NOCHK; |
| |
| __attribute__ ((noinline)) |
| void __cyg_profile_func_enter (void *fn, void *parent) |
| { |
| entry_calls++; |
| last_fn_entered = (void (*)())fn; |
| } |
| __attribute__ ((noinline)) |
| void __cyg_profile_func_exit (void *fn, void *parent) |
| { |
| exit_calls++; |
| last_fn_exited = (void (*)())fn; |
| } |