1// Try to check that registers are preserved when the stack is unwound.
2// { dg-do run }
3// { dg-options -O2 }
4
5extern "C" void exit(int);
6extern "C" void abort();
7
8// This test case triggers up to DEPTH recursive calls to function
9// foo(), These calls are numbered so that 0 is the innermost, 1 the
10// second innermost, and so on.  Each call caches NUM_VARS elements of
11// both DOUBLE_SRC and INT_SRC and applies a trivial operation to each
12// cached value.  The innermost foo() call will throw an integer call
13// number.  The specified call should store its cached values in
14// DOUBLE_DEST and INT_DEST, which main() will check.
15const int num_vars = 16;
16const int depth = 3;
17
18float float_src[num_vars * depth];
19float float_dest[num_vars];
20
21int int_src[num_vars * depth];
22int int_dest[num_vars];
23
24void foo (int level, int throw_to)
25{
26  float *fsrc = &float_src[level * num_vars];
27  float f00 = *fsrc++ + 1.0f;
28  float f01 = *fsrc++ + 1.0f;
29  float f02 = *fsrc++ + 1.0f;
30  float f03 = *fsrc++ + 1.0f;
31  float f04 = *fsrc++ + 1.0f;
32  float f05 = *fsrc++ + 1.0f;
33  float f06 = *fsrc++ + 1.0f;
34  float f07 = *fsrc++ + 1.0f;
35  float f08 = *fsrc++ + 1.0f;
36  float f09 = *fsrc++ + 1.0f;
37  float f10 = *fsrc++ + 1.0f;
38  float f11 = *fsrc++ + 1.0f;
39  float f12 = *fsrc++ + 1.0f;
40  float f13 = *fsrc++ + 1.0f;
41  float f14 = *fsrc++ + 1.0f;
42  float f15 = *fsrc++ + 1.0f;
43
44  int *isrc = &int_src[level * num_vars];
45  int i00 = *isrc++ + 1;
46  int i01 = *isrc++ + 1;
47  int i02 = *isrc++ + 1;
48  int i03 = *isrc++ + 1;
49  int i04 = *isrc++ + 1;
50  int i05 = *isrc++ + 1;
51  int i06 = *isrc++ + 1;
52  int i07 = *isrc++ + 1;
53  int i08 = *isrc++ + 1;
54  int i09 = *isrc++ + 1;
55  int i10 = *isrc++ + 1;
56  int i11 = *isrc++ + 1;
57  int i12 = *isrc++ + 1;
58  int i13 = *isrc++ + 1;
59  int i14 = *isrc++ + 1;
60  int i15 = *isrc++ + 1;
61
62  try
63    {
64      if (level == 0)
65	throw throw_to;
66      else
67	foo (level - 1, throw_to);
68    }
69  catch (int i)
70    {
71      if (i == level)
72	{
73	  float *fdest = float_dest;
74	  *fdest++ = f00;
75	  *fdest++ = f01;
76	  *fdest++ = f02;
77	  *fdest++ = f03;
78	  *fdest++ = f04;
79	  *fdest++ = f05;
80	  *fdest++ = f06;
81	  *fdest++ = f07;
82	  *fdest++ = f08;
83	  *fdest++ = f09;
84	  *fdest++ = f10;
85	  *fdest++ = f11;
86	  *fdest++ = f12;
87	  *fdest++ = f13;
88	  *fdest++ = f14;
89	  *fdest++ = f15;
90
91	  int *idest = int_dest;
92	  *idest++ = i00;
93	  *idest++ = i01;
94	  *idest++ = i02;
95	  *idest++ = i03;
96	  *idest++ = i04;
97	  *idest++ = i05;
98	  *idest++ = i06;
99	  *idest++ = i07;
100	  *idest++ = i08;
101	  *idest++ = i09;
102	  *idest++ = i10;
103	  *idest++ = i11;
104	  *idest++ = i12;
105	  *idest++ = i13;
106	  *idest++ = i14;
107	  *idest++ = i15;
108	}
109      else
110	{
111	  throw;
112	}
113    }
114}
115
116int main ()
117{
118  for (int i = 0; i < depth * num_vars; i++)
119    {
120      int_src[i] = i * i;
121      float_src[i] = i * 2.0f;
122    }
123  for (int level = 0; level < depth; level++)
124    for (int throw_to = 0; throw_to <= level; throw_to++)
125      {
126	foo (level, throw_to);
127	float *fsrc = &float_src[throw_to * num_vars];
128	int *isrc = &int_src[throw_to * num_vars];
129	for (int i = 0; i < num_vars; i++)
130	  {
131	    if (int_dest[i] != isrc[i] + 1)
132	      abort ();
133	    if (float_dest[i] != fsrc[i] + 1.0f)
134	      abort ();
135	  }
136      }
137  exit (0);
138}
139