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