This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Merge pull request #65 from tonycoz/compiler-find-quadmath
[metaconfig.git] / U / perl / perlxv.U
1 ?RCS: $Id: perlxv.U,v 1.1 2000/08/31 17:53:56 jhi Exp jhi $
2 ?RCS:
3 ?RCS: Copyright (c) 1999 Jarkko Hietaniemi
4 ?RCS:
5 ?RCS: You may distribute under the terms of either the GNU General Public
6 ?RCS: License or the Artistic License, as specified in the README file.
7 ?RCS:
8 ?MAKE:ivtype uvtype nvtype ivsize uvsize nvsize \
9       i8type u8type i16type u16type i32type u32type i64type u64type \
10       i8size u8size i16size u16size i32size u32size i64size u64size \
11       d_nv_preserves_uv nv_preserves_uv_bits nv_overflows_integers_at \
12       d_nv_zero_is_allbits_zero: \
13         echo rm_try use64bitint d_quad quadtype uquadtype usequadmath \
14         d_longdbl uselongdouble longdblsize doublesize i_quadmath \
15         shortsize intsize longsize i_stdlib libs gccversion \
16         cat Compile i_inttypes test signal_t run
17 ?MAKE:  -pick add $@ %<
18 ?S:ivtype:
19 ?S:     This variable contains the C type used for Perl's IV.
20 ?S:.
21 ?S:uvtype:
22 ?S:     This variable contains the C type used for Perl's UV.
23 ?S:.
24 ?S:nvtype:
25 ?S:     This variable contains the C type used for Perl's NV.
26 ?S:.
27 ?S:i8type:
28 ?S:     This variable contains the C type used for Perl's I8.
29 ?S:.
30 ?S:u8type:
31 ?S:     This variable contains the C type used for Perl's U8.
32 ?S:.
33 ?S:i16type:
34 ?S:     This variable contains the C type used for Perl's I16.
35 ?S:.
36 ?S:u16type:
37 ?S:     This variable contains the C type used for Perl's U16.
38 ?S:.
39 ?S:i32type:
40 ?S:     This variable contains the C type used for Perl's I32.
41 ?S:.
42 ?S:u32type:
43 ?S:     This variable contains the C type used for Perl's U32.
44 ?S:.
45 ?S:i64type:
46 ?S:     This variable contains the C type used for Perl's I64.
47 ?S:.
48 ?S:u64type:
49 ?S:     This variable contains the C type used for Perl's U64.
50 ?S:.
51 ?S:ivsize:
52 ?S:     This variable is the size of an IV in bytes.
53 ?S:.
54 ?S:uvsize:
55 ?S:     This variable is the size of a UV in bytes.
56 ?S:.
57 ?S:i8size:
58 ?S:     This variable is the size of an I8 in bytes.
59 ?S:.
60 ?S:u8size:
61 ?S:     This variable is the size of an U8 in bytes.
62 ?S:.
63 ?S:i16size:
64 ?S:     This variable is the size of an I16 in bytes.
65 ?S:.
66 ?S:u16size:
67 ?S:     This variable is the size of an U16 in bytes.
68 ?S:.
69 ?S:i32size:
70 ?S:     This variable is the size of an I32 in bytes.
71 ?S:.
72 ?S:u32size:
73 ?S:     This variable is the size of an U32 in bytes.
74 ?S:.
75 ?S:i64size:
76 ?S:     This variable is the size of an I64 in bytes.
77 ?S:.
78 ?S:u64size:
79 ?S:     This variable is the size of an U64 in bytes.
80 ?S:.
81 ?S:nvsize:
82 ?S:     This variable is the size of a Perl NV in bytes.
83 ?S:     Note that some floating point formats have unused bytes.
84 ?S:.
85 ?S:d_nv_preserves_uv:
86 ?S:     This variable indicates whether a variable of type nvtype
87 ?S:     can preserve all the bits a variable of type uvtype.
88 ?S:.
89 ?S:nv_preserves_uv_bits:
90 ?S:     This variable indicates how many of bits type uvtype
91 ?S:     a variable nvtype can preserve.
92 ?S:.
93 ?S:nv_overflows_integers_at:
94 ?S:     This variable gives the largest integer value that NVs can hold
95 ?S:     as a constant floating point expression.
96 ?S:     If it could not be determined, it holds the value 0.
97 ?S:.
98 ?S:d_nv_zero_is_allbits_zero:
99 ?S:     This variable indicates whether a variable of type nvtype
100 ?S:     stores 0.0 in memory as all bits zero.
101 ?S:.
102 ?C:IVTYPE:
103 ?C:     This symbol defines the C type used for Perl's IV.
104 ?C:.
105 ?C:UVTYPE:
106 ?C:     This symbol defines the C type used for Perl's UV.
107 ?C:.
108 ?C:I8TYPE:
109 ?C:     This symbol defines the C type used for Perl's I8.
110 ?C:.
111 ?C:U8TYPE:
112 ?C:     This symbol defines the C type used for Perl's U8.
113 ?C:.
114 ?C:I16TYPE:
115 ?C:     This symbol defines the C type used for Perl's I16.
116 ?C:.
117 ?C:U16TYPE:
118 ?C:     This symbol defines the C type used for Perl's U16.
119 ?C:.
120 ?C:I32TYPE:
121 ?C:     This symbol defines the C type used for Perl's I32.
122 ?C:.
123 ?C:U32TYPE:
124 ?C:     This symbol defines the C type used for Perl's U32.
125 ?C:.
126 ?C:I64TYPE:
127 ?C:     This symbol defines the C type used for Perl's I64.
128 ?C:.
129 ?C:U64TYPE:
130 ?C:     This symbol defines the C type used for Perl's U64.
131 ?C:.
132 ?C:NVTYPE:
133 ?C:     This symbol defines the C type used for Perl's NV.
134 ?C:.
135 ?C:IVSIZE:
136 ?C:     This symbol contains the sizeof(IV).
137 ?C:.
138 ?C:UVSIZE:
139 ?C:     This symbol contains the sizeof(UV).
140 ?C:.
141 ?C:I8SIZE:
142 ?C:     This symbol contains the sizeof(I8).
143 ?C:.
144 ?C:U8SIZE:
145 ?C:     This symbol contains the sizeof(U8).
146 ?C:.
147 ?C:I16SIZE:
148 ?C:     This symbol contains the sizeof(I16).
149 ?C:.
150 ?C:U16SIZE:
151 ?C:     This symbol contains the sizeof(U16).
152 ?C:.
153 ?C:I32SIZE:
154 ?C:     This symbol contains the sizeof(I32).
155 ?C:.
156 ?C:U32SIZE:
157 ?C:     This symbol contains the sizeof(U32).
158 ?C:.
159 ?C:I64SIZE:
160 ?C:     This symbol contains the sizeof(I64).
161 ?C:.
162 ?C:U64SIZE:
163 ?C:     This symbol contains the sizeof(U64).
164 ?C:.
165 ?C:NVSIZE:
166 ?C:     This symbol contains the sizeof(NV).
167 ?C:     Note that some floating point formats have unused bytes.
168 ?C:     The most notable example is the x86* 80-bit extended precision
169 ?C:     which comes in byte sizes of 12 and 16 (for 32 and 64 bit
170 ?C:     platforms, respectively), but which only uses 10 bytes.
171 ?C:     Perl compiled with -Duselongdouble on x86* is like this.
172 ?C:.
173 ?C:NV_PRESERVES_UV:
174 ?C:     This symbol, if defined, indicates that a variable of type NVTYPE
175 ?C:     can preserve all the bits of a variable of type UVTYPE.
176 ?C:.
177 ?C:NV_PRESERVES_UV_BITS:
178 ?C:     This symbol contains the number of bits a variable of type NVTYPE
179 ?C:     can preserve of a variable of type UVTYPE.
180 ?C:.
181 ?C:NV_OVERFLOWS_INTEGERS_AT:
182 ?C:     This symbol gives the largest integer value that NVs can hold. This
183 ?C:     value + 1.0 cannot be stored accurately. It is expressed as constant
184 ?C:     floating point expression to reduce the chance of decimal/binary
185 ?C:     conversion issues. If it can not be determined, the value 0 is given.
186 ?C:.
187 ?C:NV_ZERO_IS_ALLBITS_ZERO:
188 ?C:     This symbol, if defined, indicates that a variable of type NVTYPE
189 ?C:     stores 0.0 in memory as all bits zero.
190 ?C:.
191 ?H:#define      IVTYPE          $ivtype         /**/
192 ?H:#define      UVTYPE          $uvtype         /**/
193 ?H:#define      I8TYPE          $i8type         /**/
194 ?H:#define      U8TYPE          $u8type         /**/
195 ?H:#define      I16TYPE         $i16type        /**/
196 ?H:#define      U16TYPE         $u16type        /**/
197 ?H:#define      I32TYPE         $i32type        /**/
198 ?H:#define      U32TYPE         $u32type        /**/
199 ?H:?%<:#ifdef HAS_QUAD
200 ?H:?%<:#define  I64TYPE         $i64type        /**/
201 ?H:?%<:#define  U64TYPE         $u64type        /**/
202 ?H:?%<:#endif
203 ?H:#define      NVTYPE          $nvtype         /**/
204 ?H:#define      IVSIZE          $ivsize         /**/
205 ?H:#define      UVSIZE          $uvsize         /**/
206 ?H:#define      I8SIZE          $i8size         /**/
207 ?H:#define      U8SIZE          $u8size         /**/
208 ?H:#define      I16SIZE         $i16size        /**/
209 ?H:#define      U16SIZE         $u16size        /**/
210 ?H:#define      I32SIZE         $i32size        /**/
211 ?H:#define      U32SIZE         $u32size        /**/
212 ?H:?%<:#ifdef HAS_QUAD
213 ?H:?%<:#define  I64SIZE         $i64size        /**/
214 ?H:?%<:#define  U64SIZE         $u64size        /**/
215 ?H:?%<:#endif
216 ?H:#define      NVSIZE          $nvsize         /**/
217 ?H:#$d_nv_preserves_uv  NV_PRESERVES_UV
218 ?H:#define      NV_PRESERVES_UV_BITS    $nv_preserves_uv_bits
219 ?H:#define      NV_OVERFLOWS_INTEGERS_AT        ($nv_overflows_integers_at)
220 ?H:#$d_nv_zero_is_allbits_zero  NV_ZERO_IS_ALLBITS_ZERO
221 ?H:?%<:#if UVSIZE == 8
222 ?H:?%<:#   ifdef BYTEORDER
223 ?H:?%<:#       if BYTEORDER == 0x1234
224 ?H:?%<:#           undef BYTEORDER
225 ?H:?%<:#           define BYTEORDER 0x12345678
226 ?H:?%<:#       else
227 ?H:?%<:#           if BYTEORDER == 0x4321
228 ?H:?%<:#               undef BYTEORDER
229 ?H:?%<:#               define BYTEORDER 0x87654321
230 ?H:?%<:#           endif
231 ?H:?%<:#       endif
232 ?H:?%<:#   endif
233 ?H:?%<:#endif
234 ?H:.
235 ?T:xxx
236 ?T:d
237 ?F:!try
238 : Check basic sizes
239 echo " "
240 $echo "Choosing the C types to be used for Perl's internal types..." >&4
241
242 case "$use64bitint:$d_quad:$quadtype" in
243 define:define:?*)
244         ivtype="$quadtype"
245         uvtype="$uquadtype"
246         ivsize=8
247         uvsize=8
248         ;;
249 *)      ivtype="long"
250         uvtype="unsigned long"
251         ivsize=$longsize
252         uvsize=$longsize
253         ;;
254 esac
255
256 case "$uselongdouble:$d_longdbl" in
257 define:define)
258         nvtype="long double"
259         nvsize=$longdblsize
260         ;;
261 *)      nvtype=double
262         nvsize=$doublesize
263         ;;
264 esac
265
266 case "$usequadmath:$i_quadmath" in
267 define:define)
268   nvtype="__float128"
269   nvsize=16
270   : libquadmath is not in the usual places, and the place
271   : changes if the compiler is upgraded.  So ask the compiler if it
272   : can find it.
273   : We do not need to save this, if it fails we abort.
274   libs="$libs -lquadmath"
275   set try
276   $cat >try.c <<EOM
277 #include <quadmath.h>
278 #include <stdio.h>
279 int main(int argc, char *argv[]) {
280   __float128 x = 1.0;
281   if (fabsq(logq(x)) > 1e-6) {
282      fputs("quadmath is broken\n", stderr);
283      return 1;
284   }
285   puts("define");
286   return 0;
287 }
288 EOM
289   yyy=''
290   if eval $compile_ok; then
291       yyy=`$run ./try`
292       case "$yyy" in
293       define) ;;
294       *) cat <<EOM >&4
295
296 *** You requested the use of the quadmath library, but
297 *** it appears to be nonfunctional.
298 *** Cannot continue, aborting.
299
300 EOM
301        exit 1
302        ;;
303        esac
304   else
305       $cat <<EOM >&4
306
307 *** You requested the use of the quadmath library, but you
308 *** do not seem to have the quadmath library installed.
309 *** Cannot continue, aborting.
310 EOM
311     exit 1
312   fi
313   ;;
314 define:*) $cat <<EOM >&4
315
316 *** You requested the use of the quadmath library, but you
317 *** do not seem to have the required header, <quadmath.h>.
318 EOM
319   case "$gccversion" in
320   [23].*|4.[0-5]*)
321    $cat <<EOM >&4
322 *** Your gcc looks a bit old:
323 *** $gccversion
324 EOM
325     ;;
326   '')
327    $cat <<EOM >&4
328 *** You are not running a gcc.
329 EOM
330     ;;
331   esac
332   $cat <<EOM >&4
333 *** For the quadmath library you need at least gcc 4.6.
334 *** Cannot continue, aborting.
335 EOM
336   exit 1
337   ;;
338 esac
339
340 $echo "(IV will be "$ivtype", $ivsize bytes)"
341 $echo "(UV will be "$uvtype", $uvsize bytes)"
342 $echo "(NV will be "$nvtype", $nvsize bytes)"
343
344 $cat >try.c <<EOCP
345 #$i_inttypes I_INTTYPES
346 #ifdef I_INTTYPES
347 #include <inttypes.h>
348 #endif
349 #include <stdio.h>
350 int main() {
351 #ifdef INT8
352    int8_t i =  INT8_MAX;
353   uint8_t u = UINT8_MAX;
354   printf("int8_t\n");
355 #endif
356 #ifdef INT16
357    int16_t i =  INT16_MAX;
358   uint16_t u = UINT16_MAX;
359   printf("int16_t\n");
360 #endif
361 #ifdef INT32
362    int32_t i =  INT32_MAX;
363   uint32_t u = UINT32_MAX;
364   printf("int32_t\n");
365 #endif
366 }
367 EOCP
368
369 i8type="signed char"
370 u8type="unsigned char"
371 i8size=1
372 u8size=1
373
374 case "$i16type" in
375 '')     case "$shortsize" in
376         2)      i16type=short
377                 u16type="unsigned short"
378                 i16size=$shortsize
379                 u16size=$shortsize
380                 ;;
381         esac
382         ;;
383 esac
384 case "$i16type" in
385 '')     set try -DINT16
386         if eval $compile; then
387                 case "`$run ./try`" in
388                 int16_t)
389                         i16type=int16_t
390                         u16type=uint16_t
391                         i16size=2
392                         u16size=2
393                         ;;
394                 esac
395         fi
396         ;;
397 esac
398 case "$i16type" in
399 '')     if $test $shortsize -ge 2; then
400                 i16type=short
401                 u16type="unsigned short"
402                 i16size=$shortsize
403                 u16size=$shortsize
404         fi
405         ;;
406 esac
407
408 case "$i32type" in
409 '')     case "$longsize" in
410         4)      i32type=long
411                 u32type="unsigned long"
412                 i32size=$longsize
413                 u32size=$longsize
414                 ;;
415         *)      case "$intsize" in
416                 4)      i32type=int
417                         u32type="unsigned int"
418                         i32size=$intsize
419                         u32size=$intsize
420                         ;;
421                 esac
422                 ;;
423         esac
424         ;;
425 esac
426 case "$i32type" in
427 '')     set try -DINT32
428         if eval $compile; then
429                 case "`$run ./try`" in
430                 int32_t)
431                         i32type=int32_t
432                         u32type=uint32_t
433                         i32size=4
434                         u32size=4
435                         ;;
436                 esac
437         fi
438         ;;
439 esac
440 case "$i32type" in
441 '')     if $test $intsize -ge 4; then
442                 i32type=int
443                 u32type="unsigned int"
444                 i32size=$intsize
445                 u32size=$intsize
446         fi
447         ;;
448 esac
449
450 case "$i64type" in
451 '')     case "$d_quad:$quadtype" in
452         define:?*)
453                 i64type="$quadtype"
454                 u64type="$uquadtype"
455                 i64size=8
456                 u64size=8
457                 ;;
458         esac
459         ;;
460 esac
461
462 $echo "Checking how many bits of your UVs your NVs can preserve..." >&4
463 $cat <<EOP >try.c
464 #include <stdio.h>
465 #$i_stdlib I_STDLIB
466 #ifdef I_STDLIB
467 #include <stdlib.h>
468 #endif
469 #$i_inttypes I_INTTYPES
470 #ifdef I_INTTYPES
471 #include <inttypes.h>
472 #endif
473 #include <sys/types.h>
474 #include <signal.h>
475 #ifdef SIGFPE
476 /* volatile so that the compiler has to store it out to memory */
477 volatile int bletched = 0;
478 $signal_t blech(int s) { bletched = 1; }
479 #endif
480 int main() {
481     $uvtype u = 0;
482     $nvtype d;
483     int     n = 8 * $uvsize;
484     int     i;
485 #ifdef SIGFPE
486     signal(SIGFPE, blech);
487 #endif
488
489     for (i = 0; i < n; i++) {
490       u = u << 1 | ($uvtype)1;
491       d = ($nvtype)u;
492       if (($uvtype)d != u)
493         break;
494       if (d <= 0)
495         break;
496       d = ($nvtype)(u - 1);
497       if (($uvtype)d != (u - 1))
498         break;
499 #ifdef SIGFPE
500       if (bletched)
501         break;
502 #endif
503     }
504     printf("%d\n", ((i == n) ? -n : i));
505     exit(0);
506 }
507 EOP
508 set try
509
510 d_nv_preserves_uv="$undef"
511 if eval $compile; then
512         nv_preserves_uv_bits="`$run ./try`"
513 fi
514 case "$nv_preserves_uv_bits" in
515 \-[1-9]*)
516         nv_preserves_uv_bits=`expr 0 - $nv_preserves_uv_bits`
517         $echo "Your NVs can preserve all $nv_preserves_uv_bits bits of your UVs."  >&4
518         d_nv_preserves_uv="$define"
519         ;;
520 [1-9]*) $echo "Your NVs can preserve only $nv_preserves_uv_bits bits of your UVs."  >&4
521         d_nv_preserves_uv="$undef" ;;
522 *)      $echo "Can't figure out how many bits your NVs preserve." >&4
523         nv_preserves_uv_bits="0" ;;
524 esac
525 $rm_try
526
527 $echo "Checking to find the largest integer value your NVs can hold..." >&4
528 $cat <<EOP >try.c
529 #include <stdio.h>
530
531 typedef $nvtype NV;
532
533 int
534 main() {
535   NV value = 2;
536   int count = 1;
537
538   while(count < 256) {
539     /* volatile so that the compiler has to store it out to memory */
540     volatile NV up = value + 1.0;
541     volatile NV negated = -value;
542     volatile NV down = negated - 1.0;
543     volatile NV got_up = up - value;
544     int up_good = got_up == 1.0;
545     int got_down = down - negated;
546     int down_good = got_down == -1.0;
547
548     if (down_good != up_good) {
549       fprintf(stderr,
550               "Inconsistency - up %d %f; down %d %f; for 2**%d (%.20f)\n",
551               up_good, (double) got_up, down_good, (double) got_down,
552               count, (double) value);
553       return 1;
554     }
555     if (!up_good) {
556       while (1) {
557         if (count > 8) {
558           count -= 8;
559           fputs("256.0", stdout);
560         } else {
561           count--;
562           fputs("2.0", stdout);
563         }
564         if (!count) {
565           puts("");
566           return 0;
567         }
568         fputs("*", stdout);
569       }
570     }
571     value *= 2;
572     ++count;
573   }
574   fprintf(stderr, "Cannot overflow integer range, even at 2**%d (%.20f)\n",
575           count, (double) value);
576   return 1;
577 }
578 EOP
579 set try
580
581 nv_overflows_integers_at='0'
582 if eval $compile; then
583     xxx="`$run ./try`"
584     case "$?" in
585         0)
586             case "$xxx" in
587                 2*)  cat >&4 <<EOM
588 The largest integer your NVs can preserve is equal to $xxx
589 EOM
590                     nv_overflows_integers_at="$xxx"
591                     ;;
592                 *)  cat >&4 <<EOM
593 Cannot determine the largest integer value your NVs can hold, unexpected output
594 '$xxx'
595 EOM
596                     ;;
597             esac
598             ;;
599         *)  cat >&4 <<EOM
600 Cannot determine the largest integer value your NVs can hold
601 EOM
602             ;;
603     esac
604 fi
605 $rm_try
606
607 $echo "Checking whether NV 0.0 is all bits zero in memory..." >&4
608 $cat <<EOP >try.c
609 #include <stdio.h>
610 #$i_stdlib I_STDLIB
611 #ifdef I_STDLIB
612 #include <stdlib.h>
613 #endif
614 #include <string.h>
615 #include <sys/types.h>
616 #include <signal.h>
617 #ifdef SIGFPE
618 /* volatile so that the compiler has to store it out to memory */
619 volatile int bletched = 0;
620 $signal_t blech(int s) { bletched = 1; }
621 #endif
622
623 int checkit($nvtype d, const char *where) {
624     void *v = &d;
625     unsigned char *p = (unsigned char *)v;
626     unsigned char *end = p + sizeof(d);
627     int fail = 0;
628
629     while (p < end)
630         fail += *p++;
631
632     if (!fail)
633         return 0;
634
635     p = (unsigned char *)v;
636     printf("No - %s: 0x", where);
637     while (p < end)
638         printf ("%02X", *p++);
639     printf("\n");
640     return 1;
641 }
642
643 int main(int argc, char **argv) {
644     $nvtype d = 0.0;
645     int fail = 0;
646     fail += checkit(d, "0.0");
647
648     /* The compiler shouldn't be assuming that bletched is 0  */
649     d = bletched;
650
651     fail += checkit(d, "bleched");
652
653 #ifdef SIGFPE
654     signal(SIGFPE, blech);
655 #endif
656
657     /* Paranoia - the compiler should have no way of knowing that ANSI says
658        that argv[argc] will always be NULL.  Actually, if it did assume this it
659        would be buggy, as this is C and main() can be called from elsewhere in
660        the program.  */
661     d = argv[argc] ? 1 : 0;
662
663     if (d) {
664         printf("Odd argv[argc]=%p, d=%g\n", argv[argc], d);
665     }
666
667     fail += checkit(d, "ternary");
668
669     memset(&d, sizeof(d), argv[argc] ? 1 : 0);
670
671     if (d != 0.0) {
672         printf("No - memset doesn't give 0.0\n");
673         /* This might just blow up:  */
674         printf("(gives %g)\n", d);
675         return 1;
676     }
677
678 #ifdef SIGFPE
679     if (bletched) {
680         printf("No - something bleched\n");
681         return 1;
682     }
683 #endif
684     if (fail) {
685       printf("No - %d fail(s)\n", fail);
686       return 1;
687     }
688     printf("Yes\n");
689     return 0;
690 }
691 EOP
692 set try
693
694 d_nv_zero_is_allbits_zero="$undef"
695 if eval $compile; then
696     xxx="`$run ./try`"
697     case "$?" in
698         0)
699             case "$xxx" in
700                 Yes)  cat >&4 <<EOM
701 0.0 is represented as all bits zero in memory
702 EOM
703                     d_nv_zero_is_allbits_zero="$define"
704                     ;;
705                 *)  cat >&4 <<EOM
706 0.0 is not represented as all bits zero in memory
707 EOM
708                     d_nv_zero_is_allbits_zero="$undef"
709                     ;;
710             esac
711             ;;
712         *)  cat >&4 <<EOM
713 0.0 is not represented as all bits zero in memory
714 EOM
715             d_nv_zero_is_allbits_zero="$undef"
716             ;;
717     esac
718 fi
719 $rm_try
720