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