1 /* This testcase is part of GDB, the GNU debugger.
2 
3    Copyright 1998, 1999, 2001, 2003, 2004, Free Software Foundation, Inc.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18    */
19 
20 /* Test GDB's ability to restore saved registers from stack frames
21    when using the `return' command.
22    Jim Blandy <jimb@cygnus.com> --- December 1998 */
23 
24 #include <stdio.h>
25 
26 /* This is the Emacs Lisp expression I used to generate the functions
27    in this file.  If people modify the functions manually, instead of
28    changing this expression and re-running it, then evaluating this
29    expression could wipe out their work, so you probably shouldn't
30    re-run it.  But I leave it here for reference.
31 
32    (defun callee (n) (format "callee%d" n))
33    (defun caller (n) (format "caller%d" n))
34    (defun local  (n) (format "l%d"  n))
35    (defun local-sum (n)
36      (if (zerop n) (insert "0")
37        (let ((j 1))
38          (while (<= j n)
39            (insert (local j))
40            (if (< j n) (insert "+"))
41            (setq j (1+ j))))))
42    (defun local-chain (n previous first-end)
43      (let ((j 1))
44        (while (<= j n)
45 	 (insert "  register int " (local j)
46                  " = increment (" previous  ");")
47 	 (if first-end
48 	   (progn
49              (insert "  /" "* " first-end " prologue *" "/")
50              (setq first-end nil)))
51 	 (insert "\n")
52 	 (setq previous (local j))
53 	 (setq j (1+ j))))
54      previous)
55 
56    (save-excursion
57      (let ((limit 5))
58        (goto-char (point-max))
59        (search-backward "generated code starts here")
60        (forward-line 1)
61        (let ((start (point)))
62 	 (search-forward "generated code ends here")
63 	 (forward-line 0)
64 	 (delete-region start (point)))
65 
66        ;; Generate callee functions.
67        (let ((i 0))
68 	 (while (<= i limit)
69            (insert (format "/%s Returns n * %d + %d %s/\n"
70                            "*" i (/ (+ i (* i i)) 2) "*"))
71 	   (insert "int\n")
72 	   (insert (callee i) " (int n)\n")
73 	   (insert "{\n")
74 	   (local-chain i "n" (callee i))
75 	   (insert "  return ")
76 	   (local-sum i)
77 	   (insert ";\n")
78 	   (insert "}\n\n")
79 	   (setq i (1+ i))))
80 
81        ;; Generate caller functions.
82        (let ((i 1))
83 	 (while (<= i limit)
84 	   (insert "int\n")
85 	   (insert (caller i) " (void)\n")
86 	   (insert "{\n")
87 	   (let ((last (local-chain i "0x7eeb" (caller i))))
88 	     (insert "  register int n;\n")
89 	     (let ((j 0))
90 	       (while (<= j limit)
91 	         (insert "  n = " (callee j) " ("
92                          (if (> j 0) "n + " "")
93 		         last ");\n")
94 	         (setq j (1+ j)))))
95 	   (insert "  return n+")
96 	   (local-sum i)
97            (insert ";\n")
98 	   (insert "}\n\n")
99 	   (setq i (1+ i))))
100 
101        ;; Generate driver function.
102        (insert "void\n")
103        (insert "driver (void)\n")
104        (insert "{\n")
105        (let ((i 1))
106 	 (while (<= i limit)
107 	   (insert "  printf (\"" (caller i) " () => %d\\n\", "
108 		   (caller i) " ());\n")
109 	   (setq i (1+ i))))
110        (insert "}\n\n")))
111 
112 	 */
113 
114 int
115 increment (int n)
116 {
117   return n + 1;
118 }
119 
120 /* generated code starts here */
121 /* Returns n * 0 + 0 */
122 int
123 callee0 (int n)
124 {
125   return 0;
126 }
127 
128 /* Returns n * 1 + 1 */
129 int
130 callee1 (int n)
131 {
132   register int l1 = increment (n);  /* callee1 prologue */
133   return l1;
134 }
135 
136 /* Returns n * 2 + 3 */
137 int
138 callee2 (int n)
139 {
140   register int l1 = increment (n);  /* callee2 prologue */
141   register int l2 = increment (l1);
142   return l1+l2;
143 }
144 
145 /* Returns n * 3 + 6 */
146 int
147 callee3 (int n)
148 {
149   register int l1 = increment (n);  /* callee3 prologue */
150   register int l2 = increment (l1);
151   register int l3 = increment (l2);
152   return l1+l2+l3;
153 }
154 
155 /* Returns n * 4 + 10 */
156 int
157 callee4 (int n)
158 {
159   register int l1 = increment (n);  /* callee4 prologue */
160   register int l2 = increment (l1);
161   register int l3 = increment (l2);
162   register int l4 = increment (l3);
163   return l1+l2+l3+l4;
164 }
165 
166 /* Returns n * 5 + 15 */
167 int
168 callee5 (int n)
169 {
170   register int l1 = increment (n);  /* callee5 prologue */
171   register int l2 = increment (l1);
172   register int l3 = increment (l2);
173   register int l4 = increment (l3);
174   register int l5 = increment (l4);
175   return l1+l2+l3+l4+l5;
176 }
177 
178 int
179 caller1 (void)
180 {
181   register int l1 = increment (0x7eeb);  /* caller1 prologue */
182   register int n;
183   n = callee0 (l1);
184   n = callee1 (n + l1);
185   n = callee2 (n + l1);
186   n = callee3 (n + l1);
187   n = callee4 (n + l1);
188   n = callee5 (n + l1);
189   return n+l1;
190 }
191 
192 int
193 caller2 (void)
194 {
195   register int l1 = increment (0x7eeb);  /* caller2 prologue */
196   register int l2 = increment (l1);
197   register int n;
198   n = callee0 (l2);
199   n = callee1 (n + l2);
200   n = callee2 (n + l2);
201   n = callee3 (n + l2);
202   n = callee4 (n + l2);
203   n = callee5 (n + l2);
204   return n+l1+l2;
205 }
206 
207 int
208 caller3 (void)
209 {
210   register int l1 = increment (0x7eeb);  /* caller3 prologue */
211   register int l2 = increment (l1);
212   register int l3 = increment (l2);
213   register int n;
214   n = callee0 (l3);
215   n = callee1 (n + l3);
216   n = callee2 (n + l3);
217   n = callee3 (n + l3);
218   n = callee4 (n + l3);
219   n = callee5 (n + l3);
220   return n+l1+l2+l3;
221 }
222 
223 int
224 caller4 (void)
225 {
226   register int l1 = increment (0x7eeb);  /* caller4 prologue */
227   register int l2 = increment (l1);
228   register int l3 = increment (l2);
229   register int l4 = increment (l3);
230   register int n;
231   n = callee0 (l4);
232   n = callee1 (n + l4);
233   n = callee2 (n + l4);
234   n = callee3 (n + l4);
235   n = callee4 (n + l4);
236   n = callee5 (n + l4);
237   return n+l1+l2+l3+l4;
238 }
239 
240 int
241 caller5 (void)
242 {
243   register int l1 = increment (0x7eeb);  /* caller5 prologue */
244   register int l2 = increment (l1);
245   register int l3 = increment (l2);
246   register int l4 = increment (l3);
247   register int l5 = increment (l4);
248   register int n;
249   n = callee0 (l5);
250   n = callee1 (n + l5);
251   n = callee2 (n + l5);
252   n = callee3 (n + l5);
253   n = callee4 (n + l5);
254   n = callee5 (n + l5);
255   return n+l1+l2+l3+l4+l5;
256 }
257 
258 void
259 driver (void)
260 {
261   printf ("caller1 () => %d\n", caller1 ());
262   printf ("caller2 () => %d\n", caller2 ());
263   printf ("caller3 () => %d\n", caller3 ());
264   printf ("caller4 () => %d\n", caller4 ());
265   printf ("caller5 () => %d\n", caller5 ());
266 }
267 
268 /* generated code ends here */
269 
270 int main ()
271 {
272   register int local;
273 #ifdef usestubs
274   set_debug_traps();
275   breakpoint();
276 #endif
277   driver ();
278   printf("exiting\n");
279   return 0;
280 }
281