OSDN Git Service

(output_line_directive): Do not output negative line numbers when
[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
1442 static struct bb *bb_head;
1443
1444 /* Return the number of digits needed to print a value */
1445 /* __inline__ */ static int num_digits (long value, int base)
1446 {
1447   int minus = (value < 0 && base != 16);
1448   unsigned long v = (minus) ? -value : value;
1449   int ret = minus;
1450
1451   do
1452     {
1453       v /= base;
1454       ret++;
1455     }
1456   while (v);
1457
1458   return ret;
1459 }
1460
1461 void
1462 __bb_exit_func (void)
1463 {
1464   FILE *file = fopen ("bb.out", "a");
1465   long time_value;
1466
1467   if (!file)
1468     perror ("bb.out");
1469
1470   else
1471     {
1472       struct bb *ptr;
1473
1474       /* This is somewhat type incorrect, but it avoids worrying about
1475          exactly where time.h is included from.  It should be ok unless
1476          a void * differs from other pointer formats, or if sizeof (long)
1477          is < sizeof (time_t).  It would be nice if we could assume the
1478          use of rationale standards here.  */
1479
1480       time ((void *) &time_value);
1481       fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1482
1483       /* We check the length field explicitly in order to allow compatibility
1484          with older GCC's which did not provide it.  */
1485
1486       for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1487         {
1488           int i;
1489           int func_p    = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
1490           int line_p    = (func_p && ptr->line_nums);
1491           int file_p    = (func_p && ptr->filenames);
1492           long ncounts  = ptr->ncounts;
1493           long cnt_max  = 0;
1494           long line_max = 0;
1495           long addr_max = 0;
1496           int file_len  = 0;
1497           int func_len  = 0;
1498           int blk_len   = num_digits (ncounts, 10);
1499           int cnt_len;
1500           int line_len;
1501           int addr_len;
1502
1503           fprintf (file, "File %s, %ld basic blocks \n\n",
1504                    ptr->filename, ncounts);
1505
1506           /* Get max values for each field.  */
1507           for (i = 0; i < ncounts; i++)
1508             {
1509               const char *p;
1510               int len;
1511
1512               if (cnt_max < ptr->counts[i])
1513                 cnt_max = ptr->counts[i];
1514
1515               if (addr_max < ptr->addresses[i])
1516                 addr_max = ptr->addresses[i];
1517
1518               if (line_p && line_max < ptr->line_nums[i])
1519                 line_max = ptr->line_nums[i];
1520
1521               if (func_p)
1522                 {
1523                   p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1524                   len = strlen (p);
1525                   if (func_len < len)
1526                     func_len = len;
1527                 }
1528
1529               if (file_p)
1530                 {
1531                   p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1532                   len = strlen (p);
1533                   if (file_len < len)
1534                     file_len = len;
1535                 }
1536             }
1537
1538           addr_len = num_digits (addr_max, 16);
1539           cnt_len  = num_digits (cnt_max, 10);
1540           line_len = num_digits (line_max, 10);
1541
1542           /* Now print out the basic block information.  */
1543           for (i = 0; i < ncounts; i++)
1544             {
1545               fprintf (file,
1546                        "    Block #%*d: executed %*ld time(s) address= 0x%.*lx",
1547                        blk_len, i+1,
1548                        cnt_len, ptr->counts[i],
1549                        addr_len, ptr->addresses[i]);
1550
1551               if (func_p)
1552                 fprintf (file, " function= %-*s", func_len,
1553                          (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1554
1555               if (line_p)
1556                 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
1557
1558               if (file_p)
1559                 fprintf (file, " file= %s",
1560                          (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1561
1562               fprintf (file, "\n");
1563             }
1564
1565           fprintf (file, "\n");
1566           fflush (file);
1567         }
1568
1569       fprintf (file, "\n\n");
1570       fclose (file);
1571     }
1572 }
1573
1574 void
1575 __bb_init_func (struct bb *blocks)
1576 {
1577   /* User is supposed to check whether the first word is non-0,
1578      but just in case....  */
1579
1580   if (blocks->zero_word)
1581     return;
1582
1583 #ifdef ON_EXIT
1584   /* Initialize destructor.  */
1585   if (!bb_head)
1586     ON_EXIT (__bb_exit_func, 0);
1587 #endif
1588
1589   /* Set up linked list.  */
1590   blocks->zero_word = 1;
1591   blocks->next = bb_head;
1592   bb_head = blocks;
1593 }
1594
1595 #ifndef MACHINE_STATE_SAVE
1596 #define MACHINE_STATE_SAVE(ID)
1597 #endif
1598 #ifndef MACHINE_STATE_RESTORE
1599 #define MACHINE_STATE_RESTORE(ID)
1600 #endif
1601
1602 #include <string.h>
1603
1604 /* Number of buckets in hashtable of basic block addresses.  */
1605
1606 #define BB_BUCKETS 311
1607
1608 /* Maximum length of string in file bb.in.  */
1609
1610 #define BBINBUFSIZE 500
1611
1612 /* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
1613    "BBINBUFSIZE" but want to avoid trouble with preprocessors.  */
1614
1615 #define BBINBUFSIZESTR "499"
1616
1617 struct bb_edge
1618 {
1619   struct bb_edge *next;
1620   unsigned long src_addr;
1621   unsigned long dst_addr;
1622   unsigned long count;
1623 };
1624
1625 enum bb_func_mode
1626 {
1627   TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1628 };
1629
1630 struct bb_func
1631 {
1632   struct bb_func *next;
1633   char *funcname;
1634   char *filename;
1635   enum bb_func_mode mode;
1636 };
1637
1638 /* This is the connection to the outside world.
1639    The BLOCK_PROFILER macro must set __bb.blocks
1640    and __bb.blockno.  */
1641
1642 struct {
1643   unsigned long blockno;
1644   struct bb *blocks;
1645 } __bb;
1646
1647 /* Vars to store addrs of source and destination basic blocks 
1648    of a jump.  */
1649
1650 static unsigned long bb_src = 0;
1651 static unsigned long bb_dst = 0;
1652
1653 static FILE *bb_tracefile = (FILE *) 0;
1654 static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
1655 static struct bb_func *bb_func_head = (struct bb_func *) 0;
1656 static unsigned long bb_callcount = 0;
1657 static int bb_mode = 0;
1658
1659 static unsigned long *bb_stack = (unsigned long *) 0;
1660 static size_t bb_stacksize = 0;
1661
1662 static int reported = 0;
1663
1664 /* Trace modes:
1665 Always             :   Print execution frequencies of basic blocks
1666                        to file bb.out.
1667 bb_mode & 1 != 0   :   Dump trace of basic blocks to file bbtrace[.gz]
1668 bb_mode & 2 != 0   :   Print jump frequencies to file bb.out.
1669 bb_mode & 4 != 0   :   Cut call instructions from basic block flow.
1670 bb_mode & 8 != 0   :   Insert return instructions in basic block flow.
1671 */
1672
1673 #ifdef HAVE_POPEN
1674
1675 /*#include <sys/types.h>*/
1676 #include <sys/stat.h>
1677 /*#include <malloc.h>*/
1678
1679 /* Commands executed by gopen.  */
1680
1681 #define GOPENDECOMPRESS "gzip -cd "
1682 #define GOPENCOMPRESS "gzip -c >"
1683
1684 /* Like fopen but pipes through gzip.  mode may only be "r" or "w".
1685    If it does not compile, simply replace gopen by fopen and delete
1686    '.gz' from any first parameter to gopen.  */
1687
1688 static FILE *
1689 gopen (char *fn, char *mode)
1690 {
1691   int use_gzip;
1692   char *p;
1693
1694   if (mode[1])
1695     return (FILE *) 0;
1696
1697   if (mode[0] != 'r' && mode[0] != 'w') 
1698     return (FILE *) 0;
1699
1700   p = fn + strlen (fn)-1;
1701   use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z')) ||
1702               (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
1703
1704   if (use_gzip)
1705     {
1706       if (mode[0]=='r')
1707         {
1708           FILE *f;
1709           char *s = (char *) malloc (sizeof (char) * strlen (fn)
1710                                      + sizeof (GOPENDECOMPRESS));
1711           strcpy (s, GOPENDECOMPRESS);
1712           strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1713           f = popen (s, mode);
1714           free (s);
1715           return f;
1716         }
1717
1718       else
1719         {
1720           FILE *f;
1721           char *s = (char *) malloc (sizeof (char) * strlen (fn)
1722                                      + sizeof (GOPENCOMPRESS));
1723           strcpy (s, GOPENCOMPRESS);
1724           strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1725           if (!(f = popen (s, mode)))
1726             f = fopen (s, mode);
1727           free (s);
1728           return f;
1729         }
1730     }
1731
1732   else
1733     return fopen (fn, mode);
1734 }
1735
1736 static int
1737 gclose (FILE *f)
1738 {
1739   struct stat buf;
1740
1741   if (f != NULL)
1742     {
1743       if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1744         return pclose (f);
1745
1746       return fclose (f);
1747     }
1748   return 0;
1749 }
1750
1751 #endif /* HAVE_POPEN */
1752
1753 /* Called once per program.  */
1754
1755 static void
1756 __bb_exit_trace_func ()
1757 {
1758   FILE *file = fopen ("bb.out", "a");
1759   struct bb_func *f;
1760   struct bb_edge *e;
1761   struct bb *b;
1762         
1763   if (!file)
1764     perror ("bb.out");
1765
1766   if (bb_mode & 1)
1767     {
1768       if (!bb_tracefile)
1769         perror ("bbtrace");
1770       else
1771 #ifdef HAVE_POPEN
1772         gclose (bb_tracefile);
1773 #else
1774         fclose (bb_tracefile);
1775 #endif /* HAVE_POPEN */
1776     }
1777
1778   /* Check functions in `bb.in'.  */
1779
1780   if (file)
1781     {
1782       long time_value;
1783       const struct bb_func *p;
1784       int printed_something = 0;
1785       struct bb *ptr;
1786       long blk;
1787
1788       /* This is somewhat type incorrect.  */
1789       time ((void *) &time_value);
1790
1791       for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
1792         {
1793           for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1794             {
1795               if (!ptr->filename || p->filename != (char *) 0 && strcmp (p->filename, ptr->filename))
1796                 continue;
1797               for (blk = 0; blk < ptr->ncounts; blk++)
1798                 {
1799                   if (!strcmp (p->funcname, ptr->functions[blk]))
1800                     goto found;
1801                 }
1802             }
1803   
1804           if (!printed_something)
1805             {
1806               fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
1807               printed_something = 1;
1808             }
1809
1810           fprintf (file, "\tFunction %s", p->funcname);
1811           if (p->filename)
1812               fprintf (file, " of file %s", p->filename);
1813           fprintf (file, "\n" );
1814   
1815 found:        ;
1816         }
1817
1818       if (printed_something)
1819        fprintf (file, "\n");
1820
1821     }
1822
1823   if (bb_mode & 2)
1824     {
1825       if (!bb_hashbuckets)
1826         {
1827           if (!reported)
1828             {
1829               fprintf (stderr, "Profiler: out of memory\n");
1830               reported = 1;
1831             }
1832           return;
1833         }
1834     
1835       else if (file)
1836         {
1837           long time_value;
1838           int i;
1839           unsigned long addr_max = 0;
1840           unsigned long cnt_max  = 0;
1841           int cnt_len;
1842           int addr_len;
1843     
1844           /* This is somewhat type incorrect, but it avoids worrying about
1845              exactly where time.h is included from.  It should be ok unless
1846              a void * differs from other pointer formats, or if sizeof (long)
1847              is < sizeof (time_t).  It would be nice if we could assume the
1848              use of rationale standards here.  */
1849     
1850           time ((void *) &time_value);
1851           fprintf (file, "Basic block jump tracing");
1852
1853           switch (bb_mode & 12)
1854             {
1855               case 0:
1856                 fprintf (file, " (with call)");
1857               break;
1858
1859               case 4:
1860                 /* Print nothing.  */
1861               break;
1862
1863               case 8:
1864                 fprintf (file, " (with call & ret)");
1865               break;
1866
1867               case 12:
1868                 fprintf (file, " (with ret)");
1869               break;
1870             }
1871
1872           fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
1873     
1874           for (i = 0; i < BB_BUCKETS; i++)
1875             {
1876                struct bb_edge *bucket = bb_hashbuckets[i];
1877                for ( ; bucket; bucket = bucket->next )
1878                  {
1879                    if (addr_max < bucket->src_addr) 
1880                      addr_max = bucket->src_addr;
1881                    if (addr_max < bucket->dst_addr) 
1882                      addr_max = bucket->dst_addr;
1883                    if (cnt_max < bucket->count) 
1884                      cnt_max = bucket->count;
1885                  }
1886             }
1887           addr_len = num_digits (addr_max, 16);
1888           cnt_len  = num_digits (cnt_max, 10);
1889     
1890           for ( i = 0; i < BB_BUCKETS; i++)
1891             {
1892                struct bb_edge *bucket = bb_hashbuckets[i];
1893                for ( ; bucket; bucket = bucket->next )
1894                  {
1895                    fprintf (file, "Jump from block 0x%.*lx to "
1896                                   "block 0x%.*lx executed %*d time(s)\n", 
1897                             addr_len, bucket->src_addr, 
1898                             addr_len, bucket->dst_addr, 
1899                             cnt_len, bucket->count);
1900                  }
1901             }
1902   
1903           fprintf (file, "\n");
1904
1905         }
1906     }
1907
1908    if (file)
1909      fclose (file);
1910
1911    /* Free allocated memory.  */
1912
1913    f = bb_func_head;
1914    while (f)
1915      {
1916        struct bb_func *old = f;
1917
1918        f = f->next;
1919        if (old->funcname) free (old->funcname);
1920        if (old->filename) free (old->filename);
1921        free (old);
1922      }
1923
1924    if (bb_stack)
1925      free (bb_stack);
1926
1927    if (bb_hashbuckets)
1928      {
1929        int i;
1930
1931        for (i = 0; i < BB_BUCKETS; i++)
1932          {
1933            struct bb_edge *old, *bucket = bb_hashbuckets[i];
1934
1935            while (bucket)
1936              {
1937                old = bucket;
1938                bucket = bucket->next;
1939                free (old);
1940              }
1941          }
1942        free (bb_hashbuckets);
1943      }
1944
1945    for (b = bb_head; b; b = b->next)
1946      if (b->flags) free (b->flags);
1947 }
1948
1949 /* Called once per program.  */
1950
1951 static void
1952 __bb_init_prg ()
1953 {
1954
1955   FILE *file;
1956   char buf[BBINBUFSIZE];
1957   const char *p;
1958   const char *pos;
1959   enum bb_func_mode m;
1960
1961 #ifdef ON_EXIT
1962   /* Initialize destructor.  */
1963   ON_EXIT (__bb_exit_func, 0);
1964 #endif
1965
1966   if (!(file = fopen ("bb.in", "r")))
1967     return;
1968
1969   while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
1970     {
1971       p = buf;
1972       if (*p == '-') 
1973         { 
1974           m = TRACE_OFF; 
1975           p++; 
1976         }
1977       else 
1978         { 
1979           m = TRACE_ON; 
1980         }
1981       if (!strcmp (p, "__bb_trace__"))
1982         bb_mode |= 1;
1983       else if (!strcmp (p, "__bb_jumps__"))
1984         bb_mode |= 2;
1985       else if (!strcmp (p, "__bb_hidecall__"))
1986         bb_mode |= 4;
1987       else if (!strcmp (p, "__bb_showret__"))
1988         bb_mode |= 8;
1989       else 
1990         {
1991           struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
1992           if (f)
1993             {
1994               unsigned long l;
1995               f->next = bb_func_head;
1996               if (pos = strchr (p, ':'))
1997                 {
1998                   if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
1999                     continue;
2000                   strcpy (f->funcname, pos+1);
2001                   l = pos-p;
2002                   if ((f->filename = (char *) malloc (l+1)))
2003                     {
2004                       strncpy (f->filename, p, l);
2005                       f->filename[l] = '\0';
2006                     }
2007                   else
2008                     f->filename = (char *) 0;
2009                 }
2010               else
2011                 {
2012                   if (!(f->funcname = (char *) malloc (strlen (p)+1)))
2013                     continue;
2014                   strcpy (f->funcname, p);
2015                   f->filename = (char *) 0;
2016                 }
2017               f->mode = m;
2018               bb_func_head = f;
2019             }
2020          }
2021     }
2022   fclose (file);
2023
2024 #ifdef HAVE_POPEN 
2025
2026   if (bb_mode & 1)
2027       bb_tracefile = gopen ("bbtrace.gz", "w");
2028
2029 #else
2030
2031   if (bb_mode & 1)
2032       bb_tracefile = fopen ("bbtrace", "w");
2033
2034 #endif /* HAVE_POPEN */
2035
2036   if (bb_mode & 2)
2037     {
2038       bb_hashbuckets = (struct bb_edge **) 
2039                    malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2040       if (bb_hashbuckets)
2041         bzero ((char *) bb_hashbuckets, BB_BUCKETS);
2042     }
2043
2044   if (bb_mode & 12)
2045     {
2046       bb_stacksize = 10;
2047       bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2048     }
2049
2050 #ifdef ON_EXIT
2051       /* Initialize destructor.  */
2052       ON_EXIT (__bb_exit_trace_func, 0);
2053 #endif
2054
2055 }
2056
2057 /* Called upon entering a basic block.  */
2058
2059 void
2060 __bb_trace_func ()
2061 {
2062   struct bb_edge *bucket;
2063
2064   MACHINE_STATE_SAVE("1")
2065
2066   if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2067     goto skip;
2068
2069   bb_dst = __bb.blocks->addresses[__bb.blockno];
2070   __bb.blocks->counts[__bb.blockno]++;
2071
2072   if (bb_tracefile)
2073     {
2074       fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2075     }
2076
2077   if (bb_hashbuckets)
2078     {
2079       struct bb_edge **startbucket, **oldnext;
2080
2081       oldnext = startbucket =
2082           & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
2083       bucket = *startbucket;
2084
2085       for (bucket = *startbucket; bucket; 
2086            oldnext = &(bucket->next), bucket = *oldnext)
2087         {
2088           if ( bucket->src_addr == bb_src &&
2089                bucket->dst_addr == bb_dst )
2090             {
2091               bucket->count++;
2092               *oldnext = bucket->next;
2093               bucket->next = *startbucket;
2094               *startbucket = bucket;
2095               goto ret;
2096             }
2097         }
2098
2099       bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2100
2101       if (!bucket)
2102         {
2103           if (!reported)
2104             {
2105               fprintf (stderr, "Profiler: out of memory\n");
2106               reported = 1;
2107             }
2108         }
2109
2110       else
2111         {
2112           bucket->src_addr = bb_src;
2113           bucket->dst_addr = bb_dst;
2114           bucket->next = *startbucket;
2115           *startbucket = bucket;
2116           bucket->count = 1;
2117         }
2118     }
2119
2120 ret:
2121   bb_src = bb_dst;
2122
2123 skip:
2124   ;
2125
2126   MACHINE_STATE_RESTORE("1")
2127
2128 }
2129
2130 /* Called when returning from a function and `__bb_showret__' is set.  */
2131
2132 static void
2133 __bb_trace_func_ret ()
2134 {
2135   struct bb_edge *bucket;
2136
2137   if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2138     goto skip;
2139
2140   if (bb_hashbuckets)
2141     {
2142       struct bb_edge **startbucket, **oldnext;
2143
2144       oldnext = startbucket =
2145           & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
2146       bucket = *startbucket;
2147
2148       for (bucket = *startbucket; bucket; 
2149            oldnext = &(bucket->next), bucket = *oldnext)
2150         {
2151           if ( bucket->src_addr == bb_dst &&
2152                bucket->dst_addr == bb_src )
2153             {
2154               bucket->count++;
2155               *oldnext = bucket->next;
2156               bucket->next = *startbucket;
2157               *startbucket = bucket;
2158               goto ret;
2159             }
2160         }
2161
2162       bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2163
2164       if (!bucket)
2165         {
2166           if (!reported)
2167             {
2168               fprintf (stderr, "Profiler: out of memory\n");
2169               reported = 1;
2170             }
2171         }
2172
2173       else
2174         {
2175           bucket->src_addr = bb_dst;
2176           bucket->dst_addr = bb_src;
2177           bucket->next = *startbucket;
2178           *startbucket = bucket;
2179           bucket->count = 1;
2180         }
2181     }
2182
2183 ret:
2184   bb_dst = bb_src;
2185
2186 skip:
2187   ;
2188
2189 }
2190
2191 /* Called upon entering the first function of a file.  */
2192
2193 static void
2194 __bb_init_file (struct bb *blocks)
2195 {
2196
2197   const struct bb_func *p;
2198   long blk, ncounts = blocks->ncounts;
2199   const char **functions = blocks->functions;
2200
2201   /* Set up linked list.  */
2202   blocks->zero_word = 1;
2203   blocks->next = bb_head;
2204   bb_head = blocks;
2205
2206   blocks->flags = 0;
2207   if (!bb_func_head ||
2208       !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
2209     return;
2210
2211   for (blk = 0; blk < ncounts; blk++)
2212     blocks->flags[blk] = 0;
2213
2214   for (blk = 0; blk < ncounts; blk++)
2215     {
2216       for (p = bb_func_head; p; p = p->next)
2217         {
2218           if (!strcmp (p->funcname, functions[blk]) &&
2219               (!p->filename || !strcmp (p->filename, blocks->filename)))
2220             {
2221               blocks->flags[blk] |= p->mode;
2222             }
2223         }
2224     }
2225
2226 }
2227
2228 /* Called when exiting from a function.  */
2229
2230 void
2231 __bb_trace_ret ()
2232 {
2233
2234   MACHINE_STATE_SAVE("2")
2235
2236   if (bb_callcount)
2237     {
2238       if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2239         {
2240           bb_src = bb_stack[bb_callcount];
2241           if (bb_mode & 8)
2242             __bb_trace_func_ret ();
2243         }
2244
2245       bb_callcount -= 1;
2246     }
2247
2248   MACHINE_STATE_RESTORE("2")
2249
2250 }
2251
2252 /* Called when entering a function.  */
2253
2254 void
2255 __bb_init_trace_func (struct bb *blocks, unsigned long blockno)
2256 {
2257   static int trace_init = 0;
2258
2259   MACHINE_STATE_SAVE("3")
2260
2261   if (!blocks->zero_word)
2262     { 
2263       if (!trace_init)
2264         { 
2265           trace_init = 1;
2266           __bb_init_prg ();
2267         }
2268       __bb_init_file (blocks);
2269     }
2270
2271   if (bb_callcount)
2272     {
2273
2274       bb_callcount += 1;
2275
2276       if (bb_mode & 12)
2277         {
2278           if (bb_callcount >= bb_stacksize)
2279             {
2280               size_t newsize = bb_callcount + 100;
2281
2282               bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2283               if (! bb_stack)
2284                 {
2285                   if (!reported)
2286                     {
2287                       fprintf (stderr, "Profiler: out of memory\n");
2288                       reported = 1;
2289                     }
2290                   bb_stacksize = 0;
2291                   goto stack_overflow;
2292                 }
2293               bb_stacksize = newsize;
2294             }
2295           bb_stack[bb_callcount] = bb_src;
2296
2297           if (bb_mode & 4)
2298             bb_src = 0;
2299
2300         }
2301
2302 stack_overflow:;
2303
2304     }
2305
2306   else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2307     {
2308       bb_callcount = 1;
2309       bb_src = 0;
2310
2311       if (bb_stack)
2312           bb_stack[bb_callcount] = bb_src;
2313     }
2314
2315   MACHINE_STATE_RESTORE("3")
2316 }
2317
2318 #endif /* not inhibit_libc */
2319 #endif /* not BLOCK_PROFILER_CODE */
2320 #endif /* L_bb */
2321 \f
2322 /* Default free-store management functions for C++, per sections 12.5 and
2323    17.3.3 of the Working Paper.  */
2324
2325 #ifdef L_op_new
2326 /* operator new (size_t), described in 17.3.3.5.  This function is used by
2327    C++ programs to allocate a block of memory to hold a single object.  */
2328
2329 typedef void (*vfp)(void);
2330 extern vfp __new_handler;
2331 extern void __default_new_handler (void);
2332
2333 #ifdef WEAK_ALIAS
2334 void * __builtin_new (size_t sz)
2335      __attribute__ ((weak, alias ("___builtin_new")));
2336 void *
2337 ___builtin_new (size_t sz)
2338 #else
2339 void *
2340 __builtin_new (size_t sz)
2341 #endif
2342 {
2343   void *p;
2344   vfp handler = (__new_handler) ? __new_handler : __default_new_handler;
2345
2346   /* malloc (0) is unpredictable; avoid it.  */
2347   if (sz == 0)
2348     sz = 1;
2349   p = (void *) malloc (sz);
2350   while (p == 0)
2351     {
2352       (*handler) ();
2353       p = (void *) malloc (sz);
2354     }
2355   
2356   return p;
2357 }
2358 #endif /* L_op_new */
2359
2360 #ifdef L_op_vnew
2361 /* void * operator new [] (size_t), described in 17.3.3.6.  This function
2362    is used by C++ programs to allocate a block of memory for an array.  */
2363
2364 extern void * __builtin_new (size_t);
2365
2366 #ifdef WEAK_ALIAS
2367 void * __builtin_vec_new (size_t sz)
2368      __attribute__ ((weak, alias ("___builtin_vec_new")));
2369 void *
2370 ___builtin_vec_new (size_t sz)
2371 #else
2372 void *
2373 __builtin_vec_new (size_t sz)
2374 #endif
2375 {
2376   return __builtin_new (sz);
2377 }
2378 #endif /* L_op_vnew */
2379
2380 #ifdef L_new_handler
2381 /* set_new_handler (fvoid_t *) and the default new handler, described in
2382    17.3.3.2 and 17.3.3.5.  These functions define the result of a failure
2383    to allocate the amount of memory requested from operator new or new [].  */
2384
2385 #ifndef inhibit_libc
2386 /* This gets us __GNU_LIBRARY__.  */
2387 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
2388 #include <stdio.h>
2389
2390 #ifdef __GNU_LIBRARY__
2391   /* Avoid forcing the library's meaning of `write' on the user program
2392      by using the "internal" name (for use within the library)  */
2393 #define write(fd, buf, n)       __write((fd), (buf), (n))
2394 #endif
2395 #endif /* inhibit_libc */
2396
2397 typedef void (*vfp)(void);
2398 void __default_new_handler (void);
2399
2400 vfp __new_handler = (vfp) 0;
2401
2402 vfp
2403 set_new_handler (vfp handler)
2404 {
2405   vfp prev_handler;
2406
2407   prev_handler = __new_handler;
2408   if (handler == 0) handler = __default_new_handler;
2409   __new_handler = handler;
2410   return prev_handler;
2411 }
2412
2413 #define MESSAGE "Virtual memory exceeded in `new'\n"
2414
2415 void
2416 __default_new_handler ()
2417 {
2418 #ifndef inhibit_libc
2419   /* don't use fprintf (stderr, ...) because it may need to call malloc.  */
2420   /* This should really print the name of the program, but that is hard to
2421      do.  We need a standard, clean way to get at the name.  */
2422   write (2, MESSAGE, sizeof (MESSAGE));
2423 #endif
2424   /* don't call exit () because that may call global destructors which
2425      may cause a loop.  */
2426   _exit (-1);
2427 }
2428 #endif
2429
2430 #ifdef L_op_delete
2431 /* operator delete (void *), described in 17.3.3.3.  This function is used
2432    by C++ programs to return to the free store a block of memory allocated
2433    as a single object.  */
2434
2435 #ifdef WEAK_ALIAS
2436 void __builtin_delete (void *ptr)
2437      __attribute__ ((weak, alias ("___builtin_delete")));
2438 void
2439 ___builtin_delete (void *ptr)
2440 #else
2441 void
2442 __builtin_delete (void *ptr)
2443 #endif
2444 {
2445   if (ptr)
2446     free (ptr);
2447 }
2448 #endif
2449
2450 #ifdef L_op_vdel
2451 /* operator delete [] (void *), described in 17.3.3.4.  This function is
2452    used by C++ programs to return to the free store a block of memory
2453    allocated as an array.  */
2454
2455 extern void __builtin_delete (void *);
2456
2457 #ifdef WEAK_ALIAS
2458 void __builtin_vec_delete (void *ptr)
2459      __attribute__ ((weak, alias ("___builtin_vec_delete")));
2460 void
2461 ___builtin_vec_delete (void *ptr)
2462 #else
2463 void
2464 __builtin_vec_delete (void *ptr)
2465 #endif
2466 {
2467   __builtin_delete (ptr);
2468 }
2469 #endif
2470
2471 /* End of C++ free-store management functions */
2472 \f
2473 #ifdef L_shtab
2474 unsigned int __shtab[] = {
2475     0x00000001, 0x00000002, 0x00000004, 0x00000008,
2476     0x00000010, 0x00000020, 0x00000040, 0x00000080,
2477     0x00000100, 0x00000200, 0x00000400, 0x00000800,
2478     0x00001000, 0x00002000, 0x00004000, 0x00008000,
2479     0x00010000, 0x00020000, 0x00040000, 0x00080000,
2480     0x00100000, 0x00200000, 0x00400000, 0x00800000,
2481     0x01000000, 0x02000000, 0x04000000, 0x08000000,
2482     0x10000000, 0x20000000, 0x40000000, 0x80000000
2483   };
2484 #endif
2485 \f
2486 #ifdef L_clear_cache
2487 /* Clear part of an instruction cache.  */
2488
2489 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2490
2491 void
2492 __clear_cache (char *beg, char *end)
2493 {
2494 #ifdef CLEAR_INSN_CACHE 
2495   CLEAR_INSN_CACHE (beg, end);
2496 #else
2497 #ifdef INSN_CACHE_SIZE
2498   static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
2499   static int initialized;
2500   int offset;
2501   void *start_addr
2502   void *end_addr;
2503   typedef (*function_ptr) ();
2504
2505 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2506   /* It's cheaper to clear the whole cache.
2507      Put in a series of jump instructions so that calling the beginning
2508      of the cache will clear the whole thing.  */
2509
2510   if (! initialized)
2511     {
2512       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2513                  & -INSN_CACHE_LINE_WIDTH);
2514       int end_ptr = ptr + INSN_CACHE_SIZE;
2515
2516       while (ptr < end_ptr)
2517         {
2518           *(INSTRUCTION_TYPE *)ptr
2519             = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2520           ptr += INSN_CACHE_LINE_WIDTH;
2521         }
2522       *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
2523
2524       initialized = 1;
2525     }
2526
2527   /* Call the beginning of the sequence.  */
2528   (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2529                     & -INSN_CACHE_LINE_WIDTH))
2530    ());
2531
2532 #else /* Cache is large.  */
2533
2534   if (! initialized)
2535     {
2536       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2537                  & -INSN_CACHE_LINE_WIDTH);
2538
2539       while (ptr < (int) array + sizeof array)
2540         {
2541           *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2542           ptr += INSN_CACHE_LINE_WIDTH;
2543         }
2544
2545       initialized = 1;
2546     }
2547
2548   /* Find the location in array that occupies the same cache line as BEG.  */
2549
2550   offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2551   start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2552                  & -INSN_CACHE_PLANE_SIZE)
2553                 + offset);
2554
2555   /* Compute the cache alignment of the place to stop clearing.  */
2556 #if 0  /* This is not needed for gcc's purposes.  */
2557   /* If the block to clear is bigger than a cache plane,
2558      we clear the entire cache, and OFFSET is already correct.  */ 
2559   if (end < beg + INSN_CACHE_PLANE_SIZE)
2560 #endif
2561     offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2562                & -INSN_CACHE_LINE_WIDTH)
2563               & (INSN_CACHE_PLANE_SIZE - 1));
2564
2565 #if INSN_CACHE_DEPTH > 1
2566   end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2567   if (end_addr <= start_addr)
2568     end_addr += INSN_CACHE_PLANE_SIZE;
2569
2570   for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2571     {
2572       int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2573       int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2574
2575       while (addr != stop)
2576         {
2577           /* Call the return instruction at ADDR.  */
2578           ((function_ptr) addr) ();
2579
2580           addr += INSN_CACHE_LINE_WIDTH;
2581         }
2582     }
2583 #else /* just one plane */
2584   do
2585     {
2586       /* Call the return instruction at START_ADDR.  */
2587       ((function_ptr) start_addr) ();
2588
2589       start_addr += INSN_CACHE_LINE_WIDTH;
2590     }
2591   while ((start_addr % INSN_CACHE_SIZE) != offset);
2592 #endif /* just one plane */
2593 #endif /* Cache is large */
2594 #endif /* Cache exists */
2595 #endif /* CLEAR_INSN_CACHE */
2596 }
2597
2598 #endif /* L_clear_cache */
2599 \f
2600 #ifdef L_trampoline
2601
2602 /* Jump to a trampoline, loading the static chain address.  */
2603
2604 #ifdef WINNT
2605
2606 long getpagesize()
2607 {
2608 #ifdef _ALPHA_
2609   return 8192;
2610 #else
2611   return 4096;
2612 #endif
2613 }
2614
2615 int mprotect(char *addr, int len, int prot)
2616 {
2617   int np, op;
2618
2619   if (prot == 7) np = 0x40;
2620   else if (prot == 5) np = 0x20;
2621   else if (prot == 4) np = 0x10;
2622   else if (prot == 3) np = 0x04;
2623   else if (prot == 1) np = 0x02;
2624   else if (prot == 0) np = 0x01;
2625
2626   if (VirtualProtect (addr, len, np, &op))
2627     return 0;
2628   else
2629     return -1;
2630     
2631 }
2632
2633 #endif
2634
2635 #ifdef TRANSFER_FROM_TRAMPOLINE 
2636 TRANSFER_FROM_TRAMPOLINE 
2637 #endif
2638
2639 #if defined (NeXT) && defined (__MACH__)
2640
2641 /* Make stack executable so we can call trampolines on stack.
2642    This is called from INITIALIZE_TRAMPOLINE in next.h.  */
2643 #ifdef NeXTStep21
2644  #include <mach.h>
2645 #else
2646  #include <mach/mach.h>
2647 #endif
2648
2649 void
2650 __enable_execute_stack (char *addr)
2651 {
2652   kern_return_t r;
2653   char *eaddr = addr + TRAMPOLINE_SIZE;
2654   vm_address_t a = (vm_address_t) addr;
2655
2656   /* turn on execute access on stack */
2657   r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2658   if (r != KERN_SUCCESS)
2659     {
2660       mach_error("vm_protect VM_PROT_ALL", r);
2661       exit(1);
2662     }
2663
2664   /* We inline the i-cache invalidation for speed */
2665
2666 #ifdef CLEAR_INSN_CACHE
2667   CLEAR_INSN_CACHE (addr, eaddr);
2668 #else
2669   __clear_cache ((int) addr, (int) eaddr);
2670 #endif
2671
2672
2673 #endif /* defined (NeXT) && defined (__MACH__) */
2674
2675 #ifdef __convex__
2676
2677 /* Make stack executable so we can call trampolines on stack.
2678    This is called from INITIALIZE_TRAMPOLINE in convex.h.  */
2679
2680 #include <sys/mman.h>
2681 #include <sys/vmparam.h>
2682 #include <machine/machparam.h>
2683
2684 void
2685 __enable_execute_stack ()
2686 {
2687   int fp;
2688   static unsigned lowest = USRSTACK;
2689   unsigned current = (unsigned) &fp & -NBPG;
2690
2691   if (lowest > current)
2692     {
2693       unsigned len = lowest - current;
2694       mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2695       lowest = current;
2696     }
2697
2698   /* Clear instruction cache in case an old trampoline is in it.  */
2699   asm ("pich");
2700 }
2701 #endif /* __convex__ */
2702
2703 #ifdef __DOLPHIN__
2704
2705 /* Modified from the convex -code above.  */
2706
2707 #include <sys/param.h>
2708 #include <errno.h>
2709 #include <sys/m88kbcs.h>
2710
2711 void
2712 __enable_execute_stack ()
2713 {
2714   int save_errno;
2715   static unsigned long lowest = USRSTACK;
2716   unsigned long current = (unsigned long) &save_errno & -NBPC;
2717   
2718   /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2719      address is seen as 'negative'. That is the case with the stack.   */
2720
2721   save_errno=errno;
2722   if (lowest > current)
2723     {
2724       unsigned len=lowest-current;
2725       memctl(current,len,MCT_TEXT);
2726       lowest = current;
2727     }
2728   else
2729     memctl(current,NBPC,MCT_TEXT);
2730   errno=save_errno;
2731 }
2732
2733 #endif /* __DOLPHIN__ */
2734
2735 #ifdef __pyr__
2736
2737 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
2738 #include <stdio.h>
2739 #include <sys/mman.h>
2740 #include <sys/types.h>
2741 #include <sys/param.h>
2742 #include <sys/vmmac.h>
2743
2744 /* Modified from the convex -code above.
2745    mremap promises to clear the i-cache.  */
2746
2747 void
2748 __enable_execute_stack ()
2749 {
2750   int fp;
2751   if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2752                 PROT_READ|PROT_WRITE|PROT_EXEC))
2753     {
2754       perror ("mprotect in __enable_execute_stack");
2755       fflush (stderr);
2756       abort ();
2757     }
2758 }
2759 #endif /* __pyr__ */
2760
2761 #if defined (sony_news) && defined (SYSTYPE_BSD)
2762
2763 #include <stdio.h>
2764 #include <sys/types.h>
2765 #include <sys/param.h>
2766 #include <syscall.h>
2767 #include <machine/sysnews.h>
2768
2769 /* cacheflush function for NEWS-OS 4.2.
2770    This function is called from trampoline-initialize code
2771    defined in config/mips/mips.h.  */
2772
2773 void
2774 cacheflush (char *beg, int size, int flag)
2775 {
2776   if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
2777     {
2778       perror ("cache_flush");
2779       fflush (stderr);
2780       abort ();
2781     }
2782 }
2783
2784 #endif /* sony_news */
2785 #endif /* L_trampoline */
2786 \f
2787 #ifdef L__main
2788
2789 #include "gbl-ctors.h"
2790 /* Some systems use __main in a way incompatible with its use in gcc, in these
2791    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2792    give the same symbol without quotes for an alternative entry point.  You
2793    must define both, or neither.  */
2794 #ifndef NAME__MAIN
2795 #define NAME__MAIN "__main"
2796 #define SYMBOL__MAIN __main
2797 #endif
2798
2799 #ifdef INIT_SECTION_ASM_OP
2800 #undef HAS_INIT_SECTION
2801 #define HAS_INIT_SECTION
2802 #endif
2803
2804 #if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
2805 /* Run all the global destructors on exit from the program.  */
2806
2807 void
2808 __do_global_dtors ()
2809 {
2810 #ifdef DO_GLOBAL_DTORS_BODY
2811   DO_GLOBAL_DTORS_BODY;
2812 #else
2813   static func_ptr *p = __DTOR_LIST__ + 1;
2814   while (*p)
2815     {
2816       p++;
2817       (*(p-1)) ();
2818     }
2819 #endif
2820 }
2821 #endif
2822
2823 #ifndef HAS_INIT_SECTION
2824 /* Run all the global constructors on entry to the program.  */
2825
2826 #ifndef ON_EXIT
2827 #define ON_EXIT(a, b)
2828 #else
2829 /* Make sure the exit routine is pulled in to define the globals as
2830    bss symbols, just in case the linker does not automatically pull
2831    bss definitions from the library.  */
2832
2833 extern int _exit_dummy_decl;
2834 int *_exit_dummy_ref = &_exit_dummy_decl;
2835 #endif /* ON_EXIT */
2836
2837 void
2838 __do_global_ctors ()
2839 {
2840   DO_GLOBAL_CTORS_BODY;
2841   ON_EXIT (__do_global_dtors, 0);
2842 }
2843 #endif /* no HAS_INIT_SECTION */
2844
2845 #if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
2846 /* Subroutine called automatically by `main'.
2847    Compiling a global function named `main'
2848    produces an automatic call to this function at the beginning.
2849
2850    For many systems, this routine calls __do_global_ctors.
2851    For systems which support a .init section we use the .init section
2852    to run __do_global_ctors, so we need not do anything here.  */
2853
2854 void
2855 SYMBOL__MAIN ()
2856 {
2857   /* Support recursive calls to `main': run initializers just once.  */
2858   static int initialized;
2859   if (! initialized)
2860     {
2861       initialized = 1;
2862       __do_global_ctors ();
2863     }
2864 }
2865 #endif /* no HAS_INIT_SECTION or INVOKE__main */
2866
2867 #endif /* L__main */
2868 \f
2869 #ifdef L_ctors
2870
2871 #include "gbl-ctors.h"
2872
2873 /* Provide default definitions for the lists of constructors and
2874    destructors, so that we don't get linker errors.  These symbols are
2875    intentionally bss symbols, so that gld and/or collect will provide
2876    the right values.  */
2877
2878 /* We declare the lists here with two elements each,
2879    so that they are valid empty lists if no other definition is loaded.  */
2880 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
2881 #if defined(__NeXT__) || defined(_AIX)
2882 /* After 2.3, try this definition on all systems.  */
2883 func_ptr __CTOR_LIST__[2] = {0, 0};
2884 func_ptr __DTOR_LIST__[2] = {0, 0};
2885 #else
2886 func_ptr __CTOR_LIST__[2];
2887 func_ptr __DTOR_LIST__[2];
2888 #endif
2889 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
2890 #endif /* L_ctors */
2891 \f
2892 #ifdef L_exit
2893
2894 #include "gbl-ctors.h"
2895
2896 #ifdef NEED_ATEXIT
2897 # ifdef ON_EXIT
2898 #  undef ON_EXIT
2899 # endif
2900 int _exit_dummy_decl = 0;       /* prevent compiler & linker warnings */
2901 #endif
2902
2903 #ifndef ON_EXIT
2904
2905 #ifdef NEED_ATEXIT
2906 # include <errno.h>
2907
2908 static func_ptr *atexit_chain = NULL;
2909 static long atexit_chain_length = 0;
2910 static volatile long last_atexit_chain_slot = -1;
2911
2912 int atexit (func_ptr func)
2913 {
2914   if (++last_atexit_chain_slot == atexit_chain_length)
2915     {
2916       atexit_chain_length += 32;
2917       if (atexit_chain)
2918         atexit_chain = realloc (atexit_chain,
2919                                 atexit_chain_length * sizeof (func_ptr));
2920       else
2921         atexit_chain = malloc (atexit_chain_length * sizeof (func_ptr));
2922       if (! atexit_chain)
2923         {
2924           atexit_chain_length = 0;
2925           last_atexit_chain_slot = -1;
2926           errno = ENOMEM;
2927           return (-1);
2928         }
2929     }
2930   atexit_chain[last_atexit_chain_slot] = func;
2931   return (0);
2932 }
2933 #endif /* NEED_ATEXIT */
2934
2935 /* If we have no known way of registering our own __do_global_dtors
2936    routine so that it will be invoked at program exit time, then we
2937    have to define our own exit routine which will get this to happen.  */
2938
2939 extern void __do_global_dtors ();
2940 extern void _cleanup ();
2941 extern void _exit () __attribute__ ((noreturn));
2942
2943 void 
2944 exit (int status)
2945 {
2946 #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
2947 #ifdef NEED_ATEXIT
2948   if (atexit_chain)
2949     {
2950       for ( ; last_atexit_chain_slot-- >= 0; )
2951         {
2952           (*atexit_chain[last_atexit_chain_slot + 1]) ();
2953           atexit_chain[last_atexit_chain_slot + 1] = NULL;
2954         }
2955       free (atexit_chain);
2956       atexit_chain = NULL;
2957     }
2958 #else /* No NEED_ATEXIT */
2959   __do_global_dtors ();
2960 #endif /* No NEED_ATEXIT */
2961 #endif
2962 #ifdef EXIT_BODY
2963   EXIT_BODY;
2964 #else
2965   _cleanup ();
2966 #endif
2967   _exit (status);
2968 }
2969
2970 #else
2971 int _exit_dummy_decl = 0;       /* prevent compiler & linker warnings */
2972 #endif
2973
2974 #endif /* L_exit */
2975 \f
2976 #ifdef L_eh
2977
2978 #ifdef EH_TABLE_LOOKUP
2979
2980 EH_TABLE_LOOKUP
2981
2982 #else
2983
2984 typedef struct {
2985   void *start;
2986   void *end;
2987   void *exception_handler;
2988 } exception_table;
2989
2990 struct exception_table_node {
2991   exception_table *table;
2992   void *start;
2993   void *end;
2994   struct exception_table_node *next;
2995 };
2996
2997 static struct exception_table_node *exception_table_list;
2998
2999 static exception_table *
3000 find_exception_table (void *pc)
3001 {
3002   register struct exception_table_node *table = exception_table_list;
3003   for ( ; table != 0; table = table->next)
3004     {
3005       if (table->start <= pc && table->end > pc)
3006         return table->table;
3007     }
3008   return 0;
3009 }
3010
3011 /* this routine takes a pc, and the address of the exception handler associated
3012    with the closest exception table handler entry associated with that PC,
3013    or 0 if there are no table entries the PC fits in.  The algorithm works
3014    something like this:
3015
3016     while(current_entry exists) {
3017         if(current_entry.start < pc )
3018             current_entry = next_entry;
3019         else {
3020             if(prev_entry.start <= pc && prev_entry.end > pc) {
3021                 save pointer to prev_entry;
3022                 return prev_entry.exception_handler;
3023              }
3024             else return 0;
3025          }
3026      }
3027     return 0;
3028
3029    Assuming a correctly sorted table (ascending order) this routine should
3030    return the tightest match...
3031
3032    In the advent of a tie, we have to give the last entry, as it represents
3033    an inner block.  */
3034
3035 void *
3036 __find_first_exception_table_match (void *pc)
3037 {
3038   exception_table *table = find_exception_table (pc);
3039   int pos = 0;
3040   int best = 0;
3041   if (table == 0)
3042     return (void *) 0;
3043 #if 0
3044   printf ("find_first_exception_table_match (): pc = %x!\n", pc);
3045 #endif
3046
3047 #if 0
3048   /* We can't do this yet, as we don't know that the table is sorted.  */
3049   do {
3050     ++pos;
3051     if (table[pos].start > pc)
3052       /* found the first table[pos].start > pc, so the previous
3053          entry better be the one we want! */
3054       break;
3055   } while (table[pos].exception_handler != (void *) -1);
3056
3057   --pos;
3058   if (table[pos].start <= pc && table[pos].end > pc)
3059     {
3060 #if 0
3061       printf ("find_first_eh_table_match (): found match: %x\n", table[pos].exception_handler);
3062 #endif
3063       return table[pos].exception_handler;
3064     }
3065 #else
3066   while (table[++pos].exception_handler != (void *) -1) {
3067     if (table[pos].start <= pc && table[pos].end > pc)
3068       {
3069         /* This can apply.  Make sure it is better or as good as the previous
3070            best.  */
3071         /* The best one ends first.  */
3072         if (best == 0 || (table[pos].end <= table[best].end
3073                           /* The best one starts last.  */
3074                           && table[pos].start >= table[best].start))
3075           best = pos;
3076       }
3077   }
3078   if (best != 0)
3079     return table[best].exception_handler;
3080 #endif
3081
3082 #if 0
3083   printf ("find_first_eh_table_match (): else: returning NULL!\n");
3084 #endif
3085   return (void *) 0;
3086 }
3087
3088 void
3089 __register_exceptions (exception_table *table)
3090 {
3091   struct exception_table_node *node;
3092   exception_table *range = table + 1;
3093
3094   if (range->start == (void *) -1)
3095     return;
3096
3097   node = (struct exception_table_node *)
3098     malloc (sizeof (struct exception_table_node));
3099   node->table = table;
3100
3101   /* This look can be optimized away either if the table
3102      is sorted, or if we pass in extra parameters.  */
3103   node->start = range->start;
3104   node->end = range->end;
3105   for (range++ ; range->start != (void *) (-1); range++)
3106     {
3107       if (range->start < node->start)
3108         node->start = range->start;
3109       if (range->end > node->end)
3110         node->end = range->end;
3111     }
3112
3113   node->next = exception_table_list;
3114   exception_table_list = node;
3115 }
3116 #endif
3117
3118 void *
3119 __throw_type_match (void *catch_type, void *throw_type, void *obj)
3120 {
3121 #if 0
3122  printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
3123          catch_type, throw_type);
3124 #endif
3125  if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
3126    return obj;
3127  return 0;
3128 }
3129
3130 /* Throw stub routine.
3131
3132    This is work in progress, but not completed yet.  */
3133
3134 void
3135 __throw ()
3136 {
3137   abort ();
3138 }
3139
3140 /* This value identifies the place from which an exception is being
3141    thrown.  */
3142
3143 void *__eh_pc;
3144
3145 void
3146 __empty ()
3147 {
3148 }
3149
3150 #if #machine(i386)
3151 void
3152 __unwind_function(void *ptr)
3153 {
3154   asm("movl 8(%esp),%ecx");
3155   /* Undo current frame */
3156   asm("movl %ebp,%esp");
3157   asm("popl %ebp");
3158   /* like ret, but stay here */
3159   asm("addl $4,%esp");
3160   
3161   /* Now, undo previous frame.  */
3162   /* This is a test routine, as we have to dynamically probe to find out
3163      what to pop for certain, this is just a guess.  */
3164   asm("leal -16(%ebp),%esp");
3165   asm("pop %ebx");
3166   asm("pop %esi");
3167   asm("pop %edi");
3168   asm("movl %ebp,%esp");
3169   asm("popl %ebp");
3170
3171   asm("movl %ecx,0(%esp)");
3172   asm("ret");
3173 }
3174 #elif #machine(rs6000) && !defined _ARCH_PPC
3175 __unwind_function(void *ptr)
3176 {
3177   asm("mr 31,1");
3178   asm("l 1,0(1)");
3179   asm("l 31,-4(1)");
3180   asm("# br");
3181
3182   asm("mr 31,1");
3183   asm("l 1,0(1)");
3184   /* use 31 as a scratch register to restore the link register.  */
3185   asm("l 31, 8(1);mtlr 31 # l lr,8(1)");
3186   asm("l 31,-4(1)");
3187   asm("# br");
3188   asm("mtctr 3;bctr # b 3");
3189 }
3190 #elif (#machine(rs6000) || #machine(powerpc)) && defined _ARCH_PPC
3191 __unwind_function(void *ptr)
3192 {
3193   asm("mr 31,1");
3194   asm("lwz 1,0(1)");
3195   asm("lwz 31,-4(1)");
3196   asm("# br");
3197
3198   asm("mr 31,1");
3199   asm("lwz 1,0(1)");
3200   /* use 31 as a scratch register to restore the link register.  */
3201   asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)");
3202   asm("lwz 31,-4(1)");
3203   asm("# br");
3204   asm("mtctr 3;bctr # b 3");
3205 }
3206 #elif #machine(vax)
3207 __unwind_function(void *ptr)
3208 {
3209   __label__ return_again;
3210
3211   /* Replace our frame's return address with the label below.
3212      During execution, we will first return here instead of to
3213      caller, then second return takes caller's frame off the stack.
3214      Two returns matches two actual calls, so is less likely to
3215      confuse debuggers.  `16' corresponds to RETURN_ADDRESS_OFFSET.  */
3216   __asm ("movl %0,16(fp)" : : "p" (&& return_again));
3217   return;
3218
3219  return_again:
3220   return;
3221 }
3222 #else
3223 __unwind_function(void *ptr)
3224 {
3225   abort ();
3226 }
3227 #endif /* powerpc */
3228 #endif /* L_eh */
3229 \f
3230 #ifdef L_pure
3231 #ifndef inhibit_libc
3232 /* This gets us __GNU_LIBRARY__.  */
3233 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
3234 #include <stdio.h>
3235
3236 #ifdef __GNU_LIBRARY__
3237   /* Avoid forcing the library's meaning of `write' on the user program
3238      by using the "internal" name (for use within the library)  */
3239 #define write(fd, buf, n)       __write((fd), (buf), (n))
3240 #endif
3241 #endif /* inhibit_libc */
3242
3243 #define MESSAGE "pure virtual method called\n"
3244
3245 void
3246 __pure_virtual ()
3247 {
3248 #ifndef inhibit_libc
3249   write (2, MESSAGE, sizeof (MESSAGE) - 1);
3250 #endif
3251   _exit (-1);
3252 }
3253 #endif