/* Test GDB's ability to restore saved registers from stack frames when using the `return' command. Jim Blandy --- December 1998 */ #include /* This is the Emacs Lisp expression I used to generate the functions in this file. If people modify the functions manually, instead of changing this expression and re-running it, then evaluating this expression could wipe out their work, so you probably shouldn't re-run it. But I leave it here for reference. (defun callee (n) (format "callee%d" n)) (defun caller (n) (format "caller%d" n)) (defun local (n) (format "l%d" n)) (defun local-sum (n) (let ((j 1)) (while (<= j n) (insert (local j)) (if (< j n) (insert "+")) (setq j (1+ j))))) (defun local-chain (n previous first-end) (let ((j 1)) (while (<= j n) (insert " register int " (local j) " = increment (" previous ");") (if first-end (progn (insert " /" "* " first-end " *" "/") (setq first-end nil))) (insert "\n") (setq previous (local j)) (setq j (1+ j)))) previous) (save-excursion (let ((limit 5)) (goto-char (point-max)) (search-backward "generated code starts here") (forward-line 1) (let ((start (point))) (search-forward "generated code ends here") (forward-line 0) (delete-region start (point))) ;; Generate callee functions. (let ((i 0)) (while (<= i limit) (insert (format "/%s Returns n * %d + %d %s/\n" "*" i (/ (+ i (* i i)) 2) "*")) (insert "int\n") (insert (callee i) " (int n)\n") (insert "{\n") (local-chain i "n" (callee i)) (insert " return ") (if (<= i 0) (insert "n") (local-sum i)) (insert ";\n") (insert "}\n\n") (setq i (1+ i)))) ;; Generate caller functions. (let ((i 1)) (while (<= i limit) (insert "int\n") (insert (caller i) " (void)\n") (insert "{\n") (let ((last (local-chain i "0xfeeb" (caller i)))) (insert " register int n;\n") (let ((j 0)) (while (<= j limit) (insert " n = " (callee j) " (" (if (> j 0) "n + " "") last ");\n") (setq j (1+ j))))) (insert " return n+") (local-sum i) (insert ";\n") (insert "}\n\n") (setq i (1+ i)))) ;; Generate driver function. (insert "void\n") (insert "driver (void)\n") (insert "{\n") (let ((i 1)) (while (<= i limit) (insert " printf (\"" (caller i) " () => %d\\n\", " (caller i) " ());\n") (setq i (1+ i)))) (insert "}\n\n"))) */ int increment (int n) { return n + 1; } /* generated code starts here */ /* Returns n * 0 + 0 */ int callee0 (int n) { return n; } /* Returns n * 1 + 1 */ int callee1 (int n) { register int l1 = increment (n); /* callee1 */ return l1; } /* Returns n * 2 + 3 */ int callee2 (int n) { register int l1 = increment (n); /* callee2 */ register int l2 = increment (l1); return l1+l2; } /* Returns n * 3 + 6 */ int callee3 (int n) { register int l1 = increment (n); /* callee3 */ register int l2 = increment (l1); register int l3 = increment (l2); return l1+l2+l3; } /* Returns n * 4 + 10 */ int callee4 (int n) { register int l1 = increment (n); /* callee4 */ register int l2 = increment (l1); register int l3 = increment (l2); register int l4 = increment (l3); return l1+l2+l3+l4; } /* Returns n * 5 + 15 */ int callee5 (int n) { register int l1 = increment (n); /* callee5 */ register int l2 = increment (l1); register int l3 = increment (l2); register int l4 = increment (l3); register int l5 = increment (l4); return l1+l2+l3+l4+l5; } int caller1 (void) { register int l1 = increment (0xfeeb); /* caller1 */ register int n; n = callee0 (l1); n = callee1 (n + l1); n = callee2 (n + l1); n = callee3 (n + l1); n = callee4 (n + l1); n = callee5 (n + l1); return n+l1; } int caller2 (void) { register int l1 = increment (0xfeeb); /* caller2 */ register int l2 = increment (l1); register int n; n = callee0 (l2); n = callee1 (n + l2); n = callee2 (n + l2); n = callee3 (n + l2); n = callee4 (n + l2); n = callee5 (n + l2); return n+l1+l2; } int caller3 (void) { register int l1 = increment (0xfeeb); /* caller3 */ register int l2 = increment (l1); register int l3 = increment (l2); register int n; n = callee0 (l3); n = callee1 (n + l3); n = callee2 (n + l3); n = callee3 (n + l3); n = callee4 (n + l3); n = callee5 (n + l3); return n+l1+l2+l3; } int caller4 (void) { register int l1 = increment (0xfeeb); /* caller4 */ register int l2 = increment (l1); register int l3 = increment (l2); register int l4 = increment (l3); register int n; n = callee0 (l4); n = callee1 (n + l4); n = callee2 (n + l4); n = callee3 (n + l4); n = callee4 (n + l4); n = callee5 (n + l4); return n+l1+l2+l3+l4; } int caller5 (void) { register int l1 = increment (0xfeeb); /* caller5 */ register int l2 = increment (l1); register int l3 = increment (l2); register int l4 = increment (l3); register int l5 = increment (l4); register int n; n = callee0 (l5); n = callee1 (n + l5); n = callee2 (n + l5); n = callee3 (n + l5); n = callee4 (n + l5); n = callee5 (n + l5); return n+l1+l2+l3+l4+l5; } void driver (void) { printf ("caller1 () => %d\n", caller1 ()); printf ("caller2 () => %d\n", caller2 ()); printf ("caller3 () => %d\n", caller3 ()); printf ("caller4 () => %d\n", caller4 ()); printf ("caller5 () => %d\n", caller5 ()); } /* generated code ends here */ main () { register int local; #ifdef usestubs set_debug_traps(); breakpoint(); #endif driver (); printf("exiting\n"); }