libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

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 ])