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