1 /* { dg-require-effective-target return_address } */
2 /* { dg-options "-finstrument-functions" } */
3 /* { dg-xfail-run-if "" { powerpc-ibm-aix* } } */
4 
5 extern void abort (void);
6 
7 #define ASSERT(X)	if (!(X)) abort ();
8 #define NOCHK __attribute__ ((no_instrument_function))
9 
10 int entry_calls, exit_calls;
11 void (*last_fn_entered)();
12 void (*last_fn_exited)();
13 
14 __attribute__ ((noinline))
15 int main () NOCHK;
16 
17 __attribute__ ((noinline))
foo()18 void foo ()
19 {
20   ASSERT (last_fn_entered == foo);
21 }
22 
23 __attribute__ ((noinline))
foo2()24 static void foo2 ()
25 {
26   ASSERT (entry_calls == 1 && exit_calls == 0);
27   ASSERT (last_fn_entered == foo2);
28   foo ();
29   ASSERT (entry_calls == 2 && exit_calls == 1);
30   ASSERT (last_fn_entered == foo);
31   ASSERT (last_fn_exited == foo);
32 }
33 
34 __attribute__ ((noinline))
35 void nfoo (void) NOCHK;
nfoo()36 void nfoo ()
37 {
38   ASSERT (entry_calls == 2 && exit_calls == 2);
39   ASSERT (last_fn_entered == foo);
40   ASSERT (last_fn_exited == foo2);
41   foo ();
42   ASSERT (entry_calls == 3 && exit_calls == 3);
43   ASSERT (last_fn_entered == foo);
44   ASSERT (last_fn_exited == foo);
45 }
46 
main()47 int main ()
48 {
49   ASSERT (entry_calls == 0 && exit_calls == 0);
50 
51   foo2 ();
52 
53   ASSERT (entry_calls == 2 && exit_calls == 2);
54   ASSERT (last_fn_entered == foo);
55   ASSERT (last_fn_exited == foo2);
56 
57   nfoo ();
58 
59   ASSERT (entry_calls == 3 && exit_calls == 3);
60   ASSERT (last_fn_entered == foo);
61 
62   return 0;
63 }
64 
65 void __cyg_profile_func_enter (void*, void*) NOCHK;
66 void __cyg_profile_func_exit (void*, void*) NOCHK;
67 
68 __attribute__ ((noinline))
__cyg_profile_func_enter(void * fn,void * parent)69 void __cyg_profile_func_enter (void *fn, void *parent)
70 {
71   entry_calls++;
72   last_fn_entered = (void (*)())fn;
73 }
74 __attribute__ ((noinline))
__cyg_profile_func_exit(void * fn,void * parent)75 void __cyg_profile_func_exit (void *fn, void *parent)
76 {
77   exit_calls++;
78   last_fn_exited = (void (*)())fn;
79 }
80