OSDN Git Service

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