1/* { dg-require-effective-target return_address } */
2/* { dg-options "-finstrument-functions" } */
3/* { dg-xfail-run-if "" { powerpc-ibm-aix* } "*" "" } */
4
5extern void abort (void);
6
7#define ASSERT(X)	if (!(X)) abort ();
8#define NOCHK __attribute__ ((no_instrument_function))
9
10int entry_calls, exit_calls;
11void (*last_fn_entered)();
12void (*last_fn_exited)();
13
14__attribute__ ((noinline))
15int main () NOCHK;
16
17__attribute__ ((noinline))
18void foo ()
19{
20  ASSERT (last_fn_entered == foo);
21}
22
23__attribute__ ((noinline))
24static 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))
35void nfoo (void) NOCHK;
36void 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
47int 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
65void __cyg_profile_func_enter (void (*fn)(), void (*parent)()) NOCHK;
66void __cyg_profile_func_exit (void (*fn)(), void (*parent)()) NOCHK;
67
68__attribute__ ((noinline))
69void __cyg_profile_func_enter (void (*fn)(), void (*parent)())
70{
71  entry_calls++;
72  last_fn_entered = fn;
73}
74__attribute__ ((noinline))
75void __cyg_profile_func_exit (void (*fn)(), void (*parent)())
76{
77  exit_calls++;
78  last_fn_exited = fn;
79}
80