OSDN Git Service

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