OSDN Git Service

Tue Jun 23 13:38:18 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / libgcc2.c
1 /* More subroutines needed by GCC output code on some machines.  */
2 /* Compile this one with gcc.  */
3 /* Copyright (C) 1989, 92-97, 1998 Free Software Foundation, Inc.
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 /* As a special exception, if you link this library with other files,
23    some of which are compiled with GCC, to produce an executable,
24    this library does not by itself cause the resulting executable
25    to be covered by the GNU General Public License.
26    This exception does not however invalidate any other reasons why
27    the executable file might be covered by the GNU General Public License.  */
28
29 /* It is incorrect to include config.h here, because this file is being
30    compiled for the target, and hence definitions concerning only the host
31    do not apply.  */
32
33 #include "tconfig.h"
34
35 /* We disable this when inhibit_libc, so that gcc can still be built without
36    needing header files first.  */
37 /* ??? This is not a good solution, since prototypes may be required in
38    some cases for correct code.  See also frame.c.  */
39 #ifndef inhibit_libc
40 /* fixproto guarantees these system headers exist. */
41 #include <stdlib.h>
42 #include <unistd.h>
43 #endif
44
45 #include "machmode.h"
46 #include "defaults.h" 
47 #ifndef L_trampoline
48 #include <stddef.h>
49 #endif
50
51 /* Don't use `fancy_abort' here even if config.h says to use it.  */
52 #ifdef abort
53 #undef abort
54 #endif
55
56 #if (SUPPORTS_WEAK == 1) && (defined (ASM_OUTPUT_DEF) || defined (ASM_OUTPUT_WEAK_ALIAS))
57 #define WEAK_ALIAS
58 #endif
59
60 /* In a cross-compilation situation, default to inhibiting compilation
61    of routines that use libc.  */
62
63 #if defined(CROSS_COMPILE) && !defined(inhibit_libc)
64 #define inhibit_libc
65 #endif
66
67 /* Permit the tm.h file to select the endianness to use just for this
68    file.  This is used when the endianness is determined when the
69    compiler is run.  */
70
71 #ifndef LIBGCC2_WORDS_BIG_ENDIAN
72 #define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
73 #endif
74
75 /* In the first part of this file, we are interfacing to calls generated
76    by the compiler itself.  These calls pass values into these routines
77    which have very specific modes (rather than very specific types), and
78    these compiler-generated calls also expect any return values to have
79    very specific modes (rather than very specific types).  Thus, we need
80    to avoid using regular C language type names in this part of the file
81    because the sizes for those types can be configured to be anything.
82    Instead we use the following special type names.  */
83
84 typedef unsigned int UQItype    __attribute__ ((mode (QI)));
85 typedef          int SItype     __attribute__ ((mode (SI)));
86 typedef unsigned int USItype    __attribute__ ((mode (SI)));
87 typedef          int DItype     __attribute__ ((mode (DI)));
88 typedef unsigned int UDItype    __attribute__ ((mode (DI)));
89
90 typedef         float SFtype    __attribute__ ((mode (SF)));
91 typedef         float DFtype    __attribute__ ((mode (DF)));
92
93 #if LONG_DOUBLE_TYPE_SIZE == 96
94 typedef         float XFtype    __attribute__ ((mode (XF)));
95 #endif
96 #if LONG_DOUBLE_TYPE_SIZE == 128
97 typedef         float TFtype    __attribute__ ((mode (TF)));
98 #endif
99
100 typedef int word_type __attribute__ ((mode (__word__)));
101
102 /* Make sure that we don't accidentally use any normal C language built-in
103    type names in the first part of this file.  Instead we want to use *only*
104    the type names defined above.  The following macro definitions insure
105    that if we *do* accidentally use some normal C language built-in type name,
106    we will get a syntax error.  */
107
108 #define char bogus_type
109 #define short bogus_type
110 #define int bogus_type
111 #define long bogus_type
112 #define unsigned bogus_type
113 #define float bogus_type
114 #define double bogus_type
115
116 #define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
117
118 /* DIstructs are pairs of SItype values in the order determined by
119    LIBGCC2_WORDS_BIG_ENDIAN.  */
120
121 #if LIBGCC2_WORDS_BIG_ENDIAN
122   struct DIstruct {SItype high, low;};
123 #else
124   struct DIstruct {SItype low, high;};
125 #endif
126
127 /* We need this union to unpack/pack DImode values, since we don't have
128    any arithmetic yet.  Incoming DImode parameters are stored into the
129    `ll' field, and the unpacked result is read from the struct `s'.  */
130
131 typedef union
132 {
133   struct DIstruct s;
134   DItype ll;
135 } DIunion;
136
137 #if (defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)\
138      || defined (L_divdi3) || defined (L_udivdi3) \
139      || defined (L_moddi3) || defined (L_umoddi3))
140
141 #include "longlong.h"
142
143 #endif /* udiv or mul */
144
145 extern DItype __fixunssfdi (SFtype a);
146 extern DItype __fixunsdfdi (DFtype a);
147 #if LONG_DOUBLE_TYPE_SIZE == 96
148 extern DItype __fixunsxfdi (XFtype a);
149 #endif
150 #if LONG_DOUBLE_TYPE_SIZE == 128
151 extern DItype __fixunstfdi (TFtype a);
152 #endif
153 \f
154 #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
155 #if defined (L_divdi3) || defined (L_moddi3)
156 static inline
157 #endif
158 DItype
159 __negdi2 (DItype u)
160 {
161   DIunion w;
162   DIunion uu;
163
164   uu.ll = u;
165
166   w.s.low = -uu.s.low;
167   w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
168
169   return w.ll;
170 }
171 #endif
172 \f
173 /* Unless shift functions are defined whith full ANSI prototypes,
174    parameter b will be promoted to int if word_type is smaller than an int.  */
175 #ifdef L_lshrdi3
176 DItype
177 __lshrdi3 (DItype u, word_type b)
178 {
179   DIunion w;
180   word_type bm;
181   DIunion uu;
182
183   if (b == 0)
184     return u;
185
186   uu.ll = u;
187
188   bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
189   if (bm <= 0)
190     {
191       w.s.high = 0;
192       w.s.low = (USItype)uu.s.high >> -bm;
193     }
194   else
195     {
196       USItype carries = (USItype)uu.s.high << bm;
197       w.s.high = (USItype)uu.s.high >> b;
198       w.s.low = ((USItype)uu.s.low >> b) | carries;
199     }
200
201   return w.ll;
202 }
203 #endif
204
205 #ifdef L_ashldi3
206 DItype
207 __ashldi3 (DItype u, word_type b)
208 {
209   DIunion w;
210   word_type bm;
211   DIunion uu;
212
213   if (b == 0)
214     return u;
215
216   uu.ll = u;
217
218   bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
219   if (bm <= 0)
220     {
221       w.s.low = 0;
222       w.s.high = (USItype)uu.s.low << -bm;
223     }
224   else
225     {
226       USItype carries = (USItype)uu.s.low >> bm;
227       w.s.low = (USItype)uu.s.low << b;
228       w.s.high = ((USItype)uu.s.high << b) | carries;
229     }
230
231   return w.ll;
232 }
233 #endif
234
235 #ifdef L_ashrdi3
236 DItype
237 __ashrdi3 (DItype u, word_type b)
238 {
239   DIunion w;
240   word_type bm;
241   DIunion uu;
242
243   if (b == 0)
244     return u;
245
246   uu.ll = u;
247
248   bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
249   if (bm <= 0)
250     {
251       /* w.s.high = 1..1 or 0..0 */
252       w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
253       w.s.low = uu.s.high >> -bm;
254     }
255   else
256     {
257       USItype carries = (USItype)uu.s.high << bm;
258       w.s.high = uu.s.high >> b;
259       w.s.low = ((USItype)uu.s.low >> b) | carries;
260     }
261
262   return w.ll;
263 }
264 #endif
265 \f
266 #ifdef L_ffsdi2
267 DItype
268 __ffsdi2 (DItype u)
269 {
270   DIunion uu, w;
271   uu.ll = u;
272   w.s.high = 0;
273   w.s.low = ffs (uu.s.low);
274   if (w.s.low != 0)
275     return w.ll;
276   w.s.low = ffs (uu.s.high);
277   if (w.s.low != 0)
278     {
279       w.s.low += BITS_PER_UNIT * sizeof (SItype);
280       return w.ll;
281     }
282   return w.ll;
283 }
284 #endif
285 \f
286 #ifdef L_muldi3
287 DItype
288 __muldi3 (DItype u, DItype v)
289 {
290   DIunion w;
291   DIunion uu, vv;
292
293   uu.ll = u,
294   vv.ll = v;
295
296   w.ll = __umulsidi3 (uu.s.low, vv.s.low);
297   w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
298                + (USItype) uu.s.high * (USItype) vv.s.low);
299
300   return w.ll;
301 }
302 #endif
303 \f
304 #ifdef L_udiv_w_sdiv
305 #if defined (sdiv_qrnnd)
306 USItype
307 __udiv_w_sdiv (USItype *rp, USItype a1, USItype a0, USItype d)
308 {
309   USItype q, r;
310   USItype c0, c1, b1;
311
312   if ((SItype) d >= 0)
313     {
314       if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
315         {
316           /* dividend, divisor, and quotient are nonnegative */
317           sdiv_qrnnd (q, r, a1, a0, d);
318         }
319       else
320         {
321           /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
322           sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
323           /* Divide (c1*2^32 + c0) by d */
324           sdiv_qrnnd (q, r, c1, c0, d);
325           /* Add 2^31 to quotient */
326           q += (USItype) 1 << (SI_TYPE_SIZE - 1);
327         }
328     }
329   else
330     {
331       b1 = d >> 1;                      /* d/2, between 2^30 and 2^31 - 1 */
332       c1 = a1 >> 1;                     /* A/2 */
333       c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
334
335       if (a1 < b1)                      /* A < 2^32*b1, so A/2 < 2^31*b1 */
336         {
337           sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
338
339           r = 2*r + (a0 & 1);           /* Remainder from A/(2*b1) */
340           if ((d & 1) != 0)
341             {
342               if (r >= q)
343                 r = r - q;
344               else if (q - r <= d)
345                 {
346                   r = r - q + d;
347                   q--;
348                 }
349               else
350                 {
351                   r = r - q + 2*d;
352                   q -= 2;
353                 }
354             }
355         }
356       else if (c1 < b1)                 /* So 2^31 <= (A/2)/b1 < 2^32 */
357         {
358           c1 = (b1 - 1) - c1;
359           c0 = ~c0;                     /* logical NOT */
360
361           sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
362
363           q = ~q;                       /* (A/2)/b1 */
364           r = (b1 - 1) - r;
365
366           r = 2*r + (a0 & 1);           /* A/(2*b1) */
367
368           if ((d & 1) != 0)
369             {
370               if (r >= q)
371                 r = r - q;
372               else if (q - r <= d)
373                 {
374                   r = r - q + d;
375                   q--;
376                 }
377               else
378                 {
379                   r = r - q + 2*d;
380                   q -= 2;
381                 }
382             }
383         }
384       else                              /* Implies c1 = b1 */
385         {                               /* Hence a1 = d - 1 = 2*b1 - 1 */
386           if (a0 >= -d)
387             {
388               q = -1;
389               r = a0 + d;
390             }
391           else
392             {
393               q = -2;
394               r = a0 + 2*d;
395             }
396         }
397     }
398
399   *rp = r;
400   return q;
401 }
402 #else
403 /* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv.  */
404 USItype
405 __udiv_w_sdiv (USItype *rp __attribute__ ((__unused__)),
406                USItype a1 __attribute__ ((__unused__)),
407                USItype a0 __attribute__ ((__unused__)),
408                USItype d __attribute__ ((__unused__)))
409 {
410   return 0;
411 }
412 #endif
413 #endif
414 \f
415 #if (defined (L_udivdi3) || defined (L_divdi3) || \
416      defined (L_umoddi3) || defined (L_moddi3))
417 #define L_udivmoddi4
418 #endif
419
420 #ifdef L_udivmoddi4
421 static const UQItype __clz_tab[] =
422 {
423   0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
424   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
425   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
426   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
427   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
428   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
429   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
430   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
431 };
432
433 #if (defined (L_udivdi3) || defined (L_divdi3) || \
434      defined (L_umoddi3) || defined (L_moddi3))
435 static inline
436 #endif
437 UDItype
438 __udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
439 {
440   DIunion ww;
441   DIunion nn, dd;
442   DIunion rr;
443   USItype d0, d1, n0, n1, n2;
444   USItype q0, q1;
445   USItype b, bm;
446
447   nn.ll = n;
448   dd.ll = d;
449
450   d0 = dd.s.low;
451   d1 = dd.s.high;
452   n0 = nn.s.low;
453   n1 = nn.s.high;
454
455 #if !UDIV_NEEDS_NORMALIZATION
456   if (d1 == 0)
457     {
458       if (d0 > n1)
459         {
460           /* 0q = nn / 0D */
461
462           udiv_qrnnd (q0, n0, n1, n0, d0);
463           q1 = 0;
464
465           /* Remainder in n0.  */
466         }
467       else
468         {
469           /* qq = NN / 0d */
470
471           if (d0 == 0)
472             d0 = 1 / d0;        /* Divide intentionally by zero.  */
473
474           udiv_qrnnd (q1, n1, 0, n1, d0);
475           udiv_qrnnd (q0, n0, n1, n0, d0);
476
477           /* Remainder in n0.  */
478         }
479
480       if (rp != 0)
481         {
482           rr.s.low = n0;
483           rr.s.high = 0;
484           *rp = rr.ll;
485         }
486     }
487
488 #else /* UDIV_NEEDS_NORMALIZATION */
489
490   if (d1 == 0)
491     {
492       if (d0 > n1)
493         {
494           /* 0q = nn / 0D */
495
496           count_leading_zeros (bm, d0);
497
498           if (bm != 0)
499             {
500               /* Normalize, i.e. make the most significant bit of the
501                  denominator set.  */
502
503               d0 = d0 << bm;
504               n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
505               n0 = n0 << bm;
506             }
507
508           udiv_qrnnd (q0, n0, n1, n0, d0);
509           q1 = 0;
510
511           /* Remainder in n0 >> bm.  */
512         }
513       else
514         {
515           /* qq = NN / 0d */
516
517           if (d0 == 0)
518             d0 = 1 / d0;        /* Divide intentionally by zero.  */
519
520           count_leading_zeros (bm, d0);
521
522           if (bm == 0)
523             {
524               /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
525                  conclude (the most significant bit of n1 is set) /\ (the
526                  leading quotient digit q1 = 1).
527
528                  This special case is necessary, not an optimization.
529                  (Shifts counts of SI_TYPE_SIZE are undefined.)  */
530
531               n1 -= d0;
532               q1 = 1;
533             }
534           else
535             {
536               /* Normalize.  */
537
538               b = SI_TYPE_SIZE - bm;
539
540               d0 = d0 << bm;
541               n2 = n1 >> b;
542               n1 = (n1 << bm) | (n0 >> b);
543               n0 = n0 << bm;
544
545               udiv_qrnnd (q1, n1, n2, n1, d0);
546             }
547
548           /* n1 != d0...  */
549
550           udiv_qrnnd (q0, n0, n1, n0, d0);
551
552           /* Remainder in n0 >> bm.  */
553         }
554
555       if (rp != 0)
556         {
557           rr.s.low = n0 >> bm;
558           rr.s.high = 0;
559           *rp = rr.ll;
560         }
561     }
562 #endif /* UDIV_NEEDS_NORMALIZATION */
563
564   else
565     {
566       if (d1 > n1)
567         {
568           /* 00 = nn / DD */
569
570           q0 = 0;
571           q1 = 0;
572
573           /* Remainder in n1n0.  */
574           if (rp != 0)
575             {
576               rr.s.low = n0;
577               rr.s.high = n1;
578               *rp = rr.ll;
579             }
580         }
581       else
582         {
583           /* 0q = NN / dd */
584
585           count_leading_zeros (bm, d1);
586           if (bm == 0)
587             {
588               /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
589                  conclude (the most significant bit of n1 is set) /\ (the
590                  quotient digit q0 = 0 or 1).
591
592                  This special case is necessary, not an optimization.  */
593
594               /* The condition on the next line takes advantage of that
595                  n1 >= d1 (true due to program flow).  */
596               if (n1 > d1 || n0 >= d0)
597                 {
598                   q0 = 1;
599                   sub_ddmmss (n1, n0, n1, n0, d1, d0);
600                 }
601               else
602                 q0 = 0;
603
604               q1 = 0;
605
606               if (rp != 0)
607                 {
608                   rr.s.low = n0;
609                   rr.s.high = n1;
610                   *rp = rr.ll;
611                 }
612             }
613           else
614             {
615               USItype m1, m0;
616               /* Normalize.  */
617
618               b = SI_TYPE_SIZE - bm;
619
620               d1 = (d1 << bm) | (d0 >> b);
621               d0 = d0 << bm;
622               n2 = n1 >> b;
623               n1 = (n1 << bm) | (n0 >> b);
624               n0 = n0 << bm;
625
626               udiv_qrnnd (q0, n1, n2, n1, d1);
627               umul_ppmm (m1, m0, q0, d0);
628
629               if (m1 > n1 || (m1 == n1 && m0 > n0))
630                 {
631                   q0--;
632                   sub_ddmmss (m1, m0, m1, m0, d1, d0);
633                 }
634
635               q1 = 0;
636
637               /* Remainder in (n1n0 - m1m0) >> bm.  */
638               if (rp != 0)
639                 {
640                   sub_ddmmss (n1, n0, n1, n0, m1, m0);
641                   rr.s.low = (n1 << b) | (n0 >> bm);
642                   rr.s.high = n1 >> bm;
643                   *rp = rr.ll;
644                 }
645             }
646         }
647     }
648
649   ww.s.low = q0;
650   ww.s.high = q1;
651   return ww.ll;
652 }
653 #endif
654
655 #ifdef L_divdi3
656 UDItype __udivmoddi4 ();
657
658 DItype
659 __divdi3 (DItype u, DItype v)
660 {
661   word_type c = 0;
662   DIunion uu, vv;
663   DItype w;
664
665   uu.ll = u;
666   vv.ll = v;
667
668   if (uu.s.high < 0)
669     c = ~c,
670     uu.ll = __negdi2 (uu.ll);
671   if (vv.s.high < 0)
672     c = ~c,
673     vv.ll = __negdi2 (vv.ll);
674
675   w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
676   if (c)
677     w = __negdi2 (w);
678
679   return w;
680 }
681 #endif
682
683 #ifdef L_moddi3
684 UDItype __udivmoddi4 ();
685 DItype
686 __moddi3 (DItype u, DItype v)
687 {
688   word_type c = 0;
689   DIunion uu, vv;
690   DItype w;
691
692   uu.ll = u;
693   vv.ll = v;
694
695   if (uu.s.high < 0)
696     c = ~c,
697     uu.ll = __negdi2 (uu.ll);
698   if (vv.s.high < 0)
699     vv.ll = __negdi2 (vv.ll);
700
701   (void) __udivmoddi4 (uu.ll, vv.ll, &w);
702   if (c)
703     w = __negdi2 (w);
704
705   return w;
706 }
707 #endif
708
709 #ifdef L_umoddi3
710 UDItype __udivmoddi4 ();
711 UDItype
712 __umoddi3 (UDItype u, UDItype v)
713 {
714   UDItype w;
715
716   (void) __udivmoddi4 (u, v, &w);
717
718   return w;
719 }
720 #endif
721
722 #ifdef L_udivdi3
723 UDItype __udivmoddi4 ();
724 UDItype
725 __udivdi3 (UDItype n, UDItype d)
726 {
727   return __udivmoddi4 (n, d, (UDItype *) 0);
728 }
729 #endif
730 \f
731 #ifdef L_cmpdi2
732 word_type
733 __cmpdi2 (DItype a, DItype b)
734 {
735   DIunion au, bu;
736
737   au.ll = a, bu.ll = b;
738
739   if (au.s.high < bu.s.high)
740     return 0;
741   else if (au.s.high > bu.s.high)
742     return 2;
743   if ((USItype) au.s.low < (USItype) bu.s.low)
744     return 0;
745   else if ((USItype) au.s.low > (USItype) bu.s.low)
746     return 2;
747   return 1;
748 }
749 #endif
750
751 #ifdef L_ucmpdi2
752 word_type
753 __ucmpdi2 (DItype a, DItype b)
754 {
755   DIunion au, bu;
756
757   au.ll = a, bu.ll = b;
758
759   if ((USItype) au.s.high < (USItype) bu.s.high)
760     return 0;
761   else if ((USItype) au.s.high > (USItype) bu.s.high)
762     return 2;
763   if ((USItype) au.s.low < (USItype) bu.s.low)
764     return 0;
765   else if ((USItype) au.s.low > (USItype) bu.s.low)
766     return 2;
767   return 1;
768 }
769 #endif
770 \f
771 #if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
772 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
773 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
774
775 DItype
776 __fixunstfdi (TFtype a)
777 {
778   TFtype b;
779   UDItype v;
780
781   if (a < 0)
782     return 0;
783
784   /* Compute high word of result, as a flonum.  */
785   b = (a / HIGH_WORD_COEFF);
786   /* Convert that to fixed (but not to DItype!),
787      and shift it into the high word.  */
788   v = (USItype) b;
789   v <<= WORD_SIZE;
790   /* Remove high part from the TFtype, leaving the low part as flonum.  */
791   a -= (TFtype)v;
792   /* Convert that to fixed (but not to DItype!) and add it in.
793      Sometimes A comes out negative.  This is significant, since
794      A has more bits than a long int does.  */
795   if (a < 0)
796     v -= (USItype) (- a);
797   else
798     v += (USItype) a;
799   return v;
800 }
801 #endif
802
803 #if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
804 DItype
805 __fixtfdi (TFtype a)
806 {
807   if (a < 0)
808     return - __fixunstfdi (-a);
809   return __fixunstfdi (a);
810 }
811 #endif
812
813 #if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
814 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
815 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
816
817 DItype
818 __fixunsxfdi (XFtype a)
819 {
820   XFtype b;
821   UDItype v;
822
823   if (a < 0)
824     return 0;
825
826   /* Compute high word of result, as a flonum.  */
827   b = (a / HIGH_WORD_COEFF);
828   /* Convert that to fixed (but not to DItype!),
829      and shift it into the high word.  */
830   v = (USItype) b;
831   v <<= WORD_SIZE;
832   /* Remove high part from the XFtype, leaving the low part as flonum.  */
833   a -= (XFtype)v;
834   /* Convert that to fixed (but not to DItype!) and add it in.
835      Sometimes A comes out negative.  This is significant, since
836      A has more bits than a long int does.  */
837   if (a < 0)
838     v -= (USItype) (- a);
839   else
840     v += (USItype) a;
841   return v;
842 }
843 #endif
844
845 #if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
846 DItype
847 __fixxfdi (XFtype a)
848 {
849   if (a < 0)
850     return - __fixunsxfdi (-a);
851   return __fixunsxfdi (a);
852 }
853 #endif
854
855 #ifdef L_fixunsdfdi
856 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
857 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
858
859 DItype
860 __fixunsdfdi (DFtype a)
861 {
862   DFtype b;
863   UDItype v;
864
865   if (a < 0)
866     return 0;
867
868   /* Compute high word of result, as a flonum.  */
869   b = (a / HIGH_WORD_COEFF);
870   /* Convert that to fixed (but not to DItype!),
871      and shift it into the high word.  */
872   v = (USItype) b;
873   v <<= WORD_SIZE;
874   /* Remove high part from the DFtype, leaving the low part as flonum.  */
875   a -= (DFtype)v;
876   /* Convert that to fixed (but not to DItype!) and add it in.
877      Sometimes A comes out negative.  This is significant, since
878      A has more bits than a long int does.  */
879   if (a < 0)
880     v -= (USItype) (- a);
881   else
882     v += (USItype) a;
883   return v;
884 }
885 #endif
886
887 #ifdef L_fixdfdi
888 DItype
889 __fixdfdi (DFtype a)
890 {
891   if (a < 0)
892     return - __fixunsdfdi (-a);
893   return __fixunsdfdi (a);
894 }
895 #endif
896
897 #ifdef L_fixunssfdi
898 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
899 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
900
901 DItype
902 __fixunssfdi (SFtype original_a)
903 {
904   /* Convert the SFtype to a DFtype, because that is surely not going
905      to lose any bits.  Some day someone else can write a faster version
906      that avoids converting to DFtype, and verify it really works right.  */
907   DFtype a = original_a;
908   DFtype b;
909   UDItype v;
910
911   if (a < 0)
912     return 0;
913
914   /* Compute high word of result, as a flonum.  */
915   b = (a / HIGH_WORD_COEFF);
916   /* Convert that to fixed (but not to DItype!),
917      and shift it into the high word.  */
918   v = (USItype) b;
919   v <<= WORD_SIZE;
920   /* Remove high part from the DFtype, leaving the low part as flonum.  */
921   a -= (DFtype)v;
922   /* Convert that to fixed (but not to DItype!) and add it in.
923      Sometimes A comes out negative.  This is significant, since
924      A has more bits than a long int does.  */
925   if (a < 0)
926     v -= (USItype) (- a);
927   else
928     v += (USItype) a;
929   return v;
930 }
931 #endif
932
933 #ifdef L_fixsfdi
934 DItype
935 __fixsfdi (SFtype a)
936 {
937   if (a < 0)
938     return - __fixunssfdi (-a);
939   return __fixunssfdi (a);
940 }
941 #endif
942
943 #if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96)
944 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
945 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
946 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
947
948 XFtype
949 __floatdixf (DItype u)
950 {
951   XFtype d;
952
953   d = (SItype) (u >> WORD_SIZE);
954   d *= HIGH_HALFWORD_COEFF;
955   d *= HIGH_HALFWORD_COEFF;
956   d += (USItype) (u & (HIGH_WORD_COEFF - 1));
957
958   return d;
959 }
960 #endif
961
962 #if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
963 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
964 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
965 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
966
967 TFtype
968 __floatditf (DItype u)
969 {
970   TFtype d;
971
972   d = (SItype) (u >> WORD_SIZE);
973   d *= HIGH_HALFWORD_COEFF;
974   d *= HIGH_HALFWORD_COEFF;
975   d += (USItype) (u & (HIGH_WORD_COEFF - 1));
976
977   return d;
978 }
979 #endif
980
981 #ifdef L_floatdidf
982 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
983 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
984 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
985
986 DFtype
987 __floatdidf (DItype u)
988 {
989   DFtype d;
990
991   d = (SItype) (u >> WORD_SIZE);
992   d *= HIGH_HALFWORD_COEFF;
993   d *= HIGH_HALFWORD_COEFF;
994   d += (USItype) (u & (HIGH_WORD_COEFF - 1));
995
996   return d;
997 }
998 #endif
999
1000 #ifdef L_floatdisf
1001 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
1002 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
1003 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
1004 #define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT)
1005
1006 /* Define codes for all the float formats that we know of.  Note
1007    that this is copied from real.h.  */
1008    
1009 #define UNKNOWN_FLOAT_FORMAT 0
1010 #define IEEE_FLOAT_FORMAT 1
1011 #define VAX_FLOAT_FORMAT 2
1012 #define IBM_FLOAT_FORMAT 3
1013
1014 /* Default to IEEE float if not specified.  Nearly all machines use it.  */
1015 #ifndef HOST_FLOAT_FORMAT
1016 #define HOST_FLOAT_FORMAT       IEEE_FLOAT_FORMAT
1017 #endif
1018
1019 #if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
1020 #define DF_SIZE 53
1021 #define SF_SIZE 24
1022 #endif
1023
1024 #if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
1025 #define DF_SIZE 56
1026 #define SF_SIZE 24
1027 #endif
1028
1029 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
1030 #define DF_SIZE 56
1031 #define SF_SIZE 24
1032 #endif
1033
1034 SFtype
1035 __floatdisf (DItype u)
1036 {
1037   /* Do the calculation in DFmode
1038      so that we don't lose any of the precision of the high word
1039      while multiplying it.  */
1040   DFtype f;
1041
1042   /* Protect against double-rounding error.
1043      Represent any low-order bits, that might be truncated in DFmode,
1044      by a bit that won't be lost.  The bit can go in anywhere below the
1045      rounding position of the SFmode.  A fixed mask and bit position
1046      handles all usual configurations.  It doesn't handle the case
1047      of 128-bit DImode, however.  */
1048   if (DF_SIZE < DI_SIZE
1049       && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1050     {
1051 #define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
1052       if (! (- ((DItype) 1 << DF_SIZE) < u
1053              && u < ((DItype) 1 << DF_SIZE)))
1054         {
1055           if ((USItype) u & (REP_BIT - 1))
1056             u |= REP_BIT;
1057         }
1058     }
1059   f = (SItype) (u >> WORD_SIZE);
1060   f *= HIGH_HALFWORD_COEFF;
1061   f *= HIGH_HALFWORD_COEFF;
1062   f += (USItype) (u & (HIGH_WORD_COEFF - 1));
1063
1064   return (SFtype) f;
1065 }
1066 #endif
1067
1068 #if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96
1069 /* Reenable the normal types, in case limits.h needs them.  */
1070 #undef char
1071 #undef short
1072 #undef int
1073 #undef long
1074 #undef unsigned
1075 #undef float
1076 #undef double
1077 #undef MIN
1078 #undef MAX
1079 #include <limits.h>
1080
1081 USItype
1082 __fixunsxfsi (XFtype a)
1083 {
1084   if (a >= - (DFtype) LONG_MIN)
1085     return (SItype) (a + LONG_MIN) - LONG_MIN;
1086   return (SItype) a;
1087 }
1088 #endif
1089
1090 #ifdef L_fixunsdfsi
1091 /* Reenable the normal types, in case limits.h needs them.  */
1092 #undef char
1093 #undef short
1094 #undef int
1095 #undef long
1096 #undef unsigned
1097 #undef float
1098 #undef double
1099 #undef MIN
1100 #undef MAX
1101 #include <limits.h>
1102
1103 USItype
1104 __fixunsdfsi (DFtype a)
1105 {
1106   if (a >= - (DFtype) LONG_MIN)
1107     return (SItype) (a + LONG_MIN) - LONG_MIN;
1108   return (SItype) a;
1109 }
1110 #endif
1111
1112 #ifdef L_fixunssfsi
1113 /* Reenable the normal types, in case limits.h needs them.  */
1114 #undef char
1115 #undef short
1116 #undef int
1117 #undef long
1118 #undef unsigned
1119 #undef float
1120 #undef double
1121 #undef MIN
1122 #undef MAX
1123 #include <limits.h>
1124
1125 USItype
1126 __fixunssfsi (SFtype a)
1127 {
1128   if (a >= - (SFtype) LONG_MIN)
1129     return (SItype) (a + LONG_MIN) - LONG_MIN;
1130   return (SItype) a;
1131 }
1132 #endif
1133 \f
1134 /* From here on down, the routines use normal data types.  */
1135
1136 #define SItype bogus_type
1137 #define USItype bogus_type
1138 #define DItype bogus_type
1139 #define UDItype bogus_type
1140 #define SFtype bogus_type
1141 #define DFtype bogus_type
1142
1143 #undef char
1144 #undef short
1145 #undef int
1146 #undef long
1147 #undef unsigned
1148 #undef float
1149 #undef double
1150 \f
1151 #ifdef L__gcc_bcmp
1152
1153 /* Like bcmp except the sign is meaningful.
1154    Result is negative if S1 is less than S2,
1155    positive if S1 is greater, 0 if S1 and S2 are equal.  */
1156
1157 int
1158 __gcc_bcmp (unsigned char *s1, unsigned char *s2, size_t size)
1159 {
1160   while (size > 0)
1161     {
1162       unsigned char c1 = *s1++, c2 = *s2++;
1163       if (c1 != c2)
1164         return c1 - c2;
1165       size--;
1166     }
1167   return 0;
1168 }
1169
1170 #endif
1171 \f\f
1172 #ifdef L__dummy
1173 void
1174 __dummy () {}
1175 #endif
1176
1177 #ifdef L_varargs
1178 #ifdef __i860__
1179 #if defined(__svr4__) || defined(__alliant__)
1180         asm ("  .text");
1181         asm ("  .align  4");
1182
1183 /* The Alliant needs the added underscore.  */
1184         asm (".globl    __builtin_saveregs");
1185 asm ("__builtin_saveregs:");
1186         asm (".globl    ___builtin_saveregs");
1187 asm ("___builtin_saveregs:");
1188
1189         asm ("  andnot  0x0f,%sp,%sp"); /* round down to 16-byte boundary */
1190         asm ("  adds    -96,%sp,%sp");  /* allocate stack space for reg save
1191                                            area and also for a new va_list
1192                                            structure */
1193         /* Save all argument registers in the arg reg save area.  The
1194            arg reg save area must have the following layout (according
1195            to the svr4 ABI):
1196
1197                 struct {
1198                   union  {
1199                     float freg[8];
1200                     double dreg[4];
1201                   } float_regs;
1202                   long  ireg[12];
1203                 };
1204         */
1205
1206         asm ("  fst.q   %f8,  0(%sp)"); /* save floating regs (f8-f15)  */
1207         asm ("  fst.q   %f12,16(%sp)"); 
1208
1209         asm ("  st.l    %r16,32(%sp)"); /* save integer regs (r16-r27) */
1210         asm ("  st.l    %r17,36(%sp)"); 
1211         asm ("  st.l    %r18,40(%sp)");
1212         asm ("  st.l    %r19,44(%sp)");
1213         asm ("  st.l    %r20,48(%sp)");
1214         asm ("  st.l    %r21,52(%sp)");
1215         asm ("  st.l    %r22,56(%sp)");
1216         asm ("  st.l    %r23,60(%sp)");
1217         asm ("  st.l    %r24,64(%sp)");
1218         asm ("  st.l    %r25,68(%sp)");
1219         asm ("  st.l    %r26,72(%sp)");
1220         asm ("  st.l    %r27,76(%sp)");
1221
1222         asm ("  adds    80,%sp,%r16");  /* compute the address of the new
1223                                            va_list structure.  Put in into
1224                                            r16 so that it will be returned
1225                                            to the caller.  */
1226
1227         /* Initialize all fields of the new va_list structure.  This
1228            structure looks like:
1229
1230                 typedef struct {
1231                     unsigned long       ireg_used;
1232                     unsigned long       freg_used;
1233                     long                *reg_base;
1234                     long                *mem_ptr;
1235                 } va_list;
1236         */
1237
1238         asm ("  st.l    %r0, 0(%r16)"); /* nfixed */
1239         asm ("  st.l    %r0, 4(%r16)"); /* nfloating */
1240         asm ("  st.l    %sp, 8(%r16)"); /* __va_ctl points to __va_struct.  */
1241         asm ("  bri     %r1");          /* delayed return */
1242         asm ("  st.l    %r28,12(%r16)"); /* pointer to overflow args */
1243
1244 #else /* not __svr4__ */
1245 #if defined(__PARAGON__)
1246         /*
1247          *      we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
1248          *      and we stand a better chance of hooking into libraries
1249          *      compiled by PGI.  [andyp@ssd.intel.com]
1250          */
1251         asm ("  .text");
1252         asm ("  .align  4");
1253         asm (".globl    __builtin_saveregs");
1254 asm ("__builtin_saveregs:");
1255         asm (".globl    ___builtin_saveregs");
1256 asm ("___builtin_saveregs:");
1257
1258         asm ("  andnot  0x0f,sp,sp");   /* round down to 16-byte boundary */
1259         asm ("  adds    -96,sp,sp");    /* allocate stack space for reg save
1260                                            area and also for a new va_list
1261                                            structure */
1262         /* Save all argument registers in the arg reg save area.  The
1263            arg reg save area must have the following layout (according
1264            to the svr4 ABI):
1265
1266                 struct {
1267                   union  {
1268                     float freg[8];
1269                     double dreg[4];
1270                   } float_regs;
1271                   long  ireg[12];
1272                 };
1273         */
1274
1275         asm ("  fst.q   f8,  0(sp)");
1276         asm ("  fst.q   f12,16(sp)"); 
1277         asm ("  st.l    r16,32(sp)");
1278         asm ("  st.l    r17,36(sp)"); 
1279         asm ("  st.l    r18,40(sp)");
1280         asm ("  st.l    r19,44(sp)");
1281         asm ("  st.l    r20,48(sp)");
1282         asm ("  st.l    r21,52(sp)");
1283         asm ("  st.l    r22,56(sp)");
1284         asm ("  st.l    r23,60(sp)");
1285         asm ("  st.l    r24,64(sp)");
1286         asm ("  st.l    r25,68(sp)");
1287         asm ("  st.l    r26,72(sp)");
1288         asm ("  st.l    r27,76(sp)");
1289
1290         asm ("  adds    80,sp,r16");  /* compute the address of the new
1291                                            va_list structure.  Put in into
1292                                            r16 so that it will be returned
1293                                            to the caller.  */
1294
1295         /* Initialize all fields of the new va_list structure.  This
1296            structure looks like:
1297
1298                 typedef struct {
1299                     unsigned long       ireg_used;
1300                     unsigned long       freg_used;
1301                     long                *reg_base;
1302                     long                *mem_ptr;
1303                 } va_list;
1304         */
1305
1306         asm ("  st.l    r0, 0(r16)"); /* nfixed */
1307         asm ("  st.l    r0, 4(r16)"); /* nfloating */
1308         asm ("  st.l    sp, 8(r16)"); /* __va_ctl points to __va_struct.  */
1309         asm ("  bri     r1");           /* delayed return */
1310         asm ("   st.l   r28,12(r16)"); /* pointer to overflow args */
1311 #else /* not __PARAGON__ */
1312         asm ("  .text");
1313         asm ("  .align  4");
1314
1315         asm (".globl    ___builtin_saveregs");
1316         asm ("___builtin_saveregs:");
1317         asm ("  mov     sp,r30");
1318         asm ("  andnot  0x0f,sp,sp");
1319         asm ("  adds    -96,sp,sp");  /* allocate sufficient space on the stack */
1320
1321 /* Fill in the __va_struct.  */
1322         asm ("  st.l    r16, 0(sp)"); /* save integer regs (r16-r27) */
1323         asm ("  st.l    r17, 4(sp)"); /* int    fixed[12] */
1324         asm ("  st.l    r18, 8(sp)");
1325         asm ("  st.l    r19,12(sp)");
1326         asm ("  st.l    r20,16(sp)");
1327         asm ("  st.l    r21,20(sp)");
1328         asm ("  st.l    r22,24(sp)");
1329         asm ("  st.l    r23,28(sp)");
1330         asm ("  st.l    r24,32(sp)");
1331         asm ("  st.l    r25,36(sp)");
1332         asm ("  st.l    r26,40(sp)");
1333         asm ("  st.l    r27,44(sp)");
1334
1335         asm ("  fst.q   f8, 48(sp)"); /* save floating regs (f8-f15) */
1336         asm ("  fst.q   f12,64(sp)"); /* int floating[8] */
1337
1338 /* Fill in the __va_ctl.  */
1339         asm ("  st.l    sp, 80(sp)"); /* __va_ctl points to __va_struct.  */
1340         asm ("  st.l    r28,84(sp)"); /* pointer to more args */
1341         asm ("  st.l    r0, 88(sp)"); /* nfixed */
1342         asm ("  st.l    r0, 92(sp)"); /* nfloating */
1343
1344         asm ("  adds    80,sp,r16");  /* return address of the __va_ctl.  */
1345         asm ("  bri     r1");
1346         asm ("  mov     r30,sp");
1347                                 /* recover stack and pass address to start 
1348                                    of data.  */
1349 #endif /* not __PARAGON__ */
1350 #endif /* not __svr4__ */
1351 #else /* not __i860__ */
1352 #ifdef __sparc__
1353         asm (".global __builtin_saveregs");
1354         asm ("__builtin_saveregs:");
1355         asm (".global ___builtin_saveregs");
1356         asm ("___builtin_saveregs:");
1357 #ifdef NEED_PROC_COMMAND
1358         asm (".proc 020");
1359 #endif
1360         asm ("st %i0,[%fp+68]");
1361         asm ("st %i1,[%fp+72]");
1362         asm ("st %i2,[%fp+76]");
1363         asm ("st %i3,[%fp+80]");
1364         asm ("st %i4,[%fp+84]");
1365         asm ("retl");
1366         asm ("st %i5,[%fp+88]");
1367 #ifdef NEED_TYPE_COMMAND
1368         asm (".type __builtin_saveregs,#function");
1369         asm (".size __builtin_saveregs,.-__builtin_saveregs");
1370 #endif
1371 #else /* not __sparc__ */
1372 #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1373
1374   asm ("        .text");
1375 #ifdef __mips16
1376   asm ("        .set nomips16");
1377 #endif
1378   asm ("        .ent __builtin_saveregs");
1379   asm ("        .globl __builtin_saveregs");
1380   asm ("__builtin_saveregs:");
1381   asm ("        sw      $4,0($30)");
1382   asm ("        sw      $5,4($30)");
1383   asm ("        sw      $6,8($30)");
1384   asm ("        sw      $7,12($30)");
1385   asm ("        j       $31");
1386   asm ("        .end __builtin_saveregs");
1387 #else /* not __mips__, etc.  */
1388
1389 void *
1390 __builtin_saveregs ()
1391 {
1392   abort ();
1393 }
1394
1395 #endif /* not __mips__ */
1396 #endif /* not __sparc__ */
1397 #endif /* not __i860__ */
1398 #endif
1399 \f
1400 #ifdef L_eprintf
1401 #ifndef inhibit_libc
1402
1403 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1404 #include <stdio.h>
1405 /* This is used by the `assert' macro.  */
1406 void
1407 __eprintf (const char *string, const char *expression,
1408            int line, const char *filename)
1409 {
1410   fprintf (stderr, string, expression, line, filename);
1411   fflush (stderr);
1412   abort ();
1413 }
1414
1415 #endif
1416 #endif
1417
1418 #ifdef L_bb
1419
1420 /* Structure emitted by -a  */
1421 struct bb
1422 {
1423   long zero_word;
1424   const char *filename;
1425   long *counts;
1426   long ncounts;
1427   struct bb *next;
1428   const unsigned long *addresses;
1429
1430   /* Older GCC's did not emit these fields.  */
1431   long nwords;
1432   const char **functions;
1433   const long *line_nums;
1434   const char **filenames;
1435   char *flags;
1436 };
1437
1438 #ifdef BLOCK_PROFILER_CODE
1439 BLOCK_PROFILER_CODE
1440 #else
1441 #ifndef inhibit_libc
1442
1443 /* Simple minded basic block profiling output dumper for
1444    systems that don't provide tcov support.  At present,
1445    it requires atexit and stdio.  */
1446
1447 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1448 #include <stdio.h>
1449 char *ctime ();
1450
1451 #include "gbl-ctors.h"
1452 #include "gcov-io.h"
1453 #include <string.h>
1454
1455 static struct bb *bb_head;
1456
1457 /* Return the number of digits needed to print a value */
1458 /* __inline__ */ static int num_digits (long value, int base)
1459 {
1460   int minus = (value < 0 && base != 16);
1461   unsigned long v = (minus) ? -value : value;
1462   int ret = minus;
1463
1464   do
1465     {
1466       v /= base;
1467       ret++;
1468     }
1469   while (v);
1470
1471   return ret;
1472 }
1473
1474 void
1475 __bb_exit_func (void)
1476 {
1477   FILE *da_file, *file;
1478   long time_value;
1479   int i;
1480
1481   if (bb_head == 0)
1482     return;
1483
1484   i = strlen (bb_head->filename) - 3;
1485
1486   if (!strcmp (bb_head->filename+i, ".da"))
1487     {
1488       /* Must be -fprofile-arcs not -a.
1489          Dump data in a form that gcov expects.  */
1490
1491       struct bb *ptr;
1492
1493       for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1494         {
1495           /* If the file exists, and the number of counts in it is the same,
1496              then merge them in.  */
1497              
1498           if ((da_file = fopen (ptr->filename, "r")) != 0)
1499             {
1500               long n_counts = 0;
1501               
1502               if (__read_long (&n_counts, da_file, 8) != 0)
1503                 {
1504                   fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1505                            ptr->filename);
1506                   continue;
1507                 }
1508
1509               if (n_counts == ptr->ncounts)
1510                 {
1511                   int i;
1512
1513                   for (i = 0; i < n_counts; i++)
1514                     {
1515                       long v = 0;
1516
1517                       if (__read_long (&v, da_file, 8) != 0)
1518                         {
1519                           fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1520                                    ptr->filename);
1521                           break;
1522                         }
1523                       ptr->counts[i] += v;
1524                     }
1525                 }
1526
1527               if (fclose (da_file) == EOF)
1528                 fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1529                          ptr->filename);
1530             }
1531           if ((da_file = fopen (ptr->filename, "w")) == 0)
1532             {
1533               fprintf (stderr, "arc profiling: Can't open output file %s.\n",
1534                        ptr->filename);
1535               continue;
1536             }
1537
1538           /* ??? Should first write a header to the file.  Preferably, a 4 byte
1539              magic number, 4 bytes containing the time the program was
1540              compiled, 4 bytes containing the last modification time of the
1541              source file, and 4 bytes indicating the compiler options used.
1542
1543              That way we can easily verify that the proper source/executable/
1544              data file combination is being used from gcov.  */
1545
1546           if (__write_long (ptr->ncounts, da_file, 8) != 0)
1547             {
1548               
1549               fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1550                        ptr->filename);
1551             }
1552           else
1553             {
1554               int j;
1555               long *count_ptr = ptr->counts;
1556               int ret = 0;
1557               for (j = ptr->ncounts; j > 0; j--)
1558                 {
1559                   if (__write_long (*count_ptr, da_file, 8) != 0)
1560                     {
1561                       ret=1;
1562                       break;
1563                     }
1564                   count_ptr++;
1565                 }
1566               if (ret)
1567                 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1568                          ptr->filename);
1569             }
1570           
1571           if (fclose (da_file) == EOF)
1572             fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1573                      ptr->filename);
1574         }
1575
1576       return;
1577     }
1578
1579   /* Must be basic block profiling.  Emit a human readable output file.  */
1580
1581   file = fopen ("bb.out", "a");
1582
1583   if (!file)
1584     perror ("bb.out");
1585
1586   else
1587     {
1588       struct bb *ptr;
1589
1590       /* This is somewhat type incorrect, but it avoids worrying about
1591          exactly where time.h is included from.  It should be ok unless
1592          a void * differs from other pointer formats, or if sizeof (long)
1593          is < sizeof (time_t).  It would be nice if we could assume the
1594          use of rationale standards here.  */
1595
1596       time ((void *) &time_value);
1597       fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1598
1599       /* We check the length field explicitly in order to allow compatibility
1600          with older GCC's which did not provide it.  */
1601
1602       for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1603         {
1604           int i;
1605           int func_p    = (ptr->nwords >= sizeof (struct bb)
1606                            && ptr->nwords <= 1000
1607                            && ptr->functions);
1608           int line_p    = (func_p && ptr->line_nums);
1609           int file_p    = (func_p && ptr->filenames);
1610           int addr_p    = (ptr->addresses != 0);
1611           long ncounts  = ptr->ncounts;
1612           long cnt_max  = 0;
1613           long line_max = 0;
1614           long addr_max = 0;
1615           int file_len  = 0;
1616           int func_len  = 0;
1617           int blk_len   = num_digits (ncounts, 10);
1618           int cnt_len;
1619           int line_len;
1620           int addr_len;
1621
1622           fprintf (file, "File %s, %ld basic blocks \n\n",
1623                    ptr->filename, ncounts);
1624
1625           /* Get max values for each field.  */
1626           for (i = 0; i < ncounts; i++)
1627             {
1628               const char *p;
1629               int len;
1630
1631               if (cnt_max < ptr->counts[i])
1632                 cnt_max = ptr->counts[i];
1633
1634               if (addr_p && addr_max < ptr->addresses[i])
1635                 addr_max = ptr->addresses[i];
1636
1637               if (line_p && line_max < ptr->line_nums[i])
1638                 line_max = ptr->line_nums[i];
1639
1640               if (func_p)
1641                 {
1642                   p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1643                   len = strlen (p);
1644                   if (func_len < len)
1645                     func_len = len;
1646                 }
1647
1648               if (file_p)
1649                 {
1650                   p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1651                   len = strlen (p);
1652                   if (file_len < len)
1653                     file_len = len;
1654                 }
1655             }
1656
1657           addr_len = num_digits (addr_max, 16);
1658           cnt_len  = num_digits (cnt_max, 10);
1659           line_len = num_digits (line_max, 10);
1660
1661           /* Now print out the basic block information.  */
1662           for (i = 0; i < ncounts; i++)
1663             {
1664               fprintf (file,
1665                        "    Block #%*d: executed %*ld time(s)",
1666                        blk_len, i+1,
1667                        cnt_len, ptr->counts[i]);
1668
1669               if (addr_p)
1670                 fprintf (file, " address= 0x%.*lx", addr_len,
1671                          ptr->addresses[i]);
1672
1673               if (func_p)
1674                 fprintf (file, " function= %-*s", func_len,
1675                          (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1676
1677               if (line_p)
1678                 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
1679
1680               if (file_p)
1681                 fprintf (file, " file= %s",
1682                          (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1683
1684               fprintf (file, "\n");
1685             }
1686
1687           fprintf (file, "\n");
1688           fflush (file);
1689         }
1690
1691       fprintf (file, "\n\n");
1692       fclose (file);
1693     }
1694 }
1695
1696 void
1697 __bb_init_func (struct bb *blocks)
1698 {
1699   /* User is supposed to check whether the first word is non-0,
1700      but just in case....  */
1701
1702   if (blocks->zero_word)
1703     return;
1704
1705 #ifdef ON_EXIT
1706   /* Initialize destructor.  */
1707   if (!bb_head)
1708     ON_EXIT (__bb_exit_func, 0);
1709 #endif
1710
1711   /* Set up linked list.  */
1712   blocks->zero_word = 1;
1713   blocks->next = bb_head;
1714   bb_head = blocks;
1715 }
1716
1717 #ifndef MACHINE_STATE_SAVE
1718 #define MACHINE_STATE_SAVE(ID)
1719 #endif
1720 #ifndef MACHINE_STATE_RESTORE
1721 #define MACHINE_STATE_RESTORE(ID)
1722 #endif
1723
1724 /* Number of buckets in hashtable of basic block addresses.  */
1725
1726 #define BB_BUCKETS 311
1727
1728 /* Maximum length of string in file bb.in.  */
1729
1730 #define BBINBUFSIZE 500
1731
1732 /* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
1733    "BBINBUFSIZE" but want to avoid trouble with preprocessors.  */
1734
1735 #define BBINBUFSIZESTR "499"
1736
1737 struct bb_edge
1738 {
1739   struct bb_edge *next;
1740   unsigned long src_addr;
1741   unsigned long dst_addr;
1742   unsigned long count;
1743 };
1744
1745 enum bb_func_mode
1746 {
1747   TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1748 };
1749
1750 struct bb_func
1751 {
1752   struct bb_func *next;
1753   char *funcname;
1754   char *filename;
1755   enum bb_func_mode mode;
1756 };
1757
1758 /* This is the connection to the outside world.
1759    The BLOCK_PROFILER macro must set __bb.blocks
1760    and __bb.blockno.  */
1761
1762 struct {
1763   unsigned long blockno;
1764   struct bb *blocks;
1765 } __bb;
1766
1767 /* Vars to store addrs of source and destination basic blocks 
1768    of a jump.  */
1769
1770 static unsigned long bb_src = 0;
1771 static unsigned long bb_dst = 0;
1772
1773 static FILE *bb_tracefile = (FILE *) 0;
1774 static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
1775 static struct bb_func *bb_func_head = (struct bb_func *) 0;
1776 static unsigned long bb_callcount = 0;
1777 static int bb_mode = 0;
1778
1779 static unsigned long *bb_stack = (unsigned long *) 0;
1780 static size_t bb_stacksize = 0;
1781
1782 static int reported = 0;
1783
1784 /* Trace modes:
1785 Always             :   Print execution frequencies of basic blocks
1786                        to file bb.out.
1787 bb_mode & 1 != 0   :   Dump trace of basic blocks to file bbtrace[.gz]
1788 bb_mode & 2 != 0   :   Print jump frequencies to file bb.out.
1789 bb_mode & 4 != 0   :   Cut call instructions from basic block flow.
1790 bb_mode & 8 != 0   :   Insert return instructions in basic block flow.
1791 */
1792
1793 #ifdef HAVE_POPEN
1794
1795 /*#include <sys/types.h>*/
1796 #include <sys/stat.h>
1797 /*#include <malloc.h>*/
1798
1799 /* Commands executed by gopen.  */
1800
1801 #define GOPENDECOMPRESS "gzip -cd "
1802 #define GOPENCOMPRESS "gzip -c >"
1803
1804 /* Like fopen but pipes through gzip.  mode may only be "r" or "w".
1805    If it does not compile, simply replace gopen by fopen and delete
1806    '.gz' from any first parameter to gopen.  */
1807
1808 static FILE *
1809 gopen (char *fn, char *mode)
1810 {
1811   int use_gzip;
1812   char *p;
1813
1814   if (mode[1])
1815     return (FILE *) 0;
1816
1817   if (mode[0] != 'r' && mode[0] != 'w') 
1818     return (FILE *) 0;
1819
1820   p = fn + strlen (fn)-1;
1821   use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
1822               || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
1823
1824   if (use_gzip)
1825     {
1826       if (mode[0]=='r')
1827         {
1828           FILE *f;
1829           char *s = (char *) malloc (sizeof (char) * strlen (fn)
1830                                      + sizeof (GOPENDECOMPRESS));
1831           strcpy (s, GOPENDECOMPRESS);
1832           strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1833           f = popen (s, mode);
1834           free (s);
1835           return f;
1836         }
1837
1838       else
1839         {
1840           FILE *f;
1841           char *s = (char *) malloc (sizeof (char) * strlen (fn)
1842                                      + sizeof (GOPENCOMPRESS));
1843           strcpy (s, GOPENCOMPRESS);
1844           strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1845           if (!(f = popen (s, mode)))
1846             f = fopen (s, mode);
1847           free (s);
1848           return f;
1849         }
1850     }
1851
1852   else
1853     return fopen (fn, mode);
1854 }
1855
1856 static int
1857 gclose (FILE *f)
1858 {
1859   struct stat buf;
1860
1861   if (f != 0)
1862     {
1863       if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1864         return pclose (f);
1865
1866       return fclose (f);
1867     }
1868   return 0;
1869 }
1870
1871 #endif /* HAVE_POPEN */
1872
1873 /* Called once per program.  */
1874
1875 static void
1876 __bb_exit_trace_func ()
1877 {
1878   FILE *file = fopen ("bb.out", "a");
1879   struct bb_func *f;
1880   struct bb *b;
1881         
1882   if (!file)
1883     perror ("bb.out");
1884
1885   if (bb_mode & 1)
1886     {
1887       if (!bb_tracefile)
1888         perror ("bbtrace");
1889       else
1890 #ifdef HAVE_POPEN
1891         gclose (bb_tracefile);
1892 #else
1893         fclose (bb_tracefile);
1894 #endif /* HAVE_POPEN */
1895     }
1896
1897   /* Check functions in `bb.in'.  */
1898
1899   if (file)
1900     {
1901       long time_value;
1902       const struct bb_func *p;
1903       int printed_something = 0;
1904       struct bb *ptr;
1905       long blk;
1906
1907       /* This is somewhat type incorrect.  */
1908       time ((void *) &time_value);
1909
1910       for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
1911         {
1912           for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1913             {
1914               if (!ptr->filename || (p->filename != (char *) 0 && strcmp (p->filename, ptr->filename)))
1915                 continue;
1916               for (blk = 0; blk < ptr->ncounts; blk++)
1917                 {
1918                   if (!strcmp (p->funcname, ptr->functions[blk]))
1919                     goto found;
1920                 }
1921             }
1922   
1923           if (!printed_something)
1924             {
1925               fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
1926               printed_something = 1;
1927             }
1928
1929           fprintf (file, "\tFunction %s", p->funcname);
1930           if (p->filename)
1931               fprintf (file, " of file %s", p->filename);
1932           fprintf (file, "\n" );
1933   
1934 found:        ;
1935         }
1936
1937       if (printed_something)
1938        fprintf (file, "\n");
1939
1940     }
1941
1942   if (bb_mode & 2)
1943     {
1944       if (!bb_hashbuckets)
1945         {
1946           if (!reported)
1947             {
1948               fprintf (stderr, "Profiler: out of memory\n");
1949               reported = 1;
1950             }
1951           return;
1952         }
1953     
1954       else if (file)
1955         {
1956           long time_value;
1957           int i;
1958           unsigned long addr_max = 0;
1959           unsigned long cnt_max  = 0;
1960           int cnt_len;
1961           int addr_len;
1962     
1963           /* This is somewhat type incorrect, but it avoids worrying about
1964              exactly where time.h is included from.  It should be ok unless
1965              a void * differs from other pointer formats, or if sizeof (long)
1966              is < sizeof (time_t).  It would be nice if we could assume the
1967              use of rationale standards here.  */
1968     
1969           time ((void *) &time_value);
1970           fprintf (file, "Basic block jump tracing");
1971
1972           switch (bb_mode & 12)
1973             {
1974               case 0:
1975                 fprintf (file, " (with call)");
1976               break;
1977
1978               case 4:
1979                 /* Print nothing.  */
1980               break;
1981
1982               case 8:
1983                 fprintf (file, " (with call & ret)");
1984               break;
1985
1986               case 12:
1987                 fprintf (file, " (with ret)");
1988               break;
1989             }
1990
1991           fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
1992     
1993           for (i = 0; i < BB_BUCKETS; i++)
1994             {
1995                struct bb_edge *bucket = bb_hashbuckets[i];
1996                for ( ; bucket; bucket = bucket->next )
1997                  {
1998                    if (addr_max < bucket->src_addr) 
1999                      addr_max = bucket->src_addr;
2000                    if (addr_max < bucket->dst_addr) 
2001                      addr_max = bucket->dst_addr;
2002                    if (cnt_max < bucket->count) 
2003                      cnt_max = bucket->count;
2004                  }
2005             }
2006           addr_len = num_digits (addr_max, 16);
2007           cnt_len  = num_digits (cnt_max, 10);
2008     
2009           for ( i = 0; i < BB_BUCKETS; i++)
2010             {
2011                struct bb_edge *bucket = bb_hashbuckets[i];
2012                for ( ; bucket; bucket = bucket->next )
2013                  {
2014                    fprintf (file, "Jump from block 0x%.*lx to "
2015                                   "block 0x%.*lx executed %*lu time(s)\n", 
2016                             addr_len, bucket->src_addr, 
2017                             addr_len, bucket->dst_addr, 
2018                             cnt_len, bucket->count);
2019                  }
2020             }
2021   
2022           fprintf (file, "\n");
2023
2024         }
2025     }
2026
2027    if (file)
2028      fclose (file);
2029
2030    /* Free allocated memory.  */
2031
2032    f = bb_func_head;
2033    while (f)
2034      {
2035        struct bb_func *old = f;
2036
2037        f = f->next;
2038        if (old->funcname) free (old->funcname);
2039        if (old->filename) free (old->filename);
2040        free (old);
2041      }
2042
2043    if (bb_stack)
2044      free (bb_stack);
2045
2046    if (bb_hashbuckets)
2047      {
2048        int i;
2049
2050        for (i = 0; i < BB_BUCKETS; i++)
2051          {
2052            struct bb_edge *old, *bucket = bb_hashbuckets[i];
2053
2054            while (bucket)
2055              {
2056                old = bucket;
2057                bucket = bucket->next;
2058                free (old);
2059              }
2060          }
2061        free (bb_hashbuckets);
2062      }
2063
2064    for (b = bb_head; b; b = b->next)
2065      if (b->flags) free (b->flags);
2066 }
2067
2068 /* Called once per program.  */
2069
2070 static void
2071 __bb_init_prg ()
2072 {
2073
2074   FILE *file;
2075   char buf[BBINBUFSIZE];
2076   const char *p;
2077   const char *pos;
2078   enum bb_func_mode m;
2079
2080 #ifdef ON_EXIT
2081   /* Initialize destructor.  */
2082   ON_EXIT (__bb_exit_func, 0);
2083 #endif
2084
2085   if (!(file = fopen ("bb.in", "r")))
2086     return;
2087
2088   while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
2089     {
2090       p = buf;
2091       if (*p == '-') 
2092         { 
2093           m = TRACE_OFF; 
2094           p++; 
2095         }
2096       else 
2097         { 
2098           m = TRACE_ON; 
2099         }
2100       if (!strcmp (p, "__bb_trace__"))
2101         bb_mode |= 1;
2102       else if (!strcmp (p, "__bb_jumps__"))
2103         bb_mode |= 2;
2104       else if (!strcmp (p, "__bb_hidecall__"))
2105         bb_mode |= 4;
2106       else if (!strcmp (p, "__bb_showret__"))
2107         bb_mode |= 8;
2108       else 
2109         {
2110           struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
2111           if (f)
2112             {
2113               unsigned long l;
2114               f->next = bb_func_head;
2115               if ((pos = strchr (p, ':')))
2116                 {
2117                   if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
2118                     continue;
2119                   strcpy (f->funcname, pos+1);
2120                   l = pos-p;
2121                   if ((f->filename = (char *) malloc (l+1)))
2122                     {
2123                       strncpy (f->filename, p, l);
2124                       f->filename[l] = '\0';
2125                     }
2126                   else
2127                     f->filename = (char *) 0;
2128                 }
2129               else
2130                 {
2131                   if (!(f->funcname = (char *) malloc (strlen (p)+1)))
2132                     continue;
2133                   strcpy (f->funcname, p);
2134                   f->filename = (char *) 0;
2135                 }
2136               f->mode = m;
2137               bb_func_head = f;
2138             }
2139          }
2140     }
2141   fclose (file);
2142
2143 #ifdef HAVE_POPEN 
2144
2145   if (bb_mode & 1)
2146       bb_tracefile = gopen ("bbtrace.gz", "w");
2147
2148 #else
2149
2150   if (bb_mode & 1)
2151       bb_tracefile = fopen ("bbtrace", "w");
2152
2153 #endif /* HAVE_POPEN */
2154
2155   if (bb_mode & 2)
2156     {
2157       bb_hashbuckets = (struct bb_edge **) 
2158                    malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2159       if (bb_hashbuckets)
2160         memset (bb_hashbuckets, 0, BB_BUCKETS * sizeof (struct bb_edge *));
2161     }
2162
2163   if (bb_mode & 12)
2164     {
2165       bb_stacksize = 10;
2166       bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2167     }
2168
2169 #ifdef ON_EXIT
2170       /* Initialize destructor.  */
2171       ON_EXIT (__bb_exit_trace_func, 0);
2172 #endif
2173
2174 }
2175
2176 /* Called upon entering a basic block.  */
2177
2178 void
2179 __bb_trace_func ()
2180 {
2181   struct bb_edge *bucket;
2182
2183   MACHINE_STATE_SAVE("1")
2184
2185   if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2186     goto skip;
2187
2188   bb_dst = __bb.blocks->addresses[__bb.blockno];
2189   __bb.blocks->counts[__bb.blockno]++;
2190
2191   if (bb_tracefile)
2192     {
2193       fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2194     }
2195
2196   if (bb_hashbuckets)
2197     {
2198       struct bb_edge **startbucket, **oldnext;
2199
2200       oldnext = startbucket
2201         = & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
2202       bucket = *startbucket;
2203
2204       for (bucket = *startbucket; bucket; 
2205            oldnext = &(bucket->next), bucket = *oldnext)
2206         {
2207           if (bucket->src_addr == bb_src
2208               && bucket->dst_addr == bb_dst)
2209             {
2210               bucket->count++;
2211               *oldnext = bucket->next;
2212               bucket->next = *startbucket;
2213               *startbucket = bucket;
2214               goto ret;
2215             }
2216         }
2217
2218       bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2219
2220       if (!bucket)
2221         {
2222           if (!reported)
2223             {
2224               fprintf (stderr, "Profiler: out of memory\n");
2225               reported = 1;
2226             }
2227         }
2228
2229       else
2230         {
2231           bucket->src_addr = bb_src;
2232           bucket->dst_addr = bb_dst;
2233           bucket->next = *startbucket;
2234           *startbucket = bucket;
2235           bucket->count = 1;
2236         }
2237     }
2238
2239 ret:
2240   bb_src = bb_dst;
2241
2242 skip:
2243   ;
2244
2245   MACHINE_STATE_RESTORE("1")
2246
2247 }
2248
2249 /* Called when returning from a function and `__bb_showret__' is set.  */
2250
2251 static void
2252 __bb_trace_func_ret ()
2253 {
2254   struct bb_edge *bucket;
2255
2256   if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2257     goto skip;
2258
2259   if (bb_hashbuckets)
2260     {
2261       struct bb_edge **startbucket, **oldnext;
2262
2263       oldnext = startbucket
2264         = & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
2265       bucket = *startbucket;
2266
2267       for (bucket = *startbucket; bucket; 
2268            oldnext = &(bucket->next), bucket = *oldnext)
2269         {
2270           if (bucket->src_addr == bb_dst
2271                && bucket->dst_addr == bb_src)
2272             {
2273               bucket->count++;
2274               *oldnext = bucket->next;
2275               bucket->next = *startbucket;
2276               *startbucket = bucket;
2277               goto ret;
2278             }
2279         }
2280
2281       bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2282
2283       if (!bucket)
2284         {
2285           if (!reported)
2286             {
2287               fprintf (stderr, "Profiler: out of memory\n");
2288               reported = 1;
2289             }
2290         }
2291
2292       else
2293         {
2294           bucket->src_addr = bb_dst;
2295           bucket->dst_addr = bb_src;
2296           bucket->next = *startbucket;
2297           *startbucket = bucket;
2298           bucket->count = 1;
2299         }
2300     }
2301
2302 ret:
2303   bb_dst = bb_src;
2304
2305 skip:
2306   ;
2307
2308 }
2309
2310 /* Called upon entering the first function of a file.  */
2311
2312 static void
2313 __bb_init_file (struct bb *blocks)
2314 {
2315
2316   const struct bb_func *p;
2317   long blk, ncounts = blocks->ncounts;
2318   const char **functions = blocks->functions;
2319
2320   /* Set up linked list.  */
2321   blocks->zero_word = 1;
2322   blocks->next = bb_head;
2323   bb_head = blocks;
2324
2325   blocks->flags = 0;
2326   if (!bb_func_head
2327       || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
2328     return;
2329
2330   for (blk = 0; blk < ncounts; blk++)
2331     blocks->flags[blk] = 0;
2332
2333   for (blk = 0; blk < ncounts; blk++)
2334     {
2335       for (p = bb_func_head; p; p = p->next)
2336         {
2337           if (!strcmp (p->funcname, functions[blk])
2338               && (!p->filename || !strcmp (p->filename, blocks->filename)))
2339             {
2340               blocks->flags[blk] |= p->mode;
2341             }
2342         }
2343     }
2344
2345 }
2346
2347 /* Called when exiting from a function.  */
2348
2349 void
2350 __bb_trace_ret ()
2351 {
2352
2353   MACHINE_STATE_SAVE("2")
2354
2355   if (bb_callcount)
2356     {
2357       if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2358         {
2359           bb_src = bb_stack[bb_callcount];
2360           if (bb_mode & 8)
2361             __bb_trace_func_ret ();
2362         }
2363
2364       bb_callcount -= 1;
2365     }
2366
2367   MACHINE_STATE_RESTORE("2")
2368
2369 }
2370
2371 /* Called when entering a function.  */
2372
2373 void
2374 __bb_init_trace_func (struct bb *blocks, unsigned long blockno)
2375 {
2376   static int trace_init = 0;
2377
2378   MACHINE_STATE_SAVE("3")
2379
2380   if (!blocks->zero_word)
2381     { 
2382       if (!trace_init)
2383         { 
2384           trace_init = 1;
2385           __bb_init_prg ();
2386         }
2387       __bb_init_file (blocks);
2388     }
2389
2390   if (bb_callcount)
2391     {
2392
2393       bb_callcount += 1;
2394
2395       if (bb_mode & 12)
2396         {
2397           if (bb_callcount >= bb_stacksize)
2398             {
2399               size_t newsize = bb_callcount + 100;
2400
2401               bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2402               if (! bb_stack)
2403                 {
2404                   if (!reported)
2405                     {
2406                       fprintf (stderr, "Profiler: out of memory\n");
2407                       reported = 1;
2408                     }
2409                   bb_stacksize = 0;
2410                   goto stack_overflow;
2411                 }
2412               bb_stacksize = newsize;
2413             }
2414           bb_stack[bb_callcount] = bb_src;
2415
2416           if (bb_mode & 4)
2417             bb_src = 0;
2418
2419         }
2420
2421 stack_overflow:;
2422
2423     }
2424
2425   else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2426     {
2427       bb_callcount = 1;
2428       bb_src = 0;
2429
2430       if (bb_stack)
2431           bb_stack[bb_callcount] = bb_src;
2432     }
2433
2434   MACHINE_STATE_RESTORE("3")
2435 }
2436
2437 #endif /* not inhibit_libc */
2438 #endif /* not BLOCK_PROFILER_CODE */
2439 #endif /* L_bb */
2440 \f
2441 #ifdef L_shtab
2442 unsigned int __shtab[] = {
2443     0x00000001, 0x00000002, 0x00000004, 0x00000008,
2444     0x00000010, 0x00000020, 0x00000040, 0x00000080,
2445     0x00000100, 0x00000200, 0x00000400, 0x00000800,
2446     0x00001000, 0x00002000, 0x00004000, 0x00008000,
2447     0x00010000, 0x00020000, 0x00040000, 0x00080000,
2448     0x00100000, 0x00200000, 0x00400000, 0x00800000,
2449     0x01000000, 0x02000000, 0x04000000, 0x08000000,
2450     0x10000000, 0x20000000, 0x40000000, 0x80000000
2451   };
2452 #endif
2453 \f
2454 #ifdef L_clear_cache
2455 /* Clear part of an instruction cache.  */
2456
2457 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2458
2459 void
2460 __clear_cache (char *beg, char *end)
2461 {
2462 #ifdef CLEAR_INSN_CACHE 
2463   CLEAR_INSN_CACHE (beg, end);
2464 #else
2465 #ifdef INSN_CACHE_SIZE
2466   static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
2467   static int initialized;
2468   int offset;
2469   void *start_addr
2470   void *end_addr;
2471   typedef (*function_ptr) ();
2472
2473 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2474   /* It's cheaper to clear the whole cache.
2475      Put in a series of jump instructions so that calling the beginning
2476      of the cache will clear the whole thing.  */
2477
2478   if (! initialized)
2479     {
2480       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2481                  & -INSN_CACHE_LINE_WIDTH);
2482       int end_ptr = ptr + INSN_CACHE_SIZE;
2483
2484       while (ptr < end_ptr)
2485         {
2486           *(INSTRUCTION_TYPE *)ptr
2487             = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2488           ptr += INSN_CACHE_LINE_WIDTH;
2489         }
2490       *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
2491
2492       initialized = 1;
2493     }
2494
2495   /* Call the beginning of the sequence.  */
2496   (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2497                     & -INSN_CACHE_LINE_WIDTH))
2498    ());
2499
2500 #else /* Cache is large.  */
2501
2502   if (! initialized)
2503     {
2504       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2505                  & -INSN_CACHE_LINE_WIDTH);
2506
2507       while (ptr < (int) array + sizeof array)
2508         {
2509           *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2510           ptr += INSN_CACHE_LINE_WIDTH;
2511         }
2512
2513       initialized = 1;
2514     }
2515
2516   /* Find the location in array that occupies the same cache line as BEG.  */
2517
2518   offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2519   start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2520                  & -INSN_CACHE_PLANE_SIZE)
2521                 + offset);
2522
2523   /* Compute the cache alignment of the place to stop clearing.  */
2524 #if 0  /* This is not needed for gcc's purposes.  */
2525   /* If the block to clear is bigger than a cache plane,
2526      we clear the entire cache, and OFFSET is already correct.  */ 
2527   if (end < beg + INSN_CACHE_PLANE_SIZE)
2528 #endif
2529     offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2530                & -INSN_CACHE_LINE_WIDTH)
2531               & (INSN_CACHE_PLANE_SIZE - 1));
2532
2533 #if INSN_CACHE_DEPTH > 1
2534   end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2535   if (end_addr <= start_addr)
2536     end_addr += INSN_CACHE_PLANE_SIZE;
2537
2538   for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2539     {
2540       int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2541       int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2542
2543       while (addr != stop)
2544         {
2545           /* Call the return instruction at ADDR.  */
2546           ((function_ptr) addr) ();
2547
2548           addr += INSN_CACHE_LINE_WIDTH;
2549         }
2550     }
2551 #else /* just one plane */
2552   do
2553     {
2554       /* Call the return instruction at START_ADDR.  */
2555       ((function_ptr) start_addr) ();
2556
2557       start_addr += INSN_CACHE_LINE_WIDTH;
2558     }
2559   while ((start_addr % INSN_CACHE_SIZE) != offset);
2560 #endif /* just one plane */
2561 #endif /* Cache is large */
2562 #endif /* Cache exists */
2563 #endif /* CLEAR_INSN_CACHE */
2564 }
2565
2566 #endif /* L_clear_cache */
2567 \f
2568 #ifdef L_trampoline
2569
2570 /* Jump to a trampoline, loading the static chain address.  */
2571
2572 #if defined(WINNT) && ! defined(__CYGWIN32__)
2573
2574 long getpagesize()
2575 {
2576 #ifdef _ALPHA_
2577   return 8192;
2578 #else
2579   return 4096;
2580 #endif
2581 }
2582
2583 #ifdef i386
2584 extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
2585 #endif
2586
2587 int
2588 mprotect (char *addr, int len, int prot)
2589 {
2590   int np, op;
2591
2592   if (prot == 7)
2593     np = 0x40;
2594   else if (prot == 5)
2595     np = 0x20;
2596   else if (prot == 4)
2597     np = 0x10;
2598   else if (prot == 3)
2599     np = 0x04;
2600   else if (prot == 1)
2601     np = 0x02;
2602   else if (prot == 0)
2603     np = 0x01;
2604
2605   if (VirtualProtect (addr, len, np, &op))
2606     return 0;
2607   else
2608     return -1;
2609 }
2610
2611 #endif
2612
2613 #ifdef TRANSFER_FROM_TRAMPOLINE 
2614 TRANSFER_FROM_TRAMPOLINE 
2615 #endif
2616
2617 #if defined (NeXT) && defined (__MACH__)
2618
2619 /* Make stack executable so we can call trampolines on stack.
2620    This is called from INITIALIZE_TRAMPOLINE in next.h.  */
2621 #ifdef NeXTStep21
2622  #include <mach.h>
2623 #else
2624  #include <mach/mach.h>
2625 #endif
2626
2627 void
2628 __enable_execute_stack (char *addr)
2629 {
2630   kern_return_t r;
2631   char *eaddr = addr + TRAMPOLINE_SIZE;
2632   vm_address_t a = (vm_address_t) addr;
2633
2634   /* turn on execute access on stack */
2635   r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2636   if (r != KERN_SUCCESS)
2637     {
2638       mach_error("vm_protect VM_PROT_ALL", r);
2639       exit(1);
2640     }
2641
2642   /* We inline the i-cache invalidation for speed */
2643
2644 #ifdef CLEAR_INSN_CACHE
2645   CLEAR_INSN_CACHE (addr, eaddr);
2646 #else
2647   __clear_cache ((int) addr, (int) eaddr);
2648 #endif
2649
2650
2651 #endif /* defined (NeXT) && defined (__MACH__) */
2652
2653 #ifdef __convex__
2654
2655 /* Make stack executable so we can call trampolines on stack.
2656    This is called from INITIALIZE_TRAMPOLINE in convex.h.  */
2657
2658 #include <sys/mman.h>
2659 #include <sys/vmparam.h>
2660 #include <machine/machparam.h>
2661
2662 void
2663 __enable_execute_stack ()
2664 {
2665   int fp;
2666   static unsigned lowest = USRSTACK;
2667   unsigned current = (unsigned) &fp & -NBPG;
2668
2669   if (lowest > current)
2670     {
2671       unsigned len = lowest - current;
2672       mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2673       lowest = current;
2674     }
2675
2676   /* Clear instruction cache in case an old trampoline is in it.  */
2677   asm ("pich");
2678 }
2679 #endif /* __convex__ */
2680
2681 #ifdef __sysV88__
2682
2683 /* Modified from the convex -code above.  */
2684
2685 #include <sys/param.h>
2686 #include <errno.h>
2687 #include <sys/m88kbcs.h>
2688
2689 void
2690 __enable_execute_stack ()
2691 {
2692   int save_errno;
2693   static unsigned long lowest = USRSTACK;
2694   unsigned long current = (unsigned long) &save_errno & -NBPC;
2695   
2696   /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2697      address is seen as 'negative'. That is the case with the stack.   */
2698
2699   save_errno=errno;
2700   if (lowest > current)
2701     {
2702       unsigned len=lowest-current;
2703       memctl(current,len,MCT_TEXT);
2704       lowest = current;
2705     }
2706   else
2707     memctl(current,NBPC,MCT_TEXT);
2708   errno=save_errno;
2709 }
2710
2711 #endif /* __sysV88__ */
2712
2713 #ifdef __sysV68__
2714
2715 #include <sys/signal.h>
2716 #include <errno.h>
2717
2718 /* Motorola forgot to put memctl.o in the libp version of libc881.a,
2719    so define it here, because we need it in __clear_insn_cache below */
2720 /* On older versions of this OS, no memctl or MCT_TEXT are defined;
2721    hence we enable this stuff only if MCT_TEXT is #define'd.  */
2722
2723 #ifdef MCT_TEXT
2724 asm("\n\
2725         global memctl\n\
2726 memctl:\n\
2727         movq &75,%d0\n\
2728         trap &0\n\
2729         bcc.b noerror\n\
2730         jmp cerror%\n\
2731 noerror:\n\
2732         movq &0,%d0\n\
2733         rts");
2734 #endif
2735
2736 /* Clear instruction cache so we can call trampolines on stack.
2737    This is called from FINALIZE_TRAMPOLINE in mot3300.h.  */
2738
2739 void
2740 __clear_insn_cache ()
2741 {
2742 #ifdef MCT_TEXT
2743   int save_errno;
2744
2745   /* Preserve errno, because users would be surprised to have
2746   errno changing without explicitly calling any system-call. */
2747   save_errno = errno;
2748
2749   /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache. 
2750      No need to use an address derived from _start or %sp, as 0 works also. */
2751   memctl(0, 4096, MCT_TEXT);
2752   errno = save_errno;
2753 #endif
2754 }
2755
2756 #endif /* __sysV68__ */
2757
2758 #ifdef __pyr__
2759
2760 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
2761 #include <stdio.h>
2762 #include <sys/mman.h>
2763 #include <sys/types.h>
2764 #include <sys/param.h>
2765 #include <sys/vmmac.h>
2766
2767 /* Modified from the convex -code above.
2768    mremap promises to clear the i-cache.  */
2769
2770 void
2771 __enable_execute_stack ()
2772 {
2773   int fp;
2774   if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2775                 PROT_READ|PROT_WRITE|PROT_EXEC))
2776     {
2777       perror ("mprotect in __enable_execute_stack");
2778       fflush (stderr);
2779       abort ();
2780     }
2781 }
2782 #endif /* __pyr__ */
2783
2784 #if defined (sony_news) && defined (SYSTYPE_BSD)
2785
2786 #include <stdio.h>
2787 #include <sys/types.h>
2788 #include <sys/param.h>
2789 #include <syscall.h>
2790 #include <machine/sysnews.h>
2791
2792 /* cacheflush function for NEWS-OS 4.2.
2793    This function is called from trampoline-initialize code
2794    defined in config/mips/mips.h.  */
2795
2796 void
2797 cacheflush (char *beg, int size, int flag)
2798 {
2799   if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
2800     {
2801       perror ("cache_flush");
2802       fflush (stderr);
2803       abort ();
2804     }
2805 }
2806
2807 #endif /* sony_news */
2808 #endif /* L_trampoline */
2809 \f
2810 #ifndef __CYGWIN32__
2811 #ifdef L__main
2812
2813 #include "gbl-ctors.h"
2814 /* Some systems use __main in a way incompatible with its use in gcc, in these
2815    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2816    give the same symbol without quotes for an alternative entry point.  You
2817    must define both, or neither.  */
2818 #ifndef NAME__MAIN
2819 #define NAME__MAIN "__main"
2820 #define SYMBOL__MAIN __main
2821 #endif
2822
2823 #ifdef INIT_SECTION_ASM_OP
2824 #undef HAS_INIT_SECTION
2825 #define HAS_INIT_SECTION
2826 #endif
2827
2828 #if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
2829 /* Run all the global destructors on exit from the program.  */
2830
2831 void
2832 __do_global_dtors ()
2833 {
2834 #ifdef DO_GLOBAL_DTORS_BODY
2835   DO_GLOBAL_DTORS_BODY;
2836 #else
2837   static func_ptr *p = __DTOR_LIST__ + 1;
2838   while (*p)
2839     {
2840       p++;
2841       (*(p-1)) ();
2842     }
2843 #endif
2844 }
2845 #endif
2846
2847 #ifndef HAS_INIT_SECTION
2848 /* Run all the global constructors on entry to the program.  */
2849
2850 #ifndef ON_EXIT
2851 #define ON_EXIT(a, b)
2852 #else
2853 /* Make sure the exit routine is pulled in to define the globals as
2854    bss symbols, just in case the linker does not automatically pull
2855    bss definitions from the library.  */
2856
2857 extern int _exit_dummy_decl;
2858 int *_exit_dummy_ref = &_exit_dummy_decl;
2859 #endif /* ON_EXIT */
2860
2861 void
2862 __do_global_ctors ()
2863 {
2864   DO_GLOBAL_CTORS_BODY;
2865   ON_EXIT (__do_global_dtors, 0);
2866 }
2867 #endif /* no HAS_INIT_SECTION */
2868
2869 #if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
2870 /* Subroutine called automatically by `main'.
2871    Compiling a global function named `main'
2872    produces an automatic call to this function at the beginning.
2873
2874    For many systems, this routine calls __do_global_ctors.
2875    For systems which support a .init section we use the .init section
2876    to run __do_global_ctors, so we need not do anything here.  */
2877
2878 void
2879 SYMBOL__MAIN ()
2880 {
2881   /* Support recursive calls to `main': run initializers just once.  */
2882   static int initialized;
2883   if (! initialized)
2884     {
2885       initialized = 1;
2886       __do_global_ctors ();
2887     }
2888 }
2889 #endif /* no HAS_INIT_SECTION or INVOKE__main */
2890
2891 #endif /* L__main */
2892 #endif /* __CYGWIN32__ */
2893 \f
2894 #ifdef L_ctors
2895
2896 #include "gbl-ctors.h"
2897
2898 /* Provide default definitions for the lists of constructors and
2899    destructors, so that we don't get linker errors.  These symbols are
2900    intentionally bss symbols, so that gld and/or collect will provide
2901    the right values.  */
2902
2903 /* We declare the lists here with two elements each,
2904    so that they are valid empty lists if no other definition is loaded.  */
2905 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
2906 #if defined(__NeXT__) || defined(_AIX)
2907 /* After 2.3, try this definition on all systems.  */
2908 func_ptr __CTOR_LIST__[2] = {0, 0};
2909 func_ptr __DTOR_LIST__[2] = {0, 0};
2910 #else
2911 func_ptr __CTOR_LIST__[2];
2912 func_ptr __DTOR_LIST__[2];
2913 #endif
2914 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
2915 #endif /* L_ctors */
2916 \f
2917 #ifdef L_exit
2918
2919 #include "gbl-ctors.h"
2920
2921 #ifdef NEED_ATEXIT
2922 # ifdef ON_EXIT
2923 #  undef ON_EXIT
2924 # endif
2925 int _exit_dummy_decl = 0;       /* prevent compiler & linker warnings */
2926 #endif
2927
2928 #ifndef ON_EXIT
2929
2930 #ifdef NEED_ATEXIT
2931 # include <errno.h>
2932
2933 static func_ptr *atexit_chain = 0;
2934 static long atexit_chain_length = 0;
2935 static volatile long last_atexit_chain_slot = -1;
2936
2937 int atexit (func_ptr func)
2938 {
2939   if (++last_atexit_chain_slot == atexit_chain_length)
2940     {
2941       atexit_chain_length += 32;
2942       if (atexit_chain)
2943         atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
2944                                              * sizeof (func_ptr));
2945       else
2946         atexit_chain = (func_ptr *) malloc (atexit_chain_length
2947                                             * sizeof (func_ptr));
2948       if (! atexit_chain)
2949         {
2950           atexit_chain_length = 0;
2951           last_atexit_chain_slot = -1;
2952           errno = ENOMEM;
2953           return (-1);
2954         }
2955     }
2956   atexit_chain[last_atexit_chain_slot] = func;
2957   return (0);
2958 }
2959 #endif /* NEED_ATEXIT */
2960
2961 /* If we have no known way of registering our own __do_global_dtors
2962    routine so that it will be invoked at program exit time, then we
2963    have to define our own exit routine which will get this to happen.  */
2964
2965 extern void __do_global_dtors ();
2966 extern void __bb_exit_func ();
2967 extern void _cleanup ();
2968 extern void _exit () __attribute__ ((noreturn));
2969
2970 void 
2971 exit (int status)
2972 {
2973 #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
2974 #ifdef NEED_ATEXIT
2975   if (atexit_chain)
2976     {
2977       for ( ; last_atexit_chain_slot-- >= 0; )
2978         {
2979           (*atexit_chain[last_atexit_chain_slot + 1]) ();
2980           atexit_chain[last_atexit_chain_slot + 1] = 0;
2981         }
2982       free (atexit_chain);
2983       atexit_chain = 0;
2984     }
2985 #else /* No NEED_ATEXIT */
2986   __do_global_dtors ();
2987 #endif /* No NEED_ATEXIT */
2988 #endif /* !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF) */
2989 /* In gbl-ctors.h, ON_EXIT is defined if HAVE_ATEXIT is defined.  In
2990    __bb_init_func and _bb_init_prg, __bb_exit_func is registered with
2991    ON_EXIT if ON_EXIT is defined.  Thus we must not call __bb_exit_func here
2992    if HAVE_ATEXIT is defined. */
2993 #ifndef HAVE_ATEXIT
2994 #ifndef inhibit_libc
2995   __bb_exit_func ();
2996 #endif
2997 #endif /* !HAVE_ATEXIT */
2998 #ifdef EXIT_BODY
2999   EXIT_BODY;
3000 #else
3001   _cleanup ();
3002 #endif
3003   _exit (status);
3004 }
3005
3006 #else
3007 int _exit_dummy_decl = 0;       /* prevent compiler & linker warnings */
3008 #endif
3009
3010 #endif /* L_exit */
3011 \f
3012 #ifdef L_eh
3013
3014 #include "gthr.h"
3015
3016 /* Shared exception handling support routines.  */
3017
3018 void
3019 __default_terminate ()
3020 {
3021   abort ();
3022 }
3023
3024 void (*__terminate_func)() = __default_terminate;
3025
3026 void
3027 __terminate ()
3028 {
3029   (*__terminate_func)();
3030 }
3031
3032 void *
3033 __throw_type_match (void *catch_type, void *throw_type, void *obj)
3034 {
3035 #if 0
3036  printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
3037          catch_type, throw_type);
3038 #endif
3039  if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
3040    return obj;
3041  return 0;
3042 }
3043
3044 void
3045 __empty ()
3046 {
3047 }
3048 \f
3049
3050 /* Include definitions of EH context and table layout */
3051
3052 #include "eh-common.h"
3053
3054 /* This is a safeguard for dynamic handler chain. */
3055
3056 static void *top_elt[2];
3057
3058 /* Allocate and return a new EH context structure. */
3059
3060 extern void __throw ();
3061
3062 static void *
3063 new_eh_context ()
3064 {
3065   struct eh_context *eh = (struct eh_context *) malloc (sizeof *eh);
3066   if (! eh)
3067     __terminate ();
3068
3069   memset (eh, 0, sizeof *eh);
3070
3071   eh->dynamic_handler_chain = top_elt;
3072
3073   return eh;
3074 }
3075
3076 #if __GTHREADS
3077 static __gthread_key_t eh_context_key;
3078
3079 /* Destructor for struct eh_context. */
3080 static void
3081 eh_context_free (void *ptr)
3082 {
3083   __gthread_key_dtor (eh_context_key, ptr);
3084   if (ptr)
3085     free (ptr);
3086 }
3087 #endif
3088
3089 /* Pointer to function to return EH context. */
3090
3091 static struct eh_context *eh_context_initialize ();
3092 static struct eh_context *eh_context_static ();
3093 #if __GTHREADS
3094 static struct eh_context *eh_context_specific ();
3095 #endif
3096
3097 static struct eh_context *(*get_eh_context) () = &eh_context_initialize;
3098
3099 /* Routine to get EH context.
3100    This one will simply call the function pointer. */
3101
3102 void *
3103 __get_eh_context ()
3104 {
3105   return (void *) (*get_eh_context) ();
3106 }
3107
3108 /* Get and set the language specific info pointer. */
3109
3110 void **
3111 __get_eh_info ()
3112 {
3113   struct eh_context *eh = (*get_eh_context) ();
3114   return &eh->info;
3115 }
3116 \f
3117 #if __GTHREADS
3118 static void
3119 eh_threads_initialize ()
3120 {
3121   /* Try to create the key.  If it fails, revert to static method,
3122      otherwise start using thread specific EH contexts. */
3123   if (__gthread_key_create (&eh_context_key, &eh_context_free) == 0)
3124     get_eh_context = &eh_context_specific;
3125   else
3126     get_eh_context = &eh_context_static;
3127 }
3128 #endif /* no __GTHREADS */
3129
3130 /* Initialize EH context.
3131    This will be called only once, since we change GET_EH_CONTEXT
3132    pointer to another routine. */
3133
3134 static struct eh_context *
3135 eh_context_initialize ()
3136 {
3137 #if __GTHREADS
3138
3139   static __gthread_once_t once = __GTHREAD_ONCE_INIT;
3140   /* Make sure that get_eh_context does not point to us anymore.
3141      Some systems have dummy thread routines in their libc that
3142      return a success (Solaris 2.6 for example). */
3143   if (__gthread_once (&once, eh_threads_initialize) != 0
3144       || get_eh_context == &eh_context_initialize)
3145     {
3146       /* Use static version of EH context. */
3147       get_eh_context = &eh_context_static;
3148     }
3149
3150 #else /* no __GTHREADS */
3151
3152   /* Use static version of EH context. */
3153   get_eh_context = &eh_context_static;
3154
3155 #endif /* no __GTHREADS */
3156
3157   return (*get_eh_context) ();
3158 }
3159
3160 /* Return a static EH context. */
3161
3162 static struct eh_context *
3163 eh_context_static ()
3164 {
3165   static struct eh_context *eh;
3166   if (! eh)
3167     eh = new_eh_context ();
3168   return eh;
3169 }
3170
3171 #if __GTHREADS
3172 /* Return a thread specific EH context. */
3173
3174 static struct eh_context *
3175 eh_context_specific ()
3176 {
3177   struct eh_context *eh;
3178   eh = (struct eh_context *) __gthread_getspecific (eh_context_key);
3179   if (! eh)
3180     {
3181       eh = new_eh_context ();
3182       if (__gthread_setspecific (eh_context_key, (void *) eh) != 0)
3183         __terminate ();
3184     }
3185
3186   return eh;
3187 }
3188 #endif __GTHREADS
3189 \f
3190 /* Support routines for setjmp/longjmp exception handling.  */
3191
3192 /* Calls to __sjthrow are generated by the compiler when an exception
3193    is raised when using the setjmp/longjmp exception handling codegen
3194    method.  */
3195
3196 #ifdef DONT_USE_BUILTIN_SETJMP
3197 extern void longjmp (void *, int);
3198 #endif
3199
3200 /* Routine to get the head of the current thread's dynamic handler chain
3201    use for exception handling. */
3202
3203 void ***
3204 __get_dynamic_handler_chain ()
3205 {
3206   struct eh_context *eh = (*get_eh_context) ();
3207   return &eh->dynamic_handler_chain;
3208 }
3209
3210 /* This is used to throw an exception when the setjmp/longjmp codegen
3211    method is used for exception handling.
3212
3213    We call __terminate if there are no handlers left.  Otherwise we run the
3214    cleanup actions off the dynamic cleanup stack, and pop the top of the
3215    dynamic handler chain, and use longjmp to transfer back to the associated
3216    handler.  */
3217
3218 void
3219 __sjthrow ()
3220 {
3221   struct eh_context *eh = (*get_eh_context) ();
3222   void ***dhc = &eh->dynamic_handler_chain;
3223   void *jmpbuf;
3224   void (*func)(void *, int);
3225   void *arg;
3226   void ***cleanup;
3227
3228   /* The cleanup chain is one word into the buffer.  Get the cleanup
3229      chain.  */
3230   cleanup = (void***)&(*dhc)[1];
3231
3232   /* If there are any cleanups in the chain, run them now.  */
3233   if (cleanup[0])
3234     {
3235       double store[200];
3236       void **buf = (void**)store;
3237       buf[1] = 0;
3238       buf[0] = (*dhc);
3239
3240       /* try { */
3241 #ifdef DONT_USE_BUILTIN_SETJMP
3242       if (! setjmp (&buf[2]))
3243 #else
3244       if (! __builtin_setjmp (&buf[2]))
3245 #endif
3246         {
3247           *dhc = buf;
3248           while (cleanup[0])
3249             {
3250               func = (void(*)(void*, int))cleanup[0][1];
3251               arg = (void*)cleanup[0][2];
3252
3253               /* Update this before running the cleanup.  */
3254               cleanup[0] = (void **)cleanup[0][0];
3255
3256               (*func)(arg, 2);
3257             }
3258           *dhc = buf[0];
3259         }
3260       /* catch (...) */
3261       else
3262         {
3263           __terminate ();
3264         }
3265     }
3266   
3267   /* We must call terminate if we try and rethrow an exception, when
3268      there is no exception currently active and when there are no
3269      handlers left.  */
3270   if (! eh->info || (*dhc) == top_elt)
3271     __terminate ();
3272     
3273   /* Find the jmpbuf associated with the top element of the dynamic
3274      handler chain.  The jumpbuf starts two words into the buffer.  */
3275   jmpbuf = &(*dhc)[2];
3276
3277   /* Then we pop the top element off the dynamic handler chain.  */
3278   *dhc = (void**)(*dhc)[0];
3279
3280   /* And then we jump to the handler.  */
3281
3282 #ifdef DONT_USE_BUILTIN_SETJMP
3283   longjmp (jmpbuf, 1);
3284 #else
3285   __builtin_longjmp (jmpbuf, 1);
3286 #endif
3287 }
3288
3289 /* Run cleanups on the dynamic cleanup stack for the current dynamic
3290    handler, then pop the handler off the dynamic handler stack, and
3291    then throw.  This is used to skip the first handler, and transfer
3292    control to the next handler in the dynamic handler stack.  */
3293
3294 void
3295 __sjpopnthrow ()
3296 {
3297   struct eh_context *eh = (*get_eh_context) ();
3298   void ***dhc = &eh->dynamic_handler_chain;
3299   void (*func)(void *, int);
3300   void *arg;
3301   void ***cleanup;
3302
3303   /* The cleanup chain is one word into the buffer.  Get the cleanup
3304      chain.  */
3305   cleanup = (void***)&(*dhc)[1];
3306
3307   /* If there are any cleanups in the chain, run them now.  */
3308   if (cleanup[0])
3309     {
3310       double store[200];
3311       void **buf = (void**)store;
3312       buf[1] = 0;
3313       buf[0] = (*dhc);
3314
3315       /* try { */
3316 #ifdef DONT_USE_BUILTIN_SETJMP
3317       if (! setjmp (&buf[2]))
3318 #else
3319       if (! __builtin_setjmp (&buf[2]))
3320 #endif
3321         {
3322           *dhc = buf;
3323           while (cleanup[0])
3324             {
3325               func = (void(*)(void*, int))cleanup[0][1];
3326               arg = (void*)cleanup[0][2];
3327
3328               /* Update this before running the cleanup.  */
3329               cleanup[0] = (void **)cleanup[0][0];
3330
3331               (*func)(arg, 2);
3332             }
3333           *dhc = buf[0];
3334         }
3335       /* catch (...) */
3336       else
3337         {
3338           __terminate ();
3339         }
3340     }
3341
3342   /* Then we pop the top element off the dynamic handler chain.  */
3343   *dhc = (void**)(*dhc)[0];
3344
3345   __sjthrow ();
3346 }
3347 \f
3348 /* Support code for all exception region-based exception handling.  */
3349
3350 /* This value identifies the place from which an exception is being
3351    thrown.  */
3352
3353 #ifdef EH_TABLE_LOOKUP
3354
3355 EH_TABLE_LOOKUP
3356
3357 #else
3358
3359 #ifdef DWARF2_UNWIND_INFO
3360
3361
3362 /* Return the table version of an exception descriptor */
3363
3364 short 
3365 __get_eh_table_version (exception_descriptor *table) 
3366 {
3367   return table->lang.version;
3368 }
3369
3370 /* Return the originating table language of an exception descriptor */
3371
3372 short 
3373 __get_eh_table_language (exception_descriptor *table)
3374 {
3375   return table->lang.language;
3376 }
3377
3378 /* This routine takes a PC and a pointer to the exception region TABLE for
3379    its translation unit, and returns the address of the exception handler
3380    associated with the closest exception table handler entry associated
3381    with that PC, or 0 if there are no table entries the PC fits in.
3382
3383    In the advent of a tie, we have to give the last entry, as it represents
3384    an inner block.  */
3385
3386 static void *
3387 old_find_exception_handler (void *pc, old_exception_table *table)
3388 {
3389   if (table)
3390     {
3391       int pos;
3392       int best = -1;
3393
3394       /* We can't do a binary search because the table isn't guaranteed
3395          to be sorted from function to function.  */
3396       for (pos = 0; table[pos].start_region != (void *) -1; ++pos)
3397         {
3398           if (table[pos].start_region <= pc && table[pos].end_region > pc)
3399             {
3400               /* This can apply.  Make sure it is at least as small as
3401                  the previous best.  */
3402               if (best == -1 || (table[pos].end_region <= table[best].end_region
3403                         && table[pos].start_region >= table[best].start_region))
3404                 best = pos;
3405             }
3406           /* But it is sorted by starting PC within a function.  */
3407           else if (best >= 0 && table[pos].start_region > pc)
3408             break;
3409         }
3410       if (best != -1)
3411         return table[best].exception_handler;
3412     }
3413
3414   return (void *) 0;
3415 }
3416
3417 static void *
3418 find_exception_handler (void *pc, exception_descriptor *table, void *eh_info)
3419 {
3420   if (table)
3421     {
3422       /* The new model assumed the table is sorted inner-most out so the
3423          first region we find which matches is the correct one */
3424
3425       int pos;
3426       void *ret;
3427       exception_table *tab = &(table->table[0]);
3428
3429       /* Subtract 1 from the PC to avoid hitting the next region */
3430       pc--;
3431       
3432       /* We can't do a binary search because the table is in inner-most
3433          to outermost address ranges within functions */
3434       for (pos = 0; tab[pos].start_region != (void *) -1; pos++)
3435         { 
3436           if (tab[pos].start_region <= pc && tab[pos].end_region > pc)
3437             {
3438               if (tab[pos].match_info)
3439                 {
3440                   __eh_matcher matcher = ((__eh_info *)eh_info)->match_function;
3441                   /* match info but no matcher is NOT a match */
3442                   if (matcher) 
3443                     {
3444                       ret = (*matcher)(eh_info, tab[pos].match_info, table);
3445                       if (ret)
3446                         return tab[pos].exception_handler;
3447                     }
3448                 }
3449               else
3450                 return tab[pos].exception_handler;
3451             }
3452         }
3453     }
3454
3455   return (void *) 0;
3456 }
3457 #endif /* DWARF2_UNWIND_INFO */
3458 #endif /* EH_TABLE_LOOKUP */
3459 \f
3460 #ifdef DWARF2_UNWIND_INFO
3461 /* Support code for exception handling using static unwind information.  */
3462
3463 #include "frame.h"
3464
3465 /* This type is used in get_reg and put_reg to deal with ABIs where a void*
3466    is smaller than a word, such as the Irix 6 n32 ABI.  We cast twice to
3467    avoid a warning about casting between int and pointer of different
3468    sizes.  */
3469
3470 typedef int ptr_type __attribute__ ((mode (pointer)));
3471
3472 /* Get the value of register REG as saved in UDATA, where SUB_UDATA is a
3473    frame called by UDATA or 0.  */
3474
3475 static void*
3476 get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata)
3477 {
3478   if (udata->saved[reg] == REG_SAVED_OFFSET)
3479     return (void *)(ptr_type)
3480       *(word_type *)(udata->cfa + udata->reg_or_offset[reg]);
3481   else if (udata->saved[reg] == REG_SAVED_REG && sub_udata)
3482     return get_reg (udata->reg_or_offset[reg], sub_udata, 0);
3483   else
3484     abort ();
3485 }
3486
3487 /* Overwrite the saved value for register REG in frame UDATA with VAL.  */
3488
3489 static void
3490 put_reg (unsigned reg, void *val, frame_state *udata)
3491 {
3492   if (udata->saved[reg] == REG_SAVED_OFFSET)
3493     *(word_type *)(udata->cfa + udata->reg_or_offset[reg])
3494       = (word_type)(ptr_type) val;
3495   else
3496     abort ();
3497 }
3498
3499 /* Copy the saved value for register REG from frame UDATA to frame
3500    TARGET_UDATA.  Unlike the previous two functions, this can handle
3501    registers that are not one word large.  */
3502
3503 static void
3504 copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata)
3505 {
3506   if (udata->saved[reg] == REG_SAVED_OFFSET
3507       && target_udata->saved[reg] == REG_SAVED_OFFSET)
3508     memcpy (target_udata->cfa + target_udata->reg_or_offset[reg],
3509             udata->cfa + udata->reg_or_offset[reg],
3510             __builtin_dwarf_reg_size (reg));
3511   else
3512     abort ();
3513 }
3514
3515 /* Retrieve the return address for frame UDATA, where SUB_UDATA is a
3516    frame called by UDATA or 0.  */
3517
3518 static inline void *
3519 get_return_addr (frame_state *udata, frame_state *sub_udata)
3520 {
3521   return __builtin_extract_return_addr
3522     (get_reg (udata->retaddr_column, udata, sub_udata));
3523 }
3524
3525 /* Overwrite the return address for frame UDATA with VAL.  */
3526
3527 static inline void
3528 put_return_addr (void *val, frame_state *udata)
3529 {
3530   val = __builtin_frob_return_addr (val);
3531   put_reg (udata->retaddr_column, val, udata);
3532 }
3533
3534 /* Given the current frame UDATA and its return address PC, return the
3535    information about the calling frame in CALLER_UDATA.  */
3536
3537 static void *
3538 next_stack_level (void *pc, frame_state *udata, frame_state *caller_udata)
3539 {
3540   caller_udata = __frame_state_for (pc, caller_udata);
3541   if (! caller_udata)
3542     return 0;
3543
3544   /* Now go back to our caller's stack frame.  If our caller's CFA register
3545      was saved in our stack frame, restore it; otherwise, assume the CFA
3546      register is SP and restore it to our CFA value.  */
3547   if (udata->saved[caller_udata->cfa_reg])
3548     caller_udata->cfa = get_reg (caller_udata->cfa_reg, udata, 0);
3549   else
3550     caller_udata->cfa = udata->cfa;
3551   caller_udata->cfa += caller_udata->cfa_offset;
3552
3553   return caller_udata;
3554 }
3555
3556 #ifdef INCOMING_REGNO
3557 /* Is the saved value for register REG in frame UDATA stored in a register
3558    window in the previous frame?  */
3559
3560 static int
3561 in_reg_window (int reg, frame_state *udata)
3562 {
3563   if (udata->saved[reg] != REG_SAVED_OFFSET)
3564     return 0;
3565
3566 #ifdef STACK_GROWS_DOWNWARD
3567   return udata->reg_or_offset[reg] > 0;
3568 #else
3569   return udata->reg_or_offset[reg] < 0;
3570 #endif
3571 }
3572 #endif /* INCOMING_REGNO */
3573
3574 /* We first search for an exception handler, and if we don't find
3575    it, we call __terminate on the current stack frame so that we may
3576    use the debugger to walk the stack and understand why no handler
3577    was found.
3578
3579    If we find one, then we unwind the frames down to the one that
3580    has the handler and transfer control into the handler.  */
3581
3582 void
3583 __throw ()
3584 {
3585   struct eh_context *eh = (*get_eh_context) ();
3586   void *saved_pc, *pc, *handler, *retaddr;
3587   frame_state ustruct, ustruct2;
3588   frame_state *udata = &ustruct;
3589   frame_state *sub_udata = &ustruct2;
3590   frame_state my_ustruct, *my_udata = &my_ustruct;
3591   long args_size;
3592   int new_exception_model;
3593
3594   /* This is required for C++ semantics.  We must call terminate if we
3595      try and rethrow an exception, when there is no exception currently
3596      active.  */
3597   if (! eh->info)
3598     __terminate ();
3599     
3600   /* Start at our stack frame.  */
3601 label:
3602   udata = __frame_state_for (&&label, udata);
3603   if (! udata)
3604     __terminate ();
3605
3606   /* We need to get the value from the CFA register.  At this point in
3607      compiling __throw we don't know whether or not we will use the frame
3608      pointer register for the CFA, so we check our unwind info.  */
3609   if (udata->cfa_reg == __builtin_dwarf_fp_regnum ())
3610     udata->cfa = __builtin_fp ();
3611   else
3612     udata->cfa = __builtin_sp ();
3613   udata->cfa += udata->cfa_offset;
3614
3615   memcpy (my_udata, udata, sizeof (*udata));
3616
3617   /* Do any necessary initialization to access arbitrary stack frames.
3618      On the SPARC, this means flushing the register windows.  */
3619   __builtin_unwind_init ();
3620
3621   /* Now reset pc to the right throw point.  */
3622   pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
3623   saved_pc = pc;
3624
3625   handler = 0;
3626   for (;;)
3627     { 
3628       frame_state *p = udata;
3629       udata = next_stack_level (pc, udata, sub_udata);
3630       sub_udata = p;
3631
3632       /* If we couldn't find the next frame, we lose.  */
3633       if (! udata)
3634         break;
3635
3636       if (udata->eh_ptr == NULL)
3637         new_exception_model = 0;
3638       else
3639         new_exception_model = (((exception_descriptor *)(udata->eh_ptr))->
3640                                           runtime_id_field == NEW_EH_RUNTIME);
3641
3642       if (new_exception_model)
3643         handler = find_exception_handler (pc, udata->eh_ptr, eh->info);
3644       else
3645         handler = old_find_exception_handler (pc, udata->eh_ptr);
3646
3647       /* If we found one, we can stop searching.  */
3648       if (handler)
3649         {
3650           args_size = udata->args_size;
3651           break;
3652         }
3653
3654       /* Otherwise, we continue searching.  We subtract 1 from PC to avoid
3655          hitting the beginning of the next region.  */
3656       pc = get_return_addr (udata, sub_udata) - 1;
3657     }
3658
3659   /* If we haven't found a handler by now, this is an unhandled
3660      exception.  */
3661   if (! handler)
3662     __terminate ();
3663
3664   eh->handler_label = handler;
3665
3666   if (pc == saved_pc)
3667     /* We found a handler in the throw context, no need to unwind.  */
3668     udata = my_udata;
3669   else
3670     {
3671       int i;
3672
3673       /* Unwind all the frames between this one and the handler by copying
3674          their saved register values into our register save slots.  */
3675
3676       /* Remember the PC where we found the handler.  */
3677       void *handler_pc = pc;
3678
3679       /* Start from the throw context again.  */
3680       pc = saved_pc;
3681       memcpy (udata, my_udata, sizeof (*udata));
3682
3683       while (pc != handler_pc)
3684         {
3685           frame_state *p = udata;
3686           udata = next_stack_level (pc, udata, sub_udata);
3687           sub_udata = p;
3688
3689           for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
3690             if (i != udata->retaddr_column && udata->saved[i])
3691               {
3692 #ifdef INCOMING_REGNO
3693                 /* If you modify the saved value of the return address
3694                    register on the SPARC, you modify the return address for
3695                    your caller's frame.  Don't do that here, as it will
3696                    confuse get_return_addr.  */
3697                 if (in_reg_window (i, udata)
3698                     && udata->saved[udata->retaddr_column] == REG_SAVED_REG
3699                     && udata->reg_or_offset[udata->retaddr_column] == i)
3700                   continue;
3701 #endif
3702                 copy_reg (i, udata, my_udata);
3703               }
3704
3705           pc = get_return_addr (udata, sub_udata) - 1;
3706         }
3707
3708 #ifdef INCOMING_REGNO
3709       /* But we do need to update the saved return address register from
3710          the last frame we unwind, or the handler frame will have the wrong
3711          return address.  */
3712       if (udata->saved[udata->retaddr_column] == REG_SAVED_REG)
3713         {
3714           i = udata->reg_or_offset[udata->retaddr_column];
3715           if (in_reg_window (i, udata))
3716             copy_reg (i, udata, my_udata);
3717         }
3718 #endif
3719     }
3720   /* udata now refers to the frame called by the handler frame.  */
3721
3722   /* Emit the stub to adjust sp and jump to the handler.  */
3723   if (new_exception_model)
3724     retaddr = __builtin_eh_stub ();
3725   else
3726     retaddr =  __builtin_eh_stub_old ();
3727
3728   /* And then set our return address to point to the stub.  */
3729   if (my_udata->saved[my_udata->retaddr_column] == REG_SAVED_OFFSET)
3730     put_return_addr (retaddr, my_udata);
3731   else
3732     __builtin_set_return_addr_reg (retaddr);
3733
3734   /* Set up the registers we use to communicate with the stub.
3735      We check STACK_GROWS_DOWNWARD so the stub can use adjust_stack.  */
3736
3737   if (new_exception_model)
3738     __builtin_set_eh_regs ((void *)eh,
3739 #ifdef STACK_GROWS_DOWNWARD
3740                          udata->cfa - my_udata->cfa
3741 #else
3742                          my_udata->cfa - udata->cfa
3743 #endif
3744                          + args_size);
3745   else
3746     __builtin_set_eh_regs (handler,
3747
3748 #ifdef STACK_GROWS_DOWNWARD
3749                          udata->cfa - my_udata->cfa
3750 #else
3751                          my_udata->cfa - udata->cfa
3752 #endif
3753                          + args_size);
3754
3755   /* Epilogue:  restore the handler frame's register values and return
3756      to the stub.  */
3757 }
3758 #endif /* DWARF2_UNWIND_INFO */
3759
3760 #endif /* L_eh */
3761 \f
3762 #ifdef L_pure
3763 #ifndef inhibit_libc
3764 /* This gets us __GNU_LIBRARY__.  */
3765 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
3766 #include <stdio.h>
3767
3768 #ifdef __GNU_LIBRARY__
3769   /* Avoid forcing the library's meaning of `write' on the user program
3770      by using the "internal" name (for use within the library)  */
3771 #define write(fd, buf, n)       __write((fd), (buf), (n))
3772 #endif
3773 #endif /* inhibit_libc */
3774
3775 #define MESSAGE "pure virtual method called\n"
3776
3777 void
3778 __pure_virtual ()
3779 {
3780 #ifndef inhibit_libc
3781   write (2, MESSAGE, sizeof (MESSAGE) - 1);
3782 #endif
3783   _exit (-1);
3784 }
3785 #endif