From 0d43f2a562c84ff440da978a9275fc44e6f5d9da Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 7 Dec 2025 15:21:46 -0800 Subject: [PATCH] Align config.h better to src/lisp.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is mostly a cleanup patch to fix growing discrepancies between src/lisp.h and configure.ac in terms of how they deduce how EMACS_INT aligns. The patch includes a static check that the two methods now agree. It also speeds up ‘configure’ a bit. * configure.ac (ALIGNOF_INT, ALIGNOF_LONG, ALIGNOF_LONG_LONG): Remove; no longer used. (ALIGNOF_EMACS_INT): New macro. (system_malloc): Set to 'no' more consistently with what’s in src/lisp.h. * src/lisp.h (ALIGNOF_EMACS_INT): Do not define here, as config.h defines it now. Check that config.h’s definition equals the actual alignof (EMACS_INT). (USE_USB_TAG): Set more consistently with what’s in configure.ac. (alignas): Don’t second-guess Gnulib. --- configure.ac | 78 +++++++++++++++++++++++++++------------------------- src/lisp.h | 31 ++++++++------------- 2 files changed, 51 insertions(+), 58 deletions(-) diff --git a/configure.ac b/configure.ac index f567c3a7163..2c29633a6a9 100644 --- a/configure.ac +++ b/configure.ac @@ -3227,8 +3227,13 @@ to configure.]) fi # Configure gnulib. -# Although this does not affect CFLAGS or LIBS permanently. -# it temporarily reverts them to their pre-pkg-config values, +# +# Do this after any CC or CFLAGS changes that affect Gnulib, +# and before any tests that depend on gnulib tests, +# e.g., the system_malloc=no test below. +# +# Do not affect CFLAGS or LIBS permanently. +# Instead, temporarily revert them to their pre-pkg-config values, # because gnulib needs to work with both src (which uses the # pkg-config stuff) and lib-src (which does not). For example, gnulib # may need to determine whether CLOCK_TIME_LIB should contain -lrt, @@ -3266,9 +3271,19 @@ AC_CACHE_CHECK( fi]) doug_lea_malloc=$emacs_cv_var_doug_lea_malloc -AC_CHECK_ALIGNOF([int]) -AC_CHECK_ALIGNOF([long]) -AC_CHECK_ALIGNOF([long long]) +AC_CHECK_ALIGNOF([EMACS_INT], + [[#include + #include + #include + #if INTPTR_MAX <= INT_MAX && !defined WIDE_EMACS_INT + typedef int EMACS_INT; + #elif INTPTR_MAX <= LONG_MAX && !defined WIDE_EMACS_INT + typedef long int EMACS_INT; + #elif INTPTR_MAX <= LLONG_MAX + typedef long long int EMACS_INT; + #endif + ]]) + AC_CHECK_SIZEOF([long]) AC_CACHE_CHECK([for struct alignment], @@ -3293,40 +3308,27 @@ system_malloc=yes # adequately positioned memory, enable the GNU malloc, which more # consistently provides allocations at low addresses, as is required for # the pdumper to load dump files at a representable location. -AS_IF([test "$with_pdumper" = "yes" && test "$with_wide_int" != "yes"], - AC_CHECK_HEADERS([stdalign.h]) - [AC_CACHE_CHECK([whether alignas is required yet unavailable], - [emacs_cv_alignas_unavailable], - [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#ifdef HAVE_STDALIGN_H -#include -#endif - #include - ]], [[ -#define IDEAL_GCALIGNMENT 8 -#if INTPTR_MAX <= INT_MAX && !defined WIDE_EMACS_INT -# define ALIGNOF_EMACS_INT ALIGNOF_INT -# elif INTPTR_MAX <= LONG_MAX && !defined WIDE_EMACS_INT -# define ALIGNOF_EMACS_INT ALIGNOF_LONG -# elif INTPTR_MAX <= LLONG_MAX -# define ALIGNOF_EMACS_INT ALIGNOF_LONG_LONG -# else -# error "INTPTR_MAX too large" -#endif +AS_CASE([$emacs_cv_struct_alignment%$gl_cv_header_working_stdalign_h%$with_wide_int%$ac_cv_alignof_EMACS_INT%$with_pdumper], + [*%*%*%*%*%*], + [AC_MSG_ERROR([configuration values cannot contain '%'])], -#if (ALIGNOF_EMACS_INT < IDEAL_GCALIGNMENT && !defined alignas \ - && !defined HAVE_STRUCT_ATTRIBUTE_ALIGNED \ - && !defined __alignas_is_defined \ - && __STDC_VERSION__ < 202311 && __cplusplus < 201103) -#error "!USE_LSB_TAG required" -#endif - ]])], [emacs_cv_alignas_unavailable=no], - [emacs_cv_alignas_unavailable=yes])]) - AS_IF([test "$emacs_cv_alignas_unavailable" = "yes"], - [system_malloc=no - AC_MSG_WARN([The GNU memory manager will be enabled as your system -does not guarantee that the portable dumper can allocate memory at a suitably -low address.])])]) + dnl There is no problem in most situations, i.e.: + [dnl if emacs_cv_struct_alignment + yes%* \ + dnl or if gl_cv_header_working_stdalign_h + | *%yes*%*%*%* \ + dnl or if with_wide_int (as in practice tag bits are high-order) + | *%*%yes%*%* \ + dnl or if EMACS_INT's alignment is at least 8. + | *%*%*%8%* | *%*%*%[1-9]?*%*], + [], + + dnl Otherwise, if using the portable dumper, enable GNU malloc. + [*%yes], + [system_malloc=no + AC_MSG_WARN([The GNU memory manager will be enabled as your system + does not guarantee that the portable dumper can allocate memory + at a suitably low address.])]) dnl This must be before the test of $ac_cv_func_sbrk below. AC_CHECK_FUNCS_ONCE([sbrk]) diff --git a/src/lisp.h b/src/lisp.h index 47442a29f50..e63019cc088 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -90,21 +90,18 @@ DEFINE_GDB_SYMBOL_END (GCTYPEBITS) typedef int EMACS_INT; typedef unsigned int EMACS_UINT; enum { EMACS_INT_WIDTH = INT_WIDTH, EMACS_UINT_WIDTH = UINT_WIDTH }; -# define ALIGNOF_EMACS_INT ALIGNOF_INT # define EMACS_INT_MAX INT_MAX # define pI "" # elif INTPTR_MAX <= LONG_MAX && !defined WIDE_EMACS_INT typedef long int EMACS_INT; typedef unsigned long EMACS_UINT; enum { EMACS_INT_WIDTH = LONG_WIDTH, EMACS_UINT_WIDTH = ULONG_WIDTH }; -# define ALIGNOF_EMACS_INT ALIGNOF_LONG # define EMACS_INT_MAX LONG_MAX # define pI "l" # elif INTPTR_MAX <= LLONG_MAX typedef long long int EMACS_INT; typedef unsigned long long int EMACS_UINT; enum { EMACS_INT_WIDTH = LLONG_WIDTH, EMACS_UINT_WIDTH = ULLONG_WIDTH }; -# define ALIGNOF_EMACS_INT ALIGNOF_LONG_LONG # define EMACS_INT_MAX LLONG_MAX /* MinGW supports %lld only if __USE_MINGW_ANSI_STDIO is non-zero, which is arranged by config.h, and (for mingw.org) if GCC is 6.0 or @@ -123,6 +120,7 @@ enum { EMACS_INT_WIDTH = LLONG_WIDTH, EMACS_UINT_WIDTH = ULLONG_WIDTH }; # error "INTPTR_MAX too large" # endif #endif +static_assert (alignof (EMACS_INT) == ALIGNOF_EMACS_INT); /* Number of bits to put in each character in the internal representation of bool vectors. This should not vary across implementations. */ @@ -252,15 +250,13 @@ DEFINE_GDB_SYMBOL_END (INTTYPEBITS) b. slower, because it typically requires extra masking. So, USE_LSB_TAG is true only on hosts where it might be useful. */ DEFINE_GDB_SYMBOL_BEGIN (bool, USE_LSB_TAG) -#if (ALIGNOF_EMACS_INT < IDEAL_GCALIGNMENT && !defined alignas \ - && ! (__GNUC__ || 4 <= __clang_major__) \ - && __STDC_VERSION__ < 202311 && __cplusplus < 201103) \ - && !defined WIDE_EMACS_INT \ - && !defined HAVE_STRUCT_ATTRIBUTE_ALIGNED -#define USE_LSB_TAG 0 -#else /* ALIGNOF_EMACS_INT >= IDEAL_GCALIGNMENT || defined alignas ... */ -#define USE_LSB_TAG (VAL_MAX / 2 < INTPTR_MAX) -#endif /* ALIGNOF_EMACS_INT >= IDEAL_GCALIGNMENT || defined alignas ... */ +#if (ALIGNOF_EMACS_INT < IDEAL_GCALIGNMENT \ + && !HAVE_C_ALIGNASOF && !defined alignas \ + && !defined HAVE_STRUCT_ATTRIBUTE_ALIGNED) +# define USE_LSB_TAG false +#else +# define USE_LSB_TAG (VAL_MAX / 2 < INTPTR_MAX) +#endif DEFINE_GDB_SYMBOL_END (USE_LSB_TAG) /* Mask for the value (as opposed to the type bits) of a Lisp object. */ @@ -268,14 +264,9 @@ DEFINE_GDB_SYMBOL_BEGIN (EMACS_INT, VALMASK) # define VALMASK (USE_LSB_TAG ? - (1 << GCTYPEBITS) : VAL_MAX) DEFINE_GDB_SYMBOL_END (VALMASK) -/* Support 'alignas (A)' if possible, where A is an integer constant. */ -#ifndef alignas -# if __GNUC__ || 4 <= __clang_major__ -/* This is more reliable than the alignas operator, in GCC 14. */ -# define alignas(a) __attribute__ ((__aligned__ (a))) -# elif __STDC_VERSION__ < 202311 && __cplusplus < 201103 -# define alignas(a) /* not supported */ -# endif +/* Ignore 'alignas' on compilers lacking it. */ +#if !HAVE_C_ALIGNASOF && !defined alignas +# define alignas(a) /* not supported */ #endif /* The minimum alignment requirement for Lisp objects that is imposed by the