OSDN Git Service

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