obstack-zprintf-posix: Add tests.
[gnulib.git] / m4 / host-cpu-c-abi.m4
blob60539302885017e9dfc6e614136bf6cfc7875616
1 # host-cpu-c-abi.m4
2 # serial 17
3 dnl Copyright (C) 2002-2024 Free Software Foundation, Inc.
4 dnl This file is free software; the Free Software Foundation
5 dnl gives unlimited permission to copy and/or distribute it,
6 dnl with or without modifications, as long as this notice is preserved.
8 dnl From Bruno Haible and Sam Steingold.
10 dnl Sets the HOST_CPU variable to the canonical name of the CPU.
11 dnl Sets the HOST_CPU_C_ABI variable to the canonical name of the CPU with its
12 dnl C language ABI (application binary interface).
13 dnl Also defines __${HOST_CPU}__ and __${HOST_CPU_C_ABI}__ as C macros in
14 dnl config.h.
15 dnl
16 dnl This canonical name can be used to select a particular assembly language
17 dnl source file that will interoperate with C code on the given host.
18 dnl
19 dnl For example:
20 dnl * 'i386' and 'sparc' are different canonical names, because code for i386
21 dnl   will not run on SPARC CPUs and vice versa. They have different
22 dnl   instruction sets.
23 dnl * 'sparc' and 'sparc64' are different canonical names, because code for
24 dnl   'sparc' and code for 'sparc64' cannot be linked together: 'sparc' code
25 dnl   contains 32-bit instructions, whereas 'sparc64' code contains 64-bit
26 dnl   instructions. A process on a SPARC CPU can be in 32-bit mode or in 64-bit
27 dnl   mode, but not both.
28 dnl * 'mips' and 'mipsn32' are different canonical names, because they use
29 dnl   different argument passing and return conventions for C functions, and
30 dnl   although the instruction set of 'mips' is a large subset of the
31 dnl   instruction set of 'mipsn32'.
32 dnl * 'mipsn32' and 'mips64' are different canonical names, because they use
33 dnl   different sizes for the C types like 'int' and 'void *', and although
34 dnl   the instruction sets of 'mipsn32' and 'mips64' are the same.
35 dnl * The same canonical name is used for different endiannesses. You can
36 dnl   determine the endianness through preprocessor symbols:
37 dnl   - 'arm': test __ARMEL__.
38 dnl   - 'mips', 'mipsn32', 'mips64': test _MIPSEB vs. _MIPSEL.
39 dnl   - 'powerpc64': test _BIG_ENDIAN vs. _LITTLE_ENDIAN.
40 dnl * The same name 'i386' is used for CPUs of type i386, i486, i586
41 dnl   (Pentium), AMD K7, Pentium II, Pentium IV, etc., because
42 dnl   - Instructions that do not exist on all of these CPUs (cmpxchg,
43 dnl     MMX, SSE, SSE2, 3DNow! etc.) are not frequently used. If your
44 dnl     assembly language source files use such instructions, you will
45 dnl     need to make the distinction.
46 dnl   - Speed of execution of the common instruction set is reasonable across
47 dnl     the entire family of CPUs. If you have assembly language source files
48 dnl     that are optimized for particular CPU types (like GNU gmp has), you
49 dnl     will need to make the distinction.
50 dnl   See <https://en.wikipedia.org/wiki/X86_instruction_listings>.
51 AC_DEFUN([gl_HOST_CPU_C_ABI],
53   AC_REQUIRE([AC_CANONICAL_HOST])
54   AC_REQUIRE([gl_C_ASM])
55   AC_CACHE_CHECK([host CPU and C ABI], [gl_cv_host_cpu_c_abi],
56     [case "$host_cpu" in
58 changequote(,)dnl
59        i[34567]86 )
60 changequote([,])dnl
61          gl_cv_host_cpu_c_abi=i386
62          ;;
64        x86_64 )
65          # On x86_64 systems, the C compiler may be generating code in one of
66          # these ABIs:
67          # - 64-bit instruction set, 64-bit pointers, 64-bit 'long': x86_64.
68          # - 64-bit instruction set, 64-bit pointers, 32-bit 'long': x86_64
69          #   with native Windows (mingw, MSVC).
70          # - 64-bit instruction set, 32-bit pointers, 32-bit 'long': x86_64-x32.
71          # - 32-bit instruction set, 32-bit pointers, 32-bit 'long': i386.
72          AC_COMPILE_IFELSE(
73            [AC_LANG_SOURCE(
74               [[#if (defined __x86_64__ || defined __amd64__ \
75                      || defined _M_X64 || defined _M_AMD64)
76                  int ok;
77                 #else
78                  error fail
79                 #endif
80               ]])],
81            [AC_COMPILE_IFELSE(
82               [AC_LANG_SOURCE(
83                  [[#if defined __ILP32__ || defined _ILP32
84                     int ok;
85                    #else
86                     error fail
87                    #endif
88                  ]])],
89               [gl_cv_host_cpu_c_abi=x86_64-x32],
90               [gl_cv_host_cpu_c_abi=x86_64])],
91            [gl_cv_host_cpu_c_abi=i386])
92          ;;
94 changequote(,)dnl
95        alphaev[4-8] | alphaev56 | alphapca5[67] | alphaev6[78] )
96 changequote([,])dnl
97          gl_cv_host_cpu_c_abi=alpha
98          ;;
100        arm* | aarch64 )
101          # Assume arm with EABI.
102          # On arm64 systems, the C compiler may be generating code in one of
103          # these ABIs:
104          # - aarch64 instruction set, 64-bit pointers, 64-bit 'long': arm64.
105          # - aarch64 instruction set, 32-bit pointers, 32-bit 'long': arm64-ilp32.
106          # - 32-bit instruction set, 32-bit pointers, 32-bit 'long': arm or armhf.
107          AC_COMPILE_IFELSE(
108            [AC_LANG_SOURCE(
109               [[#ifdef __aarch64__
110                  int ok;
111                 #else
112                  error fail
113                 #endif
114               ]])],
115            [AC_COMPILE_IFELSE(
116               [AC_LANG_SOURCE(
117                 [[#if defined __ILP32__ || defined _ILP32
118                    int ok;
119                   #else
120                    error fail
121                   #endif
122                 ]])],
123               [gl_cv_host_cpu_c_abi=arm64-ilp32],
124               [gl_cv_host_cpu_c_abi=arm64])],
125            [# Don't distinguish little-endian and big-endian arm, since they
126             # don't require different machine code for simple operations and
127             # since the user can distinguish them through the preprocessor
128             # defines __ARMEL__ vs. __ARMEB__.
129             # But distinguish arm which passes floating-point arguments and
130             # return values in integer registers (r0, r1, ...) - this is
131             # gcc -mfloat-abi=soft or gcc -mfloat-abi=softfp - from arm which
132             # passes them in float registers (s0, s1, ...) and double registers
133             # (d0, d1, ...) - this is gcc -mfloat-abi=hard. GCC 4.6 or newer
134             # sets the preprocessor defines __ARM_PCS (for the first case) and
135             # __ARM_PCS_VFP (for the second case), but older GCC does not.
136             echo 'double ddd; void func (double dd) { ddd = dd; }' > conftest.c
137             # Look for a reference to the register d0 in the .s file.
138             AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $gl_c_asm_opt conftest.c) >/dev/null 2>&1
139             if LC_ALL=C grep 'd0,' conftest.$gl_asmext >/dev/null; then
140               gl_cv_host_cpu_c_abi=armhf
141             else
142               gl_cv_host_cpu_c_abi=arm
143             fi
144             rm -f conftest*
145            ])
146          ;;
148        hppa1.0 | hppa1.1 | hppa2.0* | hppa64 )
149          # On hppa, the C compiler may be generating 32-bit code or 64-bit
150          # code. In the latter case, it defines _LP64 and __LP64__.
151          AC_COMPILE_IFELSE(
152            [AC_LANG_SOURCE(
153               [[#ifdef __LP64__
154                  int ok;
155                 #else
156                  error fail
157                 #endif
158               ]])],
159            [gl_cv_host_cpu_c_abi=hppa64],
160            [gl_cv_host_cpu_c_abi=hppa])
161          ;;
163        ia64* )
164          # On ia64 on HP-UX, the C compiler may be generating 64-bit code or
165          # 32-bit code. In the latter case, it defines _ILP32.
166          AC_COMPILE_IFELSE(
167            [AC_LANG_SOURCE(
168               [[#ifdef _ILP32
169                  int ok;
170                 #else
171                  error fail
172                 #endif
173               ]])],
174            [gl_cv_host_cpu_c_abi=ia64-ilp32],
175            [gl_cv_host_cpu_c_abi=ia64])
176          ;;
178        mips* )
179          # We should also check for (_MIPS_SZPTR == 64), but gcc keeps this
180          # at 32.
181          AC_COMPILE_IFELSE(
182            [AC_LANG_SOURCE(
183               [[#if defined _MIPS_SZLONG && (_MIPS_SZLONG == 64)
184                  int ok;
185                 #else
186                  error fail
187                 #endif
188               ]])],
189            [gl_cv_host_cpu_c_abi=mips64],
190            [# In the n32 ABI, _ABIN32 is defined, _ABIO32 is not defined (but
191             # may later get defined by <sgidefs.h>), and _MIPS_SIM == _ABIN32.
192             # In the 32 ABI, _ABIO32 is defined, _ABIN32 is not defined (but
193             # may later get defined by <sgidefs.h>), and _MIPS_SIM == _ABIO32.
194             AC_COMPILE_IFELSE(
195               [AC_LANG_SOURCE(
196                  [[#if (_MIPS_SIM == _ABIN32)
197                     int ok;
198                    #else
199                     error fail
200                    #endif
201                  ]])],
202               [gl_cv_host_cpu_c_abi=mipsn32],
203               [gl_cv_host_cpu_c_abi=mips])])
204          ;;
206        powerpc* )
207          # Different ABIs are in use on AIX vs. Mac OS X vs. Linux,*BSD.
208          # No need to distinguish them here; the caller may distinguish
209          # them based on the OS.
210          # On powerpc64 systems, the C compiler may still be generating
211          # 32-bit code. And on powerpc-ibm-aix systems, the C compiler may
212          # be generating 64-bit code.
213          AC_COMPILE_IFELSE(
214            [AC_LANG_SOURCE(
215               [[#if defined __powerpc64__ || defined __LP64__
216                  int ok;
217                 #else
218                  error fail
219                 #endif
220               ]])],
221            [# On powerpc64, there are two ABIs on Linux: The AIX compatible
222             # one and the ELFv2 one. The latter defines _CALL_ELF=2.
223             AC_COMPILE_IFELSE(
224               [AC_LANG_SOURCE(
225                  [[#if defined _CALL_ELF && _CALL_ELF == 2
226                     int ok;
227                    #else
228                     error fail
229                    #endif
230                  ]])],
231               [gl_cv_host_cpu_c_abi=powerpc64-elfv2],
232               [gl_cv_host_cpu_c_abi=powerpc64])
233            ],
234            [gl_cv_host_cpu_c_abi=powerpc])
235          ;;
237        rs6000 )
238          gl_cv_host_cpu_c_abi=powerpc
239          ;;
241        riscv32 | riscv64 )
242          # There are 2 architectures (with variants): rv32* and rv64*.
243          AC_COMPILE_IFELSE(
244            [AC_LANG_SOURCE(
245               [[#if __riscv_xlen == 64
246                   int ok;
247                 #else
248                   error fail
249                 #endif
250               ]])],
251            [cpu=riscv64],
252            [cpu=riscv32])
253          # There are 6 ABIs: ilp32, ilp32f, ilp32d, lp64, lp64f, lp64d.
254          # Size of 'long' and 'void *':
255          AC_COMPILE_IFELSE(
256            [AC_LANG_SOURCE(
257               [[#if defined __LP64__
258                   int ok;
259                 #else
260                   error fail
261                 #endif
262               ]])],
263            [main_abi=lp64],
264            [main_abi=ilp32])
265          # Float ABIs:
266          # __riscv_float_abi_double:
267          #   'float' and 'double' are passed in floating-point registers.
268          # __riscv_float_abi_single:
269          #   'float' are passed in floating-point registers.
270          # __riscv_float_abi_soft:
271          #   No values are passed in floating-point registers.
272          AC_COMPILE_IFELSE(
273            [AC_LANG_SOURCE(
274               [[#if defined __riscv_float_abi_double
275                   int ok;
276                 #else
277                   error fail
278                 #endif
279               ]])],
280            [float_abi=d],
281            [AC_COMPILE_IFELSE(
282               [AC_LANG_SOURCE(
283                  [[#if defined __riscv_float_abi_single
284                      int ok;
285                    #else
286                      error fail
287                    #endif
288                  ]])],
289               [float_abi=f],
290               [float_abi=''])
291            ])
292          gl_cv_host_cpu_c_abi="${cpu}-${main_abi}${float_abi}"
293          ;;
295        s390* )
296          # On s390x, the C compiler may be generating 64-bit (= s390x) code
297          # or 31-bit (= s390) code.
298          AC_COMPILE_IFELSE(
299            [AC_LANG_SOURCE(
300               [[#if defined __LP64__ || defined __s390x__
301                   int ok;
302                 #else
303                   error fail
304                 #endif
305               ]])],
306            [gl_cv_host_cpu_c_abi=s390x],
307            [gl_cv_host_cpu_c_abi=s390])
308          ;;
310        sparc | sparc64 )
311          # UltraSPARCs running Linux have `uname -m` = "sparc64", but the
312          # C compiler still generates 32-bit code.
313          AC_COMPILE_IFELSE(
314            [AC_LANG_SOURCE(
315               [[#if defined __sparcv9 || defined __arch64__
316                  int ok;
317                 #else
318                  error fail
319                 #endif
320               ]])],
321            [gl_cv_host_cpu_c_abi=sparc64],
322            [gl_cv_host_cpu_c_abi=sparc])
323          ;;
325        *)
326          gl_cv_host_cpu_c_abi="$host_cpu"
327          ;;
328      esac
329     ])
331   dnl In most cases, $HOST_CPU and $HOST_CPU_C_ABI are the same.
332   HOST_CPU=`echo "$gl_cv_host_cpu_c_abi" | sed -e 's/-.*//'`
333   HOST_CPU_C_ABI="$gl_cv_host_cpu_c_abi"
334   AC_SUBST([HOST_CPU])
335   AC_SUBST([HOST_CPU_C_ABI])
337   # This was
338   #   AC_DEFINE_UNQUOTED([__${HOST_CPU}__])
339   #   AC_DEFINE_UNQUOTED([__${HOST_CPU_C_ABI}__])
340   # earlier, but KAI C++ 3.2d doesn't like this.
341   sed -e 's/-/_/g' >> confdefs.h <<EOF
342 #ifndef __${HOST_CPU}__
343 #define __${HOST_CPU}__ 1
344 #endif
345 #ifndef __${HOST_CPU_C_ABI}__
346 #define __${HOST_CPU_C_ABI}__ 1
347 #endif
349   AH_TOP([/* CPU and C ABI indicator */
350 #ifndef __i386__
351 #undef __i386__
352 #endif
353 #ifndef __x86_64_x32__
354 #undef __x86_64_x32__
355 #endif
356 #ifndef __x86_64__
357 #undef __x86_64__
358 #endif
359 #ifndef __alpha__
360 #undef __alpha__
361 #endif
362 #ifndef __arm__
363 #undef __arm__
364 #endif
365 #ifndef __armhf__
366 #undef __armhf__
367 #endif
368 #ifndef __arm64_ilp32__
369 #undef __arm64_ilp32__
370 #endif
371 #ifndef __arm64__
372 #undef __arm64__
373 #endif
374 #ifndef __hppa__
375 #undef __hppa__
376 #endif
377 #ifndef __hppa64__
378 #undef __hppa64__
379 #endif
380 #ifndef __ia64_ilp32__
381 #undef __ia64_ilp32__
382 #endif
383 #ifndef __ia64__
384 #undef __ia64__
385 #endif
386 #ifndef __loongarch64__
387 #undef __loongarch64__
388 #endif
389 #ifndef __m68k__
390 #undef __m68k__
391 #endif
392 #ifndef __mips__
393 #undef __mips__
394 #endif
395 #ifndef __mipsn32__
396 #undef __mipsn32__
397 #endif
398 #ifndef __mips64__
399 #undef __mips64__
400 #endif
401 #ifndef __powerpc__
402 #undef __powerpc__
403 #endif
404 #ifndef __powerpc64__
405 #undef __powerpc64__
406 #endif
407 #ifndef __powerpc64_elfv2__
408 #undef __powerpc64_elfv2__
409 #endif
410 #ifndef __riscv32__
411 #undef __riscv32__
412 #endif
413 #ifndef __riscv64__
414 #undef __riscv64__
415 #endif
416 #ifndef __riscv32_ilp32__
417 #undef __riscv32_ilp32__
418 #endif
419 #ifndef __riscv32_ilp32f__
420 #undef __riscv32_ilp32f__
421 #endif
422 #ifndef __riscv32_ilp32d__
423 #undef __riscv32_ilp32d__
424 #endif
425 #ifndef __riscv64_ilp32__
426 #undef __riscv64_ilp32__
427 #endif
428 #ifndef __riscv64_ilp32f__
429 #undef __riscv64_ilp32f__
430 #endif
431 #ifndef __riscv64_ilp32d__
432 #undef __riscv64_ilp32d__
433 #endif
434 #ifndef __riscv64_lp64__
435 #undef __riscv64_lp64__
436 #endif
437 #ifndef __riscv64_lp64f__
438 #undef __riscv64_lp64f__
439 #endif
440 #ifndef __riscv64_lp64d__
441 #undef __riscv64_lp64d__
442 #endif
443 #ifndef __s390__
444 #undef __s390__
445 #endif
446 #ifndef __s390x__
447 #undef __s390x__
448 #endif
449 #ifndef __sh__
450 #undef __sh__
451 #endif
452 #ifndef __sparc__
453 #undef __sparc__
454 #endif
455 #ifndef __sparc64__
456 #undef __sparc64__
457 #endif
463 dnl Sets the HOST_CPU_C_ABI_32BIT variable to 'yes' if the C language ABI
464 dnl (application binary interface) is a 32-bit one, to 'no' if it is a 64-bit
465 dnl one.
466 dnl This is a simplified variant of gl_HOST_CPU_C_ABI.
467 AC_DEFUN([gl_HOST_CPU_C_ABI_32BIT],
469   AC_REQUIRE([AC_CANONICAL_HOST])
470   AC_CACHE_CHECK([32-bit host C ABI], [gl_cv_host_cpu_c_abi_32bit],
471     [case "$host_cpu" in
473        # CPUs that only support a 32-bit ABI.
474        arc \
475        | bfin \
476        | cris* \
477        | csky \
478        | epiphany \
479        | ft32 \
480        | h8300 \
481        | m68k \
482        | microblaze | microblazeel \
483        | nds32 | nds32le | nds32be \
484        | nios2 | nios2eb | nios2el \
485        | or1k* \
486        | or32 \
487        | sh | sh[1234] | sh[1234]e[lb] \
488        | tic6x \
489        | xtensa* )
490          gl_cv_host_cpu_c_abi_32bit=yes
491          ;;
493        # CPUs that only support a 64-bit ABI.
494 changequote(,)dnl
495        alpha | alphaev[4-8] | alphaev56 | alphapca5[67] | alphaev6[78] \
496        | mmix )
497 changequote([,])dnl
498          gl_cv_host_cpu_c_abi_32bit=no
499          ;;
501        *)
502          if test -n "$gl_cv_host_cpu_c_abi"; then
503            dnl gl_HOST_CPU_C_ABI has already been run. Use its result.
504            case "$gl_cv_host_cpu_c_abi" in
505              i386 | x86_64-x32 | arm | armhf | arm64-ilp32 | hppa | ia64-ilp32 | mips | mipsn32 | powerpc | riscv*-ilp32* | s390 | sparc)
506                gl_cv_host_cpu_c_abi_32bit=yes ;;
507              x86_64 | alpha | arm64 | aarch64c | hppa64 | ia64 | mips64 | powerpc64 | powerpc64-elfv2 | riscv*-lp64* | s390x | sparc64 )
508                gl_cv_host_cpu_c_abi_32bit=no ;;
509              *)
510                gl_cv_host_cpu_c_abi_32bit=unknown ;;
511            esac
512          else
513            gl_cv_host_cpu_c_abi_32bit=unknown
514          fi
515          if test $gl_cv_host_cpu_c_abi_32bit = unknown; then
516            AC_COMPILE_IFELSE(
517              [AC_LANG_SOURCE(
518                 [[int test_pointer_size[sizeof (void *) - 5];
519                 ]])],
520              [gl_cv_host_cpu_c_abi_32bit=no],
521              [gl_cv_host_cpu_c_abi_32bit=yes])
522          fi
523          ;;
524      esac
525     ])
527   HOST_CPU_C_ABI_32BIT="$gl_cv_host_cpu_c_abi_32bit"