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