blob: f669d093d6186962d836f214c73003c027c64d8a [file] [log] [blame]
hp.com!davidma0f3b062003-02-22 03:08:22 +00001#include <stdio.h>
2#include <stdlib.h>
3
4#include <libunwind.h>
5
6#include "ia64-test-rbs.h"
7
8#define panic(args...) \
9 do { fprintf (stderr, args); ++nerrors; return -9999; } while (0)
10
11#define NELEMS(a) ((int) (sizeof (a) / sizeof ((a)[0])))
12
13/* The loadrs field in ar.rsc is 14 bits wide, which limits all ia64
14 implementations to at most 2048 physical stacked registers
15 (actually, slightly less than that, because loadrs also counts RNaT
16 slots). Since we can dirty 93 stacked registers per recursion, we
17 need to recurse RECURSION_DEPTH times to ensure all physical
18 stacked registers are in use. */
19#define MAX_PHYS_STACKED 2048
20#define RECURSION_DEPTH ((MAX_PHYS_STACKED + 92) / 93)
21
22typedef int spill_func_t (long iteration, int (*next_func[])());
23
24extern int loadup (long iteration, int *values, int (*next_func[])());
25extern char resumption_point_label;
26
27#define DCL(n) \
28 extern int rbs_spill_##n (long iteration, int (*next_func[])())
29 DCL(2); DCL(3); DCL(4); DCL(5); DCL(6); DCL(7);
30 DCL(8); DCL(9); DCL(10); DCL(11); DCL(12); DCL(13); DCL(14); DCL(15);
31 DCL(16); DCL(17); DCL(18); DCL(19); DCL(20); DCL(21); DCL(22); DCL(23);
32 DCL(24); DCL(25); DCL(26); DCL(27); DCL(28); DCL(29); DCL(30); DCL(31);
33 DCL(32); DCL(33); DCL(34); DCL(35); DCL(36); DCL(37); DCL(38); DCL(39);
34 DCL(40); DCL(41); DCL(42); DCL(43); DCL(44); DCL(45); DCL(46); DCL(47);
35 DCL(48); DCL(49); DCL(50); DCL(51); DCL(52); DCL(53); DCL(54); DCL(55);
36 DCL(56); DCL(57); DCL(58); DCL(59); DCL(60); DCL(61); DCL(62); DCL(63);
37 DCL(64); DCL(65); DCL(66); DCL(67); DCL(68); DCL(69); DCL(70); DCL(71);
38 DCL(72); DCL(73); DCL(74); DCL(75); DCL(76); DCL(77); DCL(78); DCL(79);
39 DCL(80); DCL(81); DCL(82); DCL(83); DCL(84); DCL(85); DCL(86); DCL(87);
40 DCL(88); DCL(89); DCL(90); DCL(91); DCL(92); DCL(93); DCL(94);
41
42#define SPL(n) rbs_spill_##n
43spill_func_t *spill_funcs[] =
44 {
45 SPL(2), SPL(3), SPL(4), SPL(5), SPL(6), SPL(7),
46 SPL(8), SPL(9), SPL(10), SPL(11), SPL(12), SPL(13), SPL(14), SPL(15),
47 SPL(16), SPL(17), SPL(18), SPL(19), SPL(20), SPL(21), SPL(22), SPL(23),
48 SPL(24), SPL(25), SPL(26), SPL(27), SPL(28), SPL(29), SPL(30), SPL(31),
49 SPL(32), SPL(33), SPL(34), SPL(35), SPL(36), SPL(37), SPL(38), SPL(39),
50 SPL(40), SPL(41), SPL(42), SPL(43), SPL(44), SPL(45), SPL(46), SPL(47),
51 SPL(48), SPL(49), SPL(50), SPL(51), SPL(52), SPL(53), SPL(54), SPL(55),
52 SPL(56), SPL(57), SPL(58), SPL(59), SPL(60), SPL(61), SPL(62), SPL(63),
53 SPL(64), SPL(65), SPL(66), SPL(67), SPL(68), SPL(69), SPL(70), SPL(71),
54 SPL(72), SPL(73), SPL(74), SPL(75), SPL(76), SPL(77), SPL(78), SPL(79),
55 SPL(80), SPL(81), SPL(82), SPL(83), SPL(84), SPL(85), SPL(86), SPL(87),
56 SPL(88), SPL(89), SPL(90), SPL(91), SPL(92), SPL(93), SPL(94)
57 };
58
59static int verbose;
60static int nerrors;
61static int unwind_count;
62
63static int
64unwind_and_resume (long iteration, int (*next_func[])())
65{
66 unw_context_t uc;
67 unw_cursor_t c;
68 unw_word_t ip;
69 int i, ret;
70
71 if (verbose)
72 printf (" %s(iteration=%ld, next_func=%p)\n",
73 __FUNCTION__, iteration, next_func);
74
75 unw_getcontext (&uc);
76 if ((ret = unw_init_local (&c, &uc)) < 0)
77 panic ("unw_init_local (ret=%d)", ret);
78
79 for (i = 0; i < unwind_count; ++i)
80 if ((ret = unw_step (&c)) < 0)
81 panic ("unw_step (ret=%d)", ret);
82
83 if (unw_get_reg (&c, UNW_REG_IP, &ip) < 0
84 || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) &resumption_point_label) < 0
85 || unw_set_reg (&c, UNW_REG_EH_ARG0, 0) /* ret val */
86 || unw_set_reg (&c, UNW_REG_EH_ARG1, ip))
87 panic ("failed to redirect to resumption_point\n");
88
89 if (verbose)
90 {
91 unw_word_t bsp;
92 if (unw_get_reg (&c, UNW_IA64_BSP, &bsp) < 0)
93 panic ("unw_get_reg() failed\n");
94 printf (" bsp=%lx, old ip=%lx, new ip=%p\n", bsp,
95 ip, &resumption_point_label);
96 }
97
98 ret = unw_resume (&c);
99 panic ("unw_resume() returned (ret=%d)!!\n", ret);
100 return 0;
101}
102
103static int
104run_check (int test)
105{
106 int nfuncs, nspills, n, ret, i, reg_values[88];
107 spill_func_t *func[NSTACKS + 1];
108
109 /* First, generate a set of 88 random values which loadup() will load
110 into loc2-loc89 (r37-r124). */
111 for (i = 0; i < NELEMS (reg_values); ++i)
112 {
113 reg_values[i] = random ();
114 /* Generate NaTs with a reasonably probability (1/16th): */
115 if (reg_values[i] < 0x10000000)
116 reg_values[i] = 0;
117 }
118
119 nspills = 0;
120 nfuncs = 0;
121 do
122 {
123 n = random () % NELEMS (spill_funcs);
124 func[nfuncs++] = spill_funcs[n];
125 nspills += 2 + n;
126 }
127 while (nspills < 128);
128 func[nfuncs++] = unwind_and_resume;
129
130 unwind_count = 1 + (random () % (nfuncs + RECURSION_DEPTH - 1));
131
132 if (verbose)
133 printf ("test%d: nfuncs=%d, unwind_count=%d\n",
134 test, nfuncs, unwind_count);
135
136 ret = loadup (RECURSION_DEPTH, reg_values, func);
137 if (ret < 0)
138 panic ("test%d: load() returned %d\n", test, ret);
139 else if (ret != RECURSION_DEPTH + nfuncs - unwind_count)
140 panic ("test%d: resumed wrong frame: expected %d, got %d\n",
141 test, RECURSION_DEPTH + nfuncs - unwind_count, ret);
142 return 0;
143}
144
145int
146main (int argc, char **argv)
147{
148 int i;
149
150 if (argc > 1)
151 verbose = 1;
152
153 for (i = 0; i < 100000; ++i)
154 run_check (i + 1);
155
156 if (nerrors > 0)
157 {
158 fprintf (stderr, "FAILURE: detected %d errors\n", nerrors);
159 exit (-1);
160 }
161 if (verbose)
162 printf ("SUCCESS.\n");
163 return 0;
164}