As suggested at [0], we can move the computation of MAXIMUM_ALIGNOF from
configure.ac and meson.build to c.h. This eliminates code duplication.
(For example, the AIX patch contemplates some changes, so it would be
good to make those in only one place.) Also, it used to be more
complicated, but now it's not really a computation anymore, it's just a
#define and two static assertions, so it's just much easier and natural
this way. (For example, doing a symbol lookup on MAXIMUM_ALIGNOF will
take you to a place with useful context, instead of to pg_config.h.)
The only trick is that the there are some ordering problems in c.h.
MAXIMUM_ALIGNOF is used in the definition of the int128, which comes
very early, before the alignment handling. I moved the int128 stuff to
later in the file, near other types with alignment dependencies. (If
you look closer, you will find other opportunities for a more
comprehensive reshuffling in c.h, but maybe that should be a separate
project.)
[0]:
https://www.postgresql.org/message-id/CA%2BhUKGLQUivg-NC7dHdbRAPmG0Hapg1gGnygM5KgDfDM2a_TMg%40mail.gmail.comFrom 6f7bcca6fc2736af6ba582aaa4233599f8185756 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Tue, 20 Jan 2026 07:20:30 +0100
Subject: [PATCH] Move MAXIMUM_ALIGNOF definition to c.h
This combines duplicate code from configure.in and meson.build.
Discussion:
https://www.postgresql.org/message-id/CA%2BhUKGLQUivg-NC7dHdbRAPmG0Hapg1gGnygM5KgDfDM2a_TMg%40mail.gmail.com
---
configure | 30 --------------
configure.ac | 26 ------------
meson.build | 25 +-----------
src/include/c.h | 81 +++++++++++++++++++++++++-------------
src/include/pg_config.h.in | 3 --
5 files changed, 56 insertions(+), 109 deletions(-)
diff --git a/configure b/configure
index fb6a4914b06..5f6f79c9516 100755
--- a/configure
+++ b/configure
@@ -17110,36 +17110,6 @@ _ACEOF
-# Compute maximum alignment of any basic type.
-#
-# We require 'double' to have the strictest alignment among the basic types,
-# because otherwise the C ABI might impose 8-byte alignment on some of the
-# other C types that correspond to TYPALIGN_DOUBLE SQL types. That could
-# cause a mismatch between the tuple layout and the C struct layout of a
-# catalog tuple. We used to carefully order catalog columns such that any
-# fixed-width, attalign=4 columns were at offsets divisible by 8 regardless
-# of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platforms
-# where TYPALIGN_DOUBLE != MAXIMUM_ALIGNOF.
-#
-# We assume without checking that long's alignment is at least as strong as
-# char, short, or int. Note that we intentionally do not consider any types
-# wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8 would be too
-# much of a penalty for disk and memory space.
-
-MAX_ALIGNOF=$ac_cv_alignof_double
-
-if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
- as_fn_error $? "alignment of 'long' is greater than the alignment of
'double'" "$LINENO" 5
-fi
-if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
- as_fn_error $? "alignment of 'int64_t' is greater than the alignment of
'double'" "$LINENO" 5
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define MAXIMUM_ALIGNOF $MAX_ALIGNOF
-_ACEOF
-
-
# Some compilers offer a 128-bit integer scalar type.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128" >&5
$as_echo_n "checking for __int128... " >&6; }
diff --git a/configure.ac b/configure.ac
index d3febfe58f1..dde7dcfa35f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1995,32 +1995,6 @@ AC_CHECK_ALIGNOF(long)
AC_CHECK_ALIGNOF(int64_t)
AC_CHECK_ALIGNOF(double)
-# Compute maximum alignment of any basic type.
-#
-# We require 'double' to have the strictest alignment among the basic types,
-# because otherwise the C ABI might impose 8-byte alignment on some of the
-# other C types that correspond to TYPALIGN_DOUBLE SQL types. That could
-# cause a mismatch between the tuple layout and the C struct layout of a
-# catalog tuple. We used to carefully order catalog columns such that any
-# fixed-width, attalign=4 columns were at offsets divisible by 8 regardless
-# of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platforms
-# where TYPALIGN_DOUBLE != MAXIMUM_ALIGNOF.
-#
-# We assume without checking that long's alignment is at least as strong as
-# char, short, or int. Note that we intentionally do not consider any types
-# wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8 would be too
-# much of a penalty for disk and memory space.
-
-MAX_ALIGNOF=$ac_cv_alignof_double
-
-if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
- AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'double'])
-fi
-if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
- AC_MSG_ERROR([alignment of 'int64_t' is greater than the alignment of
'double'])
-fi
-AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum
alignment requirement of any C data type.])
-
# Some compilers offer a 128-bit integer scalar type.
PGAC_TYPE_128BIT_INT
diff --git a/meson.build b/meson.build
index 6d304f32fb0..c5fc29ed681 100644
--- a/meson.build
+++ b/meson.build
@@ -1771,33 +1771,12 @@ endif
# Determine memory alignment requirements for the basic C data types.
-alignof_types = ['short', 'int', 'long', 'double']
+alignof_types = ['short', 'int', 'long', 'int64_t', 'double']
foreach t : alignof_types
- align = cc.alignment(t, args: test_c_args)
+ align = cc.alignment(t, args: test_c_args, prefix: '#include <stdint.h>')
cdata.set('ALIGNOF_@0@'.format(t.to_upper()), align)
endforeach
-# Compute maximum alignment of any basic type.
-#
-# We require 'double' to have the strictest alignment among the basic types,
-# because otherwise the C ABI might impose 8-byte alignment on some of the
-# other C types that correspond to TYPALIGN_DOUBLE SQL types. That could
-# cause a mismatch between the tuple layout and the C struct layout of a
-# catalog tuple. We used to carefully order catalog columns such that any
-# fixed-width, attalign=4 columns were at offsets divisible by 8 regardless
-# of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platforms
-# where TYPALIGN_DOUBLE != MAXIMUM_ALIGNOF.
-#
-# We assume without checking that int64_t's alignment is at least as strong
-# as long, char, short, or int. Note that we intentionally do not consider
-# any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8
-# would be too much of a penalty for disk and memory space.
-alignof_double = cdata.get('ALIGNOF_DOUBLE')
-if cc.alignment('int64_t', args: test_c_args, prefix: '#include <stdint.h>') >
alignof_double
- error('alignment of int64_t is greater than the alignment of double')
-endif
-cdata.set('MAXIMUM_ALIGNOF', alignof_double)
-
cdata.set('SIZEOF_LONG', cc.sizeof('long', args: test_c_args))
cdata.set('SIZEOF_LONG_LONG', cc.sizeof('long long', args: test_c_args))
cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
diff --git a/src/include/c.h b/src/include/c.h
index 7136102e5ff..b6a7330c88f 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -565,33 +565,6 @@ typedef uint32 bits32; /* >= 32 bits */
#define UINT64_FORMAT "%" PRIu64
#define OID8_FORMAT "%" PRIu64
-/*
- * 128-bit signed and unsigned integers
- * There currently is only limited support for such types.
- * E.g. 128bit literals and snprintf are not supported; but math
is.
- * Also, because we exclude such types when choosing
MAXIMUM_ALIGNOF,
- * it must be possible to coerce the compiler to allocate them on
no
- * more than MAXALIGN boundaries.
- */
-#if defined(PG_INT128_TYPE)
-#if defined(pg_attribute_aligned) || ALIGNOF_PG_INT128_TYPE <= MAXIMUM_ALIGNOF
-#define HAVE_INT128 1
-
-typedef PG_INT128_TYPE int128
-#if defined(pg_attribute_aligned)
- pg_attribute_aligned(MAXIMUM_ALIGNOF)
-#endif
- ;
-
-typedef unsigned PG_INT128_TYPE uint128
-#if defined(pg_attribute_aligned)
- pg_attribute_aligned(MAXIMUM_ALIGNOF)
-#endif
- ;
-
-#endif
-#endif
-
/* Historical names for limits in <stdint.h>. */
#define PG_INT8_MIN INT8_MIN
#define PG_INT8_MAX INT8_MAX
@@ -802,6 +775,33 @@ typedef NameData *Name;
*/
#define lengthof(array) (sizeof (array) / sizeof ((array)[0]))
+/*
+ * Compute maximum alignment of any basic type.
+ *
+ * We require 'double' to have the strictest alignment among the basic types,
+ * because otherwise the C ABI might impose 8-byte alignment on some of the
+ * other C types that correspond to TYPALIGN_DOUBLE SQL types. That could
+ * cause a mismatch between the tuple layout and the C struct layout of a
+ * catalog tuple. We used to carefully order catalog columns such that any
+ * fixed-width, attalign=4 columns were at offsets divisible by 8 regardless
+ * of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platforms
+ * where TYPALIGN_DOUBLE != MAXIMUM_ALIGNOF.
+ *
+ * We assume without checking that the alignments of int64_t and long are at
+ * least as strong as char, short, or int. Note that we intentionally do not
+ * consider any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to
+ * exceed 8 would be too much of a penalty for disk and memory space.
+ */
+
+static_assert(ALIGNOF_LONG <= ALIGNOF_DOUBLE,
+ "alignment of 'long' is greater than the alignment of
'double'");
+
+static_assert(ALIGNOF_INT64_T <= ALIGNOF_DOUBLE,
+ "alignment of 'int64_t' is greater than the alignment
of 'double'");
+
+/* The maximum alignment requirement of any C data type */
+#define MAXIMUM_ALIGNOF ALIGNOF_DOUBLE
+
/* ----------------
* Alignment macros: align a length or address appropriately for a given type.
* The fooALIGN() macros round up to a multiple of the required alignment,
@@ -1102,6 +1102,33 @@ pg_noreturn extern void ExceptionalCondition(const char
*conditionName,
#define INVERT_COMPARE_RESULT(var) \
((var) = ((var) < 0) ? 1 : -(var))
+/*
+ * 128-bit signed and unsigned integers
+ * There currently is only limited support for such types.
+ * E.g. 128bit literals and snprintf are not supported; but math
is.
+ * Also, because we exclude such types when choosing
MAXIMUM_ALIGNOF,
+ * it must be possible to coerce the compiler to allocate them on
no
+ * more than MAXALIGN boundaries.
+ */
+#if defined(PG_INT128_TYPE)
+#if defined(pg_attribute_aligned) || ALIGNOF_PG_INT128_TYPE <= MAXIMUM_ALIGNOF
+#define HAVE_INT128 1
+
+typedef PG_INT128_TYPE int128
+#if defined(pg_attribute_aligned)
+ pg_attribute_aligned(MAXIMUM_ALIGNOF)
+#endif
+ ;
+
+typedef unsigned PG_INT128_TYPE uint128
+#if defined(pg_attribute_aligned)
+ pg_attribute_aligned(MAXIMUM_ALIGNOF)
+#endif
+ ;
+
+#endif
+#endif
+
/*
* Use this, not "char buf[BLCKSZ]", to declare a field or local variable
* holding a page buffer, if that page might be accessed as a page. Otherwise
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 339268dc8ef..b42cf0df5cc 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -547,9 +547,6 @@
/* Define to 1 if you have __get_cpuid_count. */
#undef HAVE__GET_CPUID_COUNT
-/* Define as the maximum alignment requirement of any C data type. */
-#undef MAXIMUM_ALIGNOF
-
/* Define bytes to use libc memset(). */
#undef MEMSET_LOOP_LIMIT
base-commit: 7ebb64c557570647e3fcf6f5f1549e882ed26489
--
2.52.0