OSDN Git Service

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