1# Macros to detect C compiler features
2# config/c-compiler.m4
3
4
5# PGAC_C_SIGNED
6# -------------
7# Check if the C compiler understands signed types.
8AC_DEFUN([PGAC_C_SIGNED],
9[AC_CACHE_CHECK(for signed types, pgac_cv_c_signed,
10[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
11[signed char c; signed short s; signed int i;])],
12[pgac_cv_c_signed=yes],
13[pgac_cv_c_signed=no])])
14if test x"$pgac_cv_c_signed" = xno ; then
15  AC_DEFINE(signed,, [Define to empty if the C compiler does not understand signed types.])
16fi])# PGAC_C_SIGNED
17
18
19
20# PGAC_C_PRINTF_ARCHETYPE
21# -----------------------
22# Select the format archetype to be used by gcc to check printf-type functions.
23# We prefer "gnu_printf", as that most closely matches the features supported
24# by src/port/snprintf.c (particularly the %m conversion spec).  However,
25# on some NetBSD versions, that doesn't work while "__syslog__" does.
26# If all else fails, use "printf".
27AC_DEFUN([PGAC_PRINTF_ARCHETYPE],
28[AC_CACHE_CHECK([for printf format archetype], pgac_cv_printf_archetype,
29[pgac_cv_printf_archetype=gnu_printf
30PGAC_TEST_PRINTF_ARCHETYPE
31if [[ "$ac_archetype_ok" = no ]]; then
32  pgac_cv_printf_archetype=__syslog__
33  PGAC_TEST_PRINTF_ARCHETYPE
34  if [[ "$ac_archetype_ok" = no ]]; then
35    pgac_cv_printf_archetype=printf
36  fi
37fi])
38AC_DEFINE_UNQUOTED([PG_PRINTF_ATTRIBUTE], [$pgac_cv_printf_archetype],
39[Define to best printf format archetype, usually gnu_printf if available.])
40])# PGAC_PRINTF_ARCHETYPE
41
42# Subroutine: test $pgac_cv_printf_archetype, set $ac_archetype_ok to yes or no
43AC_DEFUN([PGAC_TEST_PRINTF_ARCHETYPE],
44[ac_save_c_werror_flag=$ac_c_werror_flag
45ac_c_werror_flag=yes
46AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
47[extern void pgac_write(int ignore, const char *fmt,...)
48__attribute__((format($pgac_cv_printf_archetype, 2, 3)));],
49[pgac_write(0, "error %s: %m", "foo");])],
50                  [ac_archetype_ok=yes],
51                  [ac_archetype_ok=no])
52ac_c_werror_flag=$ac_save_c_werror_flag
53])# PGAC_TEST_PRINTF_ARCHETYPE
54
55
56# PGAC_TYPE_64BIT_INT(TYPE)
57# -------------------------
58# Check if TYPE is a working 64 bit integer type. Set HAVE_TYPE_64 to
59# yes or no respectively, and define HAVE_TYPE_64 if yes.
60AC_DEFUN([PGAC_TYPE_64BIT_INT],
61[define([Ac_define], [translit([have_$1_64], [a-z *], [A-Z_P])])dnl
62define([Ac_cachevar], [translit([pgac_cv_type_$1_64], [ *], [_p])])dnl
63AC_CACHE_CHECK([whether $1 is 64 bits], [Ac_cachevar],
64[AC_RUN_IFELSE([AC_LANG_SOURCE(
65[typedef $1 ac_int64;
66
67/*
68 * These are globals to discourage the compiler from folding all the
69 * arithmetic tests down to compile-time constants.
70 */
71ac_int64 a = 20000001;
72ac_int64 b = 40000005;
73
74int does_int64_work()
75{
76  ac_int64 c,d;
77
78  if (sizeof(ac_int64) != 8)
79    return 0;			/* definitely not the right size */
80
81  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
82  c = a * b;
83  d = (c + b) / b;
84  if (d != a+1)
85    return 0;
86  return 1;
87}
88
89int
90main() {
91  return (! does_int64_work());
92}])],
93[Ac_cachevar=yes],
94[Ac_cachevar=no],
95[# If cross-compiling, check the size reported by the compiler and
96# trust that the arithmetic works.
97AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([], [sizeof($1) == 8])],
98                  Ac_cachevar=yes,
99                  Ac_cachevar=no)])])
100
101Ac_define=$Ac_cachevar
102if test x"$Ac_cachevar" = xyes ; then
103  AC_DEFINE(Ac_define, 1, [Define to 1 if `]$1[' works and is 64 bits.])
104fi
105undefine([Ac_define])dnl
106undefine([Ac_cachevar])dnl
107])# PGAC_TYPE_64BIT_INT
108
109
110# PGAC_TYPE_128BIT_INT
111# ---------------------
112# Check if __int128 is a working 128 bit integer type, and if so
113# define PG_INT128_TYPE to that typename, and define ALIGNOF_PG_INT128_TYPE
114# as its alignment requirement.
115#
116# This currently only detects a GCC/clang extension, but support for other
117# environments may be added in the future.
118#
119# For the moment we only test for support for 128bit math; support for
120# 128bit literals and snprintf is not required.
121AC_DEFUN([PGAC_TYPE_128BIT_INT],
122[AC_CACHE_CHECK([for __int128], [pgac_cv__128bit_int],
123[AC_LINK_IFELSE([AC_LANG_PROGRAM([
124/*
125 * We don't actually run this test, just link it to verify that any support
126 * functions needed for __int128 are present.
127 *
128 * These are globals to discourage the compiler from folding all the
129 * arithmetic tests down to compile-time constants.  We do not have
130 * convenient support for 128bit literals at this point...
131 */
132__int128 a = 48828125;
133__int128 b = 97656250;
134],[
135__int128 c,d;
136a = (a << 12) + 1; /* 200000000001 */
137b = (b << 12) + 5; /* 400000000005 */
138/* try the most relevant arithmetic ops */
139c = a * b;
140d = (c + b) / b;
141/* must use the results, else compiler may optimize arithmetic away */
142if (d != a+1)
143  return 1;
144])],
145[pgac_cv__128bit_int=yes],
146[pgac_cv__128bit_int=no])])
147if test x"$pgac_cv__128bit_int" = xyes ; then
148  # Use of non-default alignment with __int128 tickles bugs in some compilers.
149  # If not cross-compiling, we can test for bugs and disable use of __int128
150  # with buggy compilers.  If cross-compiling, hope for the best.
151  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83925
152  AC_CACHE_CHECK([for __int128 alignment bug], [pgac_cv__128bit_int_bug],
153  [AC_RUN_IFELSE([AC_LANG_PROGRAM([
154/* This must match the corresponding code in c.h: */
155#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
156#define pg_attribute_aligned(a) __attribute__((aligned(a)))
157#endif
158typedef __int128 int128a
159#if defined(pg_attribute_aligned)
160pg_attribute_aligned(8)
161#endif
162;
163int128a holder;
164void pass_by_val(void *buffer, int128a par) { holder = par; }
165],[
166long int i64 = 97656225L << 12;
167int128a q;
168pass_by_val(main, (int128a) i64);
169q = (int128a) i64;
170if (q != holder)
171  return 1;
172])],
173  [pgac_cv__128bit_int_bug=ok],
174  [pgac_cv__128bit_int_bug=broken],
175  [pgac_cv__128bit_int_bug="assuming ok"])])
176  if test x"$pgac_cv__128bit_int_bug" != xbroken ; then
177    AC_DEFINE(PG_INT128_TYPE, __int128, [Define to the name of a signed 128-bit integer type.])
178    AC_CHECK_ALIGNOF(PG_INT128_TYPE)
179  fi
180fi])# PGAC_TYPE_128BIT_INT
181
182
183# PGAC_C_FUNCNAME_SUPPORT
184# -----------------------
185# Check if the C compiler understands __func__ (C99) or __FUNCTION__ (gcc).
186# Define HAVE_FUNCNAME__FUNC or HAVE_FUNCNAME__FUNCTION accordingly.
187AC_DEFUN([PGAC_C_FUNCNAME_SUPPORT],
188[AC_CACHE_CHECK(for __func__, pgac_cv_funcname_func_support,
189[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <stdio.h>],
190[printf("%s\n", __func__);])],
191[pgac_cv_funcname_func_support=yes],
192[pgac_cv_funcname_func_support=no])])
193if test x"$pgac_cv_funcname_func_support" = xyes ; then
194AC_DEFINE(HAVE_FUNCNAME__FUNC, 1,
195          [Define to 1 if your compiler understands __func__.])
196else
197AC_CACHE_CHECK(for __FUNCTION__, pgac_cv_funcname_function_support,
198[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <stdio.h>],
199[printf("%s\n", __FUNCTION__);])],
200[pgac_cv_funcname_function_support=yes],
201[pgac_cv_funcname_function_support=no])])
202if test x"$pgac_cv_funcname_function_support" = xyes ; then
203AC_DEFINE(HAVE_FUNCNAME__FUNCTION, 1,
204          [Define to 1 if your compiler understands __FUNCTION__.])
205fi
206fi])# PGAC_C_FUNCNAME_SUPPORT
207
208
209
210# PGAC_C_STATIC_ASSERT
211# --------------------
212# Check if the C compiler understands _Static_assert(),
213# and define HAVE__STATIC_ASSERT if so.
214#
215# We actually check the syntax ({ _Static_assert(...) }), because we need
216# gcc-style compound expressions to be able to wrap the thing into macros.
217AC_DEFUN([PGAC_C_STATIC_ASSERT],
218[AC_CACHE_CHECK(for _Static_assert, pgac_cv__static_assert,
219[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
220[({ _Static_assert(1, "foo"); })])],
221[pgac_cv__static_assert=yes],
222[pgac_cv__static_assert=no])])
223if test x"$pgac_cv__static_assert" = xyes ; then
224AC_DEFINE(HAVE__STATIC_ASSERT, 1,
225          [Define to 1 if your compiler understands _Static_assert.])
226fi])# PGAC_C_STATIC_ASSERT
227
228
229
230# PGAC_C_TYPEOF
231# -------------
232# Check if the C compiler understands typeof or a variant.  Define
233# HAVE_TYPEOF if so, and define 'typeof' to the actual key word.
234#
235AC_DEFUN([PGAC_C_TYPEOF],
236[AC_CACHE_CHECK(for typeof, pgac_cv_c_typeof,
237[pgac_cv_c_typeof=no
238for pgac_kw in typeof __typeof__ decltype; do
239  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
240[int x = 0;
241$pgac_kw(x) y;
242y = x;
243return y;])],
244[pgac_cv_c_typeof=$pgac_kw])
245  test "$pgac_cv_c_typeof" != no && break
246done])
247if test "$pgac_cv_c_typeof" != no; then
248  AC_DEFINE(HAVE_TYPEOF, 1,
249            [Define to 1 if your compiler understands `typeof' or something similar.])
250  if test "$pgac_cv_c_typeof" != typeof; then
251    AC_DEFINE_UNQUOTED(typeof, $pgac_cv_c_typeof, [Define to how the compiler spells `typeof'.])
252  fi
253fi])# PGAC_C_TYPEOF
254
255
256
257# PGAC_C_TYPES_COMPATIBLE
258# -----------------------
259# Check if the C compiler understands __builtin_types_compatible_p,
260# and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so.
261#
262# We check usage with __typeof__, though it's unlikely any compiler would
263# have the former and not the latter.
264AC_DEFUN([PGAC_C_TYPES_COMPATIBLE],
265[AC_CACHE_CHECK(for __builtin_types_compatible_p, pgac_cv__types_compatible,
266[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
267[[ int x; static int y[__builtin_types_compatible_p(__typeof__(x), int)]; ]])],
268[pgac_cv__types_compatible=yes],
269[pgac_cv__types_compatible=no])])
270if test x"$pgac_cv__types_compatible" = xyes ; then
271AC_DEFINE(HAVE__BUILTIN_TYPES_COMPATIBLE_P, 1,
272          [Define to 1 if your compiler understands __builtin_types_compatible_p.])
273fi])# PGAC_C_TYPES_COMPATIBLE
274
275
276# PGAC_C_BUILTIN_CONSTANT_P
277# -------------------------
278# Check if the C compiler understands __builtin_constant_p(),
279# and define HAVE__BUILTIN_CONSTANT_P if so.
280# We need __builtin_constant_p("string literal") to be true, but some older
281# compilers don't think that, so test for that case explicitly.
282AC_DEFUN([PGAC_C_BUILTIN_CONSTANT_P],
283[AC_CACHE_CHECK(for __builtin_constant_p, pgac_cv__builtin_constant_p,
284[AC_COMPILE_IFELSE([AC_LANG_SOURCE(
285[[static int x;
286  static int y[__builtin_constant_p(x) ? x : 1];
287  static int z[__builtin_constant_p("string literal") ? 1 : x];
288]]
289)],
290[pgac_cv__builtin_constant_p=yes],
291[pgac_cv__builtin_constant_p=no])])
292if test x"$pgac_cv__builtin_constant_p" = xyes ; then
293AC_DEFINE(HAVE__BUILTIN_CONSTANT_P, 1,
294          [Define to 1 if your compiler understands __builtin_constant_p.])
295fi])# PGAC_C_BUILTIN_CONSTANT_P
296
297
298
299# PGAC_C_BUILTIN_OP_OVERFLOW
300# -------------------------
301# Check if the C compiler understands __builtin_$op_overflow(),
302# and define HAVE__BUILTIN_OP_OVERFLOW if so.
303#
304# Check for the most complicated case, 64 bit multiplication, as a
305# proxy for all of the operations.  To detect the case where the compiler
306# knows the function but library support is missing, we must link not just
307# compile, and store the results in global variables so the compiler doesn't
308# optimize away the call.
309AC_DEFUN([PGAC_C_BUILTIN_OP_OVERFLOW],
310[AC_CACHE_CHECK(for __builtin_mul_overflow, pgac_cv__builtin_op_overflow,
311[AC_LINK_IFELSE([AC_LANG_PROGRAM([
312PG_INT64_TYPE a = 1;
313PG_INT64_TYPE b = 1;
314PG_INT64_TYPE result;
315int oflo;
316],
317[oflo = __builtin_mul_overflow(a, b, &result);])],
318[pgac_cv__builtin_op_overflow=yes],
319[pgac_cv__builtin_op_overflow=no])])
320if test x"$pgac_cv__builtin_op_overflow" = xyes ; then
321AC_DEFINE(HAVE__BUILTIN_OP_OVERFLOW, 1,
322          [Define to 1 if your compiler understands __builtin_$op_overflow.])
323fi])# PGAC_C_BUILTIN_OP_OVERFLOW
324
325
326
327# PGAC_C_BUILTIN_UNREACHABLE
328# --------------------------
329# Check if the C compiler understands __builtin_unreachable(),
330# and define HAVE__BUILTIN_UNREACHABLE if so.
331#
332# NB: Don't get the idea of putting a for(;;); or such before the
333# __builtin_unreachable() call.  Some compilers would remove it before linking
334# and only a warning instead of an error would be produced.
335AC_DEFUN([PGAC_C_BUILTIN_UNREACHABLE],
336[AC_CACHE_CHECK(for __builtin_unreachable, pgac_cv__builtin_unreachable,
337[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
338[__builtin_unreachable();])],
339[pgac_cv__builtin_unreachable=yes],
340[pgac_cv__builtin_unreachable=no])])
341if test x"$pgac_cv__builtin_unreachable" = xyes ; then
342AC_DEFINE(HAVE__BUILTIN_UNREACHABLE, 1,
343          [Define to 1 if your compiler understands __builtin_unreachable.])
344fi])# PGAC_C_BUILTIN_UNREACHABLE
345
346
347
348# PGAC_C_COMPUTED_GOTO
349# -----------------------
350# Check if the C compiler knows computed gotos (gcc extension, also
351# available in at least clang).  If so, define HAVE_COMPUTED_GOTO.
352#
353# Checking whether computed gotos are supported syntax-wise ought to
354# be enough, as the syntax is otherwise illegal.
355AC_DEFUN([PGAC_C_COMPUTED_GOTO],
356[AC_CACHE_CHECK(for computed goto support, pgac_cv_computed_goto,
357[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
358[[void *labeladdrs[] = {&&my_label};
359  goto *labeladdrs[0];
360  my_label:
361  return 1;
362]])],
363[pgac_cv_computed_goto=yes],
364[pgac_cv_computed_goto=no])])
365if test x"$pgac_cv_computed_goto" = xyes ; then
366AC_DEFINE(HAVE_COMPUTED_GOTO, 1,
367          [Define to 1 if your compiler handles computed gotos.])
368fi])# PGAC_C_COMPUTED_GOTO
369
370
371
372# PGAC_CHECK_BUILTIN_FUNC
373# -----------------------
374# This is similar to AC_CHECK_FUNCS(), except that it will work for compiler
375# builtin functions, as that usually fails to.
376# The first argument is the function name, eg [__builtin_clzl], and the
377# second is its argument list, eg [unsigned long x].  The current coding
378# works only for a single argument named x; we might generalize that later.
379# It's assumed that the function's result type is coercible to int.
380# On success, we define "HAVEfuncname" (there's usually more than enough
381# underscores already, so we don't add another one).
382AC_DEFUN([PGAC_CHECK_BUILTIN_FUNC],
383[AC_CACHE_CHECK(for $1, pgac_cv$1,
384[AC_LINK_IFELSE([AC_LANG_PROGRAM([
385int
386call$1($2)
387{
388    return $1(x);
389}], [])],
390[pgac_cv$1=yes],
391[pgac_cv$1=no])])
392if test x"${pgac_cv$1}" = xyes ; then
393AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE$1]), 1,
394                   [Define to 1 if your compiler understands $1.])
395fi])# PGAC_CHECK_BUILTIN_FUNC
396
397
398
399# PGAC_PROG_VARCC_VARFLAGS_OPT
400# -----------------------
401# Given a compiler, variable name and a string, check if the compiler
402# supports the string as a command-line option. If it does, add the
403# string to the given variable.
404AC_DEFUN([PGAC_PROG_VARCC_VARFLAGS_OPT],
405[define([Ac_cachevar], [AS_TR_SH([pgac_cv_prog_$1_cflags_$3])])dnl
406AC_CACHE_CHECK([whether ${$1} supports $3, for $2], [Ac_cachevar],
407[pgac_save_CFLAGS=$CFLAGS
408pgac_save_CC=$CC
409CC=${$1}
410CFLAGS="${$2} $3"
411ac_save_c_werror_flag=$ac_c_werror_flag
412ac_c_werror_flag=yes
413_AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
414                   [Ac_cachevar=yes],
415                   [Ac_cachevar=no])
416ac_c_werror_flag=$ac_save_c_werror_flag
417CFLAGS="$pgac_save_CFLAGS"
418CC="$pgac_save_CC"])
419if test x"$Ac_cachevar" = x"yes"; then
420  $2="${$2} $3"
421fi
422undefine([Ac_cachevar])dnl
423])# PGAC_PROG_VARCC_VARFLAGS_OPT
424
425
426
427# PGAC_PROG_CC_CFLAGS_OPT
428# -----------------------
429# Given a string, check if the compiler supports the string as a
430# command-line option. If it does, add the string to CFLAGS.
431AC_DEFUN([PGAC_PROG_CC_CFLAGS_OPT], [
432PGAC_PROG_VARCC_VARFLAGS_OPT(CC, CFLAGS, $1)
433])# PGAC_PROG_CC_CFLAGS_OPT
434
435
436
437# PGAC_PROG_CC_VAR_OPT
438# -----------------------
439# Given a variable name and a string, check if the compiler supports
440# the string as a command-line option. If it does, add the string to
441# the given variable.
442AC_DEFUN([PGAC_PROG_CC_VAR_OPT],
443[PGAC_PROG_VARCC_VARFLAGS_OPT(CC, $1, $2)
444])# PGAC_PROG_CC_VAR_OPT
445
446
447
448# PGAC_PROG_VARCXX_VARFLAGS_OPT
449# -----------------------
450# Given a compiler, variable name and a string, check if the compiler
451# supports the string as a command-line option. If it does, add the
452# string to the given variable.
453AC_DEFUN([PGAC_PROG_VARCXX_VARFLAGS_OPT],
454[define([Ac_cachevar], [AS_TR_SH([pgac_cv_prog_$1_cxxflags_$3])])dnl
455AC_CACHE_CHECK([whether ${$1} supports $3, for $2], [Ac_cachevar],
456[pgac_save_CXXFLAGS=$CXXFLAGS
457pgac_save_CXX=$CXX
458CXX=${$1}
459CXXFLAGS="${$2} $3"
460ac_save_cxx_werror_flag=$ac_cxx_werror_flag
461ac_cxx_werror_flag=yes
462AC_LANG_PUSH(C++)
463_AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
464                   [Ac_cachevar=yes],
465                   [Ac_cachevar=no])
466AC_LANG_POP([])
467ac_cxx_werror_flag=$ac_save_cxx_werror_flag
468CXXFLAGS="$pgac_save_CXXFLAGS"
469CXX="$pgac_save_CXX"])
470if test x"$Ac_cachevar" = x"yes"; then
471  $2="${$2} $3"
472fi
473undefine([Ac_cachevar])dnl
474])# PGAC_PROG_VARCXX_VARFLAGS_OPT
475
476
477
478# PGAC_PROG_CXX_CFLAGS_OPT
479# -----------------------
480# Given a string, check if the compiler supports the string as a
481# command-line option. If it does, add the string to CXXFLAGS.
482AC_DEFUN([PGAC_PROG_CXX_CFLAGS_OPT],
483[PGAC_PROG_VARCXX_VARFLAGS_OPT(CXX, CXXFLAGS, $1)
484])# PGAC_PROG_CXX_VAR_OPT
485
486
487
488# PGAC_PROG_CC_LDFLAGS_OPT
489# ------------------------
490# Given a string, check if the compiler supports the string as a
491# command-line option. If it does, add the string to LDFLAGS.
492# For reasons you'd really rather not know about, this checks whether
493# you can link to a particular function, not just whether you can link.
494# In fact, we must actually check that the resulting program runs :-(
495AC_DEFUN([PGAC_PROG_CC_LDFLAGS_OPT],
496[define([Ac_cachevar], [AS_TR_SH([pgac_cv_prog_cc_ldflags_$1])])dnl
497AC_CACHE_CHECK([whether $CC supports $1], [Ac_cachevar],
498[pgac_save_LDFLAGS=$LDFLAGS
499LDFLAGS="$pgac_save_LDFLAGS $1"
500AC_RUN_IFELSE([AC_LANG_PROGRAM([extern void $2 (); void (*fptr) () = $2;],[])],
501              [Ac_cachevar=yes],
502              [Ac_cachevar=no],
503              [Ac_cachevar="assuming no"])
504LDFLAGS="$pgac_save_LDFLAGS"])
505if test x"$Ac_cachevar" = x"yes"; then
506  LDFLAGS="$LDFLAGS $1"
507fi
508undefine([Ac_cachevar])dnl
509])# PGAC_PROG_CC_LDFLAGS_OPT
510
511# PGAC_HAVE_GCC__SYNC_CHAR_TAS
512# -------------------------
513# Check if the C compiler understands __sync_lock_test_and_set(char),
514# and define HAVE_GCC__SYNC_CHAR_TAS
515#
516# NB: There are platforms where test_and_set is available but compare_and_swap
517# is not, so test this separately.
518# NB: Some platforms only do 32bit tas, others only do 8bit tas. Test both.
519AC_DEFUN([PGAC_HAVE_GCC__SYNC_CHAR_TAS],
520[AC_CACHE_CHECK(for builtin __sync char locking functions, pgac_cv_gcc_sync_char_tas,
521[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
522  [char lock = 0;
523   __sync_lock_test_and_set(&lock, 1);
524   __sync_lock_release(&lock);])],
525  [pgac_cv_gcc_sync_char_tas="yes"],
526  [pgac_cv_gcc_sync_char_tas="no"])])
527if test x"$pgac_cv_gcc_sync_char_tas" = x"yes"; then
528  AC_DEFINE(HAVE_GCC__SYNC_CHAR_TAS, 1, [Define to 1 if you have __sync_lock_test_and_set(char *) and friends.])
529fi])# PGAC_HAVE_GCC__SYNC_CHAR_TAS
530
531# PGAC_HAVE_GCC__SYNC_INT32_TAS
532# -------------------------
533# Check if the C compiler understands __sync_lock_test_and_set(),
534# and define HAVE_GCC__SYNC_INT32_TAS
535AC_DEFUN([PGAC_HAVE_GCC__SYNC_INT32_TAS],
536[AC_CACHE_CHECK(for builtin __sync int32 locking functions, pgac_cv_gcc_sync_int32_tas,
537[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
538  [int lock = 0;
539   __sync_lock_test_and_set(&lock, 1);
540   __sync_lock_release(&lock);])],
541  [pgac_cv_gcc_sync_int32_tas="yes"],
542  [pgac_cv_gcc_sync_int32_tas="no"])])
543if test x"$pgac_cv_gcc_sync_int32_tas" = x"yes"; then
544  AC_DEFINE(HAVE_GCC__SYNC_INT32_TAS, 1, [Define to 1 if you have __sync_lock_test_and_set(int *) and friends.])
545fi])# PGAC_HAVE_GCC__SYNC_INT32_TAS
546
547# PGAC_HAVE_GCC__SYNC_INT32_CAS
548# -------------------------
549# Check if the C compiler understands __sync_compare_and_swap() for 32bit
550# types, and define HAVE_GCC__SYNC_INT32_CAS if so.
551AC_DEFUN([PGAC_HAVE_GCC__SYNC_INT32_CAS],
552[AC_CACHE_CHECK(for builtin __sync int32 atomic operations, pgac_cv_gcc_sync_int32_cas,
553[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
554  [int val = 0;
555   __sync_val_compare_and_swap(&val, 0, 37);])],
556  [pgac_cv_gcc_sync_int32_cas="yes"],
557  [pgac_cv_gcc_sync_int32_cas="no"])])
558if test x"$pgac_cv_gcc_sync_int32_cas" = x"yes"; then
559  AC_DEFINE(HAVE_GCC__SYNC_INT32_CAS, 1, [Define to 1 if you have __sync_val_compare_and_swap(int *, int, int).])
560fi])# PGAC_HAVE_GCC__SYNC_INT32_CAS
561
562# PGAC_HAVE_GCC__SYNC_INT64_CAS
563# -------------------------
564# Check if the C compiler understands __sync_compare_and_swap() for 64bit
565# types, and define HAVE_GCC__SYNC_INT64_CAS if so.
566AC_DEFUN([PGAC_HAVE_GCC__SYNC_INT64_CAS],
567[AC_CACHE_CHECK(for builtin __sync int64 atomic operations, pgac_cv_gcc_sync_int64_cas,
568[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
569  [PG_INT64_TYPE lock = 0;
570   __sync_val_compare_and_swap(&lock, 0, (PG_INT64_TYPE) 37);])],
571  [pgac_cv_gcc_sync_int64_cas="yes"],
572  [pgac_cv_gcc_sync_int64_cas="no"])])
573if test x"$pgac_cv_gcc_sync_int64_cas" = x"yes"; then
574  AC_DEFINE(HAVE_GCC__SYNC_INT64_CAS, 1, [Define to 1 if you have __sync_val_compare_and_swap(int64 *, int64, int64).])
575fi])# PGAC_HAVE_GCC__SYNC_INT64_CAS
576
577# PGAC_HAVE_GCC__ATOMIC_INT32_CAS
578# -------------------------
579# Check if the C compiler understands __atomic_compare_exchange_n() for 32bit
580# types, and define HAVE_GCC__ATOMIC_INT32_CAS if so.
581AC_DEFUN([PGAC_HAVE_GCC__ATOMIC_INT32_CAS],
582[AC_CACHE_CHECK(for builtin __atomic int32 atomic operations, pgac_cv_gcc_atomic_int32_cas,
583[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
584  [int val = 0;
585   int expect = 0;
586   __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);])],
587  [pgac_cv_gcc_atomic_int32_cas="yes"],
588  [pgac_cv_gcc_atomic_int32_cas="no"])])
589if test x"$pgac_cv_gcc_atomic_int32_cas" = x"yes"; then
590  AC_DEFINE(HAVE_GCC__ATOMIC_INT32_CAS, 1, [Define to 1 if you have __atomic_compare_exchange_n(int *, int *, int).])
591fi])# PGAC_HAVE_GCC__ATOMIC_INT32_CAS
592
593# PGAC_HAVE_GCC__ATOMIC_INT64_CAS
594# -------------------------
595# Check if the C compiler understands __atomic_compare_exchange_n() for 64bit
596# types, and define HAVE_GCC__ATOMIC_INT64_CAS if so.
597AC_DEFUN([PGAC_HAVE_GCC__ATOMIC_INT64_CAS],
598[AC_CACHE_CHECK(for builtin __atomic int64 atomic operations, pgac_cv_gcc_atomic_int64_cas,
599[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
600  [PG_INT64_TYPE val = 0;
601   PG_INT64_TYPE expect = 0;
602   __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);])],
603  [pgac_cv_gcc_atomic_int64_cas="yes"],
604  [pgac_cv_gcc_atomic_int64_cas="no"])])
605if test x"$pgac_cv_gcc_atomic_int64_cas" = x"yes"; then
606  AC_DEFINE(HAVE_GCC__ATOMIC_INT64_CAS, 1, [Define to 1 if you have __atomic_compare_exchange_n(int64 *, int64 *, int64).])
607fi])# PGAC_HAVE_GCC__ATOMIC_INT64_CAS
608
609# PGAC_SSE42_CRC32_INTRINSICS
610# -----------------------
611# Check if the compiler supports the x86 CRC instructions added in SSE 4.2,
612# using the _mm_crc32_u8 and _mm_crc32_u32 intrinsic functions. (We don't
613# test the 8-byte variant, _mm_crc32_u64, but it is assumed to be present if
614# the other ones are, on x86-64 platforms)
615#
616# An optional compiler flag can be passed as argument (e.g. -msse4.2). If the
617# intrinsics are supported, sets pgac_sse42_crc32_intrinsics, and CFLAGS_SSE42.
618AC_DEFUN([PGAC_SSE42_CRC32_INTRINSICS],
619[define([Ac_cachevar], [AS_TR_SH([pgac_cv_sse42_crc32_intrinsics_$1])])dnl
620AC_CACHE_CHECK([for _mm_crc32_u8 and _mm_crc32_u32 with CFLAGS=$1], [Ac_cachevar],
621[pgac_save_CFLAGS=$CFLAGS
622CFLAGS="$pgac_save_CFLAGS $1"
623AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <nmmintrin.h>],
624  [unsigned int crc = 0;
625   crc = _mm_crc32_u8(crc, 0);
626   crc = _mm_crc32_u32(crc, 0);
627   /* return computed value, to prevent the above being optimized away */
628   return crc == 0;])],
629  [Ac_cachevar=yes],
630  [Ac_cachevar=no])
631CFLAGS="$pgac_save_CFLAGS"])
632if test x"$Ac_cachevar" = x"yes"; then
633  CFLAGS_SSE42="$1"
634  pgac_sse42_crc32_intrinsics=yes
635fi
636undefine([Ac_cachevar])dnl
637])# PGAC_SSE42_CRC32_INTRINSICS
638
639
640# PGAC_ARMV8_CRC32C_INTRINSICS
641# -----------------------
642# Check if the compiler supports the CRC32C instructions using the __crc32cb,
643# __crc32ch, __crc32cw, and __crc32cd intrinsic functions. These instructions
644# were first introduced in ARMv8 in the optional CRC Extension, and became
645# mandatory in ARMv8.1.
646#
647# An optional compiler flag can be passed as argument (e.g.
648# -march=armv8-a+crc). If the intrinsics are supported, sets
649# pgac_armv8_crc32c_intrinsics, and CFLAGS_ARMV8_CRC32C.
650AC_DEFUN([PGAC_ARMV8_CRC32C_INTRINSICS],
651[define([Ac_cachevar], [AS_TR_SH([pgac_cv_armv8_crc32c_intrinsics_$1])])dnl
652AC_CACHE_CHECK([for __crc32cb, __crc32ch, __crc32cw, and __crc32cd with CFLAGS=$1], [Ac_cachevar],
653[pgac_save_CFLAGS=$CFLAGS
654CFLAGS="$pgac_save_CFLAGS $1"
655AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <arm_acle.h>],
656  [unsigned int crc = 0;
657   crc = __crc32cb(crc, 0);
658   crc = __crc32ch(crc, 0);
659   crc = __crc32cw(crc, 0);
660   crc = __crc32cd(crc, 0);
661   /* return computed value, to prevent the above being optimized away */
662   return crc == 0;])],
663  [Ac_cachevar=yes],
664  [Ac_cachevar=no])
665CFLAGS="$pgac_save_CFLAGS"])
666if test x"$Ac_cachevar" = x"yes"; then
667  CFLAGS_ARMV8_CRC32C="$1"
668  pgac_armv8_crc32c_intrinsics=yes
669fi
670undefine([Ac_cachevar])dnl
671])# PGAC_ARMV8_CRC32C_INTRINSICS
672