From 22cbc3475abb510f165cd84e5140c1d69da56156 Mon Sep 17 00:00:00 2001
From: Aditya Kamath <Aditya.Kamath1@ibm.com>
Date: Fri, 30 Jan 2026 02:47:48 -0600
Subject: [PATCH] Add AIX support for Postgresql using meson build tool.

This is a patch which makes postgresql project buildable in AIX.

The patch changes are summarised as follows:

1: AIX will support postgresql from oslevel 7.2 onwards for GCC compiler in 64 bit mode only.
   Hence in cppflags and ldflags -maix64 argument has been used in meson.build of the project source directory, since AIX's default compilation
   mode is 32 bit.
2: Changes related to meson build system
   - We have added a new option called -Ddefault_library which will build both shared and static
     library by default and need to be set to shared or static if you want only one of them.
     More about this can be found in the link [0]
   - The disabler()  is used to disable static library in AIX or any platform not needing the same. In every meson.build file we check
     the same via found() and then only add them to the install targets.
3: The patch also fixes the assumption that if the align of double is not the platforms maximum align then the code will break.
   In AIX, align of double is 4 and align of int64 is 8.
   More information can be read here [1]
4: src/tools/gen_export.pl and src/backend/port/aix/mkldexport.sh assist in creating export files for AIX.
5: AIX system float.h and postgres src/include/utils/float.h can collide due to -I../src/include/utils/ passed in the build by meson
   leading to src/include/utils/float.h getting included before src/include/c.h . To avoid them changes in src/backend/utils/Makefile
   src/backend/utils/activity/meson.build, src/backend/utils/activity/wait_event.c and src/backend/utils/activity/wait_event_funcs.c
   have been made. More information on this can be found in the link [2]

Steps to build postgresql project in AIX using meson:

export OBJECT_MODE=64
meson setup build -Ddefault_library=shared
meson compile -C build

[0]:
https://www.postgresql.org/message-id/e8aa97db-872b-4087-b073-f296baae948d@eisentraut.org
[1]:
https://www.postgresql.org/message-id/1127261.1769649624%40sss.pgh.pa.us
[2]
https://www.postgresql.org/message-id/vua2n6svb6fac3fmz42ahqxndmgbgor7vpxtemis5evasfpzb3@ogs4ewexkpjm

Co-authored-by: Peter Eisentraut <peter@eisentraut.org>
Co-authored-by: Tom Lane <tgl@sss.pgh.pa.us>
Co-authored-by: Michael Paquier <michael@paquier.xyz>
Co-authored-by: Robert Haas <robertmhaas@gmail.com>
Co-authored-by: Srirama Kucherlapati <sriram.rk@in.ibm.com>
---
 .cirrus.tasks.yml                             |  1 +
 configure                                     | 64 +++------------
 configure.ac                                  | 30 +++----
 doc/src/sgml/catalogs.sgml                    |  8 +-
 doc/src/sgml/ref/create_type.sgml             |  9 ++-
 meson.build                                   | 79 +++++++++++++------
 src/backend/Makefile                          | 10 +--
 src/backend/access/common/tupdesc.c           |  8 +-
 src/backend/bootstrap/bootstrap.c             |  4 +-
 src/backend/catalog/Catalog.pm                | 10 ++-
 src/backend/catalog/heap.c                    |  4 +-
 src/backend/catalog/pg_type.c                 |  9 ++-
 src/backend/commands/typecmds.c               | 38 +++++++--
 src/backend/meson.build                       | 18 +++++
 src/backend/port/aix/mkldexport.sh            | 61 ++++++++++++++
 src/backend/tsearch/ts_typanalyze.c           |  2 +-
 src/backend/utils/.gitignore                  |  7 --
 src/backend/utils/Makefile                    | 13 ++-
 src/backend/utils/activity/.gitignore         |  3 -
 src/backend/utils/activity/Makefile           | 17 +---
 src/backend/utils/activity/meson.build        |  1 -
 src/backend/utils/activity/wait_event.c       |  2 +-
 src/backend/utils/activity/wait_event_funcs.c |  2 +-
 .../utils/activity/wait_event_names.txt       |  6 +-
 src/backend/utils/adt/arrayfuncs.c            |  2 +-
 src/backend/utils/adt/orderedsetaggs.c        |  2 +-
 src/backend/utils/adt/rangetypes_typanalyze.c |  2 +-
 src/backend/utils/error/elog.c                |  2 +
 src/bin/initdb/initdb.c                       |  2 +-
 src/bin/pg_dump/pg_dump.c                     |  4 +
 src/common/meson.build                        |  1 +
 src/fe_utils/meson.build                      |  4 +-
 src/include/Makefile                          |  1 +
 src/include/access/tupmacs.h                  | 12 +--
 src/include/c.h                               |  4 +-
 src/include/catalog/pg_type.dat               | 62 +++++++--------
 src/include/catalog/pg_type.h                 |  2 +
 src/include/pg_config.h.in                    |  3 -
 src/include/port/aix.h                        |  0
 src/include/storage/s_lock.h                  | 51 ++----------
 src/include/utils/.gitignore                  |  2 +
 src/interfaces/ecpg/compatlib/meson.build     |  8 +-
 src/interfaces/ecpg/ecpglib/meson.build       |  8 +-
 src/interfaces/ecpg/pgtypeslib/meson.build    |  9 ++-
 src/interfaces/libpq-oauth/meson.build        |  1 +
 src/interfaces/libpq/meson.build              |  4 +-
 src/makefiles/Makefile.aix                    | 39 +++++++++
 src/pl/plpython/plpy_typeio.c                 |  4 +-
 src/port/meson.build                          |  1 +
 src/port/strerror.c                           |  2 +
 src/test/regress/expected/float8.out          |  8 +-
 src/test/regress/expected/type_sanity.out     |  8 +-
 src/test/regress/sql/float8.sql               |  6 +-
 src/test/regress/sql/type_sanity.sql          |  8 +-
 src/tools/gen_export.pl                       | 11 ++-
 55 files changed, 405 insertions(+), 274 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 delete mode 100644 src/backend/utils/.gitignore
 delete mode 100644 src/backend/utils/activity/.gitignore
 create mode 100644 src/include/port/aix.h
 create mode 100755 src/makefiles/Makefile.aix

diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index 2a821593ce5..ccefaacd8ab 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -134,6 +134,7 @@ task:
         --buildtype=debug \
         --auto-features=disabled \
         -Dtap_tests=enabled \
+        -Ddefault_library=shared \
         build
     EOF
   build_script: |
diff --git a/configure b/configure
index a10a2c85c6a..5adfb3eba45 100755
--- a/configure
+++ b/configure
@@ -17095,41 +17095,6 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-# The cast to long int works around a bug in the HP C Compiler,
-# see AC_CHECK_SIZEOF for more information.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of long" >&5
-$as_echo_n "checking alignment of long... " >&6; }
-if ${ac_cv_alignof_long+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_long"        "$ac_includes_default
-#ifndef offsetof
-# define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
-#endif
-typedef struct { char x; long y; } ac__type_alignof_;"; then :
-
-else
-  if test "$ac_cv_type_long" = yes; then
-     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute alignment of long
-See \`config.log' for more details" "$LINENO" 5; }
-   else
-     ac_cv_alignof_long=0
-   fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_long" >&5
-$as_echo "$ac_cv_alignof_long" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define ALIGNOF_LONG $ac_cv_alignof_long
-_ACEOF
-
-
 # The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of int64_t" >&5
@@ -17203,27 +17168,16 @@ _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.
+# We assume without checking that the maximum alignment requirement is that
+# of int64_t and/or double.  (On most platforms those are the same, but not
+# everywhere.)  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
+if test $ac_cv_alignof_int64_t -gt $ac_cv_alignof_double ; then
+  MAX_ALIGNOF=$ac_cv_alignof_int64_t
+else
+  MAX_ALIGNOF=$ac_cv_alignof_double
 fi
 
 cat >>confdefs.h <<_ACEOF
diff --git a/configure.ac b/configure.ac
index 814e64a967e..a5eab2e5fff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2031,33 +2031,21 @@ AC_CHECK_SIZEOF([intmax_t])
 
 AC_CHECK_ALIGNOF(short)
 AC_CHECK_ALIGNOF(int)
-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
+# We assume without checking that the maximum alignment requirement is that
+# of int64_t and/or double.  (On most platforms those are the same, but not
+# everywhere.)  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.
 
-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'])
+if test $ac_cv_alignof_int64_t -gt $ac_cv_alignof_double ; then
+  MAX_ALIGNOF=$ac_cv_alignof_int64_t
+else
+  MAX_ALIGNOF=$ac_cv_alignof_double
 fi
 AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum alignment requirement of any C data type.])
 
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 332193565e2..12608d00a18 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -9567,7 +9567,13 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
          <para><literal>i</literal> = <type>int</type> alignment (4 bytes on most machines).</para>
         </listitem>
         <listitem>
-         <para><literal>d</literal> = <type>double</type> alignment (8 bytes on many machines, but by no means all).</para>
+         <para><literal>l</literal> = <type>int64</type> alignment (8 bytes on most machines, but by no means all).</para>
+        </listitem>
+        <listitem>
+         <para><literal>d</literal> = <type>double</type> alignment (8 bytes on most machines, but by no means all).</para>
+        </listitem>
+        <listitem>
+         <para><literal>m</literal> = maximum alignment (8 bytes on most machines).</para>
         </listitem>
        </itemizedlist>
       </para></entry>
diff --git a/doc/src/sgml/ref/create_type.sgml b/doc/src/sgml/ref/create_type.sgml
index 994dfc65268..006db624094 100644
--- a/doc/src/sgml/ref/create_type.sgml
+++ b/doc/src/sgml/ref/create_type.sgml
@@ -748,8 +748,15 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
      <para>
       The storage alignment requirement of the data type.  If specified,
       it must be <literal>char</literal>, <literal>int2</literal>,
-      <literal>int4</literal>, or <literal>double</literal>; the
+      <literal>int4</literal>, <literal>int8</literal>,
+      <literal>double</literal>, or <literal>max</literal>; the
       default is <literal>int4</literal>.
+      <literal>int8</literal> and <literal>double</literal> usually
+      have the same behavior, but there are platforms on which they are
+      different because integer and floating-point values have different
+      requirements.  <literal>max</literal> means the maximum alignment
+      requirement for any of these types; it is often used for container
+      types such as records.
      </para>
     </listitem>
    </varlistentry>
diff --git a/meson.build b/meson.build
index df907b62da3..f3dee86f85c 100644
--- a/meson.build
+++ b/meson.build
@@ -20,6 +20,7 @@ project('postgresql',
     'warning_level=1', #-Wall equivalent
     'b_pch=false',
     'buildtype=debugoptimized', # -O2 + debug
+    'default_library=both',
     # For compatibility with the autoconf build, set a default prefix. This
     # works even on windows, where it's a drive-relative path (i.e. when on
     # d:/somepath it'll install to d:/usr/local/pgsql)
@@ -50,6 +51,23 @@ not_found_dep = dependency('', required: false)
 thread_dep = dependency('threads')
 auto_features = get_option('auto_features')
 
+# Declare dependencies to disable static or shared libraries.  This
+# makes the 'default_library' option work even though we don't use the
+# library() function but instead shared_library() and static_library()
+# separately.
+# We want to do this because in some targets we want to build both
+# shared and static libraries, Ex: Windows and in some targets build
+# only shared libraries. Ex: AIX. So dep_static_lib is disabled when
+# we want to build only shared libraries.
+default_library_opt = get_option('default_library')
+dep_shared_lib = declare_dependency()
+dep_static_lib = declare_dependency()
+if default_library_opt == 'shared'
+  dep_static_lib = disabler()
+elif default_library_opt == 'static'
+  dep_shared_lib = disabler()
+endif
+
 
 
 ###############################################################
@@ -325,6 +343,23 @@ elif host_system == 'windows'
 
   windows = import('windows')
 
+elif host_system == 'aix'
+  sema_kind = 'unnamed_posix'
+  library_path_var = 'LIBPATH'
+  export_file_format = 'aix'
+  export_fmt = '-Wl,-bE:@0@'
+  mod_link_args_fmt = ['-Wl,-bI:@0@']
+  mod_link_with_dir = 'libdir'
+  mod_link_with_name = '@0@.imp'
+  dl_suffix = '.a'
+  cppflags += '-maix64'
+  ldflags += '-maix64'
+
+  # M:SRE sets a flag indicating that an object is a shared library.
+  # -brtllib - To link binaries to use runtime loaded shared libraries
+  ldflags_sl += '-Wl,-bM:SRE'
+  ldflags_be += '-Wl,-brtllib'
+
 else
   # XXX: Should we add an option to override the host_system as an escape
   # hatch?
@@ -1798,32 +1833,27 @@ endif
 
 # Determine memory alignment requirements for the basic C data types.
 
-alignof_types = ['short', 'int', 'long', 'double']
+alignof_types = ['short', 'int', '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.
+# We assume without checking that the maximum alignment requirement is that
+# of int64_t and/or double.  (On most platforms those are the same, but not
+# everywhere.)  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_int64_t = cdata.get('ALIGNOF_INT64_T')
 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')
+if alignof_int64_t > alignof_double
+  cdata.set('MAXIMUM_ALIGNOF', alignof_int64_t)
+else
+  cdata.set('MAXIMUM_ALIGNOF', alignof_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))
@@ -3528,18 +3558,21 @@ endif
 installed_targets = [
   backend_targets,
   bin_targets,
-  libpq_st,
   pl_targets,
   contrib_targets,
   nls_mo_targets,
   ecpg_targets,
 ]
 
+if dep_static_lib.found()
+  installed_targets += libpq_st
+endif
+
 if oauth_flow_supported
-  installed_targets += [
-    libpq_oauth_so,
-    libpq_oauth_st,
-  ]
+  installed_targets += libpq_oauth_so
+  if dep_static_lib.found()
+    installed_targets += libpq_oauth_st
+  endif
 endif
 
 # all targets that require building code
diff --git a/src/backend/Makefile b/src/backend/Makefile
index baa9b05d021..05642dc02e3 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -136,9 +136,6 @@ parser/gram.h: parser/gram.y
 storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl ../include/storage/lwlocklist.h utils/activity/wait_event_names.txt
 	$(MAKE) -C storage/lmgr lwlocknames.h
 
-utils/activity/wait_event_types.h: utils/activity/generate-wait_event_types.pl utils/activity/wait_event_names.txt
-	$(MAKE) -C utils/activity wait_event_types.h pgstat_wait_event.c wait_event_funcs_data.c
-
 # run this unconditionally to avoid needing to know its dependencies here:
 submake-catalog-headers:
 	$(MAKE) -C ../include/catalog generated-headers
@@ -163,18 +160,13 @@ submake-utils-headers:
 
 .PHONY: generated-headers
 
-generated-headers: $(top_builddir)/src/include/storage/lwlocknames.h $(top_builddir)/src/include/utils/wait_event_types.h submake-catalog-headers submake-nodes-headers submake-utils-headers parser/gram.h
+generated-headers: $(top_builddir)/src/include/storage/lwlocknames.h submake-catalog-headers submake-nodes-headers submake-utils-headers parser/gram.h
 
 $(top_builddir)/src/include/storage/lwlocknames.h: storage/lmgr/lwlocknames.h
 	prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
 	  cd '$(dir $@)' && rm -f $(notdir $@) && \
 	  $(LN_S) "$$prereqdir/$(notdir $<)" .
 
-$(top_builddir)/src/include/utils/wait_event_types.h: utils/activity/wait_event_types.h
-	prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
-	  cd '$(dir $@)' && rm -f $(notdir $@) && \
-	  $(LN_S) "$$prereqdir/$(notdir $<)" .
-
 utils/probes.o: utils/probes.d $(SUBDIROBJS)
 	$(DTRACE) $(DTRACEFLAGS) -C -G -s $(call expand_subsys,$^) -o $@
 
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index 94b4f1f9975..49e5cd6c117 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -94,9 +94,15 @@ populate_compact_attribute_internal(Form_pg_attribute src,
 		case TYPALIGN_CHAR:
 			dst->attalignby = sizeof(char);
 			break;
+		case TYPALIGN_INT64:
+			dst->attalignby = ALIGNOF_INT64_T;
+			break;
 		case TYPALIGN_DOUBLE:
 			dst->attalignby = ALIGNOF_DOUBLE;
 			break;
+		case TYPALIGN_MAX:
+			dst->attalignby = MAXIMUM_ALIGNOF;
+			break;
 		case TYPALIGN_SHORT:
 			dst->attalignby = ALIGNOF_SHORT;
 			break;
@@ -994,7 +1000,7 @@ TupleDescInitBuiltinEntry(TupleDesc desc,
 		case INT8OID:
 			att->attlen = 8;
 			att->attbyval = true;
-			att->attalign = TYPALIGN_DOUBLE;
+			att->attalign = TYPALIGN_INT64;
 			att->attstorage = TYPSTORAGE_PLAIN;
 			att->attcompression = InvalidCompressionMethod;
 			att->attcollation = InvalidOid;
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index dd57624b4f9..7a3a13a6ec7 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -115,7 +115,7 @@ static const struct typinfo TypInfo[] = {
 	F_TEXTIN, F_TEXTOUT},
 	{"oid", OIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
 	F_OIDIN, F_OIDOUT},
-	{"oid8", OID8OID, 0, 8, true, TYPALIGN_DOUBLE, TYPSTORAGE_PLAIN, InvalidOid,
+	{"oid8", OID8OID, 0, 8, true, TYPALIGN_INT64, TYPSTORAGE_PLAIN, InvalidOid,
 	F_OID8IN, F_OID8OUT},
 	{"tid", TIDOID, 0, 6, false, TYPALIGN_SHORT, TYPSTORAGE_PLAIN, InvalidOid,
 	F_TIDIN, F_TIDOUT},
@@ -137,7 +137,7 @@ static const struct typinfo TypInfo[] = {
 	F_ARRAY_IN, F_ARRAY_OUT},
 	{"_char", 1002, CHAROID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, InvalidOid,
 	F_ARRAY_IN, F_ARRAY_OUT},
-	{"_aclitem", 1034, ACLITEMOID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, InvalidOid,
+	{"_aclitem", 1034, ACLITEMOID, -1, false, TYPALIGN_INT64, TYPSTORAGE_EXTENDED, InvalidOid,
 	F_ARRAY_IN, F_ARRAY_OUT}
 };
 
diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index 219af5884d9..20884f45bd8 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -464,9 +464,13 @@ sub GenerateArrayTypes
 		$array_type{typname} = '_' . $elem_type->{typname};
 		$array_type{typelem} = $elem_type->{typname};
 
-		# Arrays require INT alignment, unless the element type requires
-		# DOUBLE alignment.
-		$array_type{typalign} = $elem_type->{typalign} eq 'd' ? 'd' : 'i';
+		# Arrays require INT alignment, unless the element type requires more.
+		$array_type{typalign} =
+		  $elem_type->{typalign} eq 'l' ? 'l'
+		  : (
+			$elem_type->{typalign} eq 'd' ? 'd'
+			: ( $elem_type->{typalign} eq 'm' ? 'm'
+				: 'i'));
 
 		# Fill in the rest of the array entry's fields.
 		foreach my $column (@$pgtype_schema)
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 606434823cf..27cc09a7680 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -1075,7 +1075,7 @@ AddNewRelationType(const char *typeName,
 				   NULL,		/* default value - none */
 				   NULL,		/* default binary representation */
 				   false,		/* passed by reference */
-				   TYPALIGN_DOUBLE, /* alignment - must be the largest! */
+				   TYPALIGN_MAX,	/* alignment - must be the largest! */
 				   TYPSTORAGE_EXTENDED, /* fully TOASTable */
 				   -1,			/* typmod */
 				   0,			/* array dimensions for typBaseType */
@@ -1399,7 +1399,7 @@ heap_create_with_catalog(const char *relname,
 				   NULL,		/* default value - none */
 				   NULL,		/* default binary representation */
 				   false,		/* passed by reference */
-				   TYPALIGN_DOUBLE, /* alignment - must be the largest! */
+				   TYPALIGN_MAX,	/* alignment - must be the largest! */
 				   TYPSTORAGE_EXTENDED, /* fully TOASTable */
 				   -1,			/* typmod */
 				   0,			/* array dimensions for typBaseType */
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index fc369c35aa6..f079fa32b40 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -287,7 +287,9 @@ TypeCreate(Oid newTypeOid,
 		}
 		else if (internalSize == (int16) sizeof(int64))
 		{
-			if (alignment != TYPALIGN_DOUBLE)
+			/* We have to trust the user to get this distinction right ... */
+			if (!(alignment == TYPALIGN_INT64 ||
+				  alignment == TYPALIGN_DOUBLE))
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 						 errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
@@ -303,7 +305,10 @@ TypeCreate(Oid newTypeOid,
 	{
 		/* varlena types must have int align or better */
 		if (internalSize == -1 &&
-			!(alignment == TYPALIGN_INT || alignment == TYPALIGN_DOUBLE))
+			!(alignment == TYPALIGN_INT ||
+			  alignment == TYPALIGN_INT64 ||
+			  alignment == TYPALIGN_DOUBLE ||
+			  alignment == TYPALIGN_MAX))
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					 errmsg("alignment \"%c\" is invalid for variable-length type",
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 288edb25f2f..2f919f764aa 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -117,6 +117,7 @@ static void makeMultirangeConstructors(const char *name, Oid namespace,
 									   Oid multirangeOid, Oid rangeOid,
 									   Oid rangeArrayOid,
 									   Oid *mltrngConstruct0_p, Oid *mltrngConstruct1_p, Oid *mltrngConstruct2_p);
+static char containerAlignment(char elemalign);
 static Oid	findTypeInputFunction(List *procname, Oid typeOid);
 static Oid	findTypeOutputFunction(List *procname, Oid typeOid);
 static Oid	findTypeReceiveFunction(List *procname, Oid typeOid);
@@ -424,6 +425,9 @@ DefineType(ParseState *pstate, List *names, List *parameters)
 			pg_strcasecmp(a, "float8") == 0 ||
 			pg_strcasecmp(a, "pg_catalog.float8") == 0)
 			alignment = TYPALIGN_DOUBLE;
+		else if (pg_strcasecmp(a, "int8") == 0 ||
+				 pg_strcasecmp(a, "pg_catalog.int8") == 0)
+			alignment = TYPALIGN_INT64;
 		else if (pg_strcasecmp(a, "int4") == 0 ||
 				 pg_strcasecmp(a, "pg_catalog.int4") == 0)
 			alignment = TYPALIGN_INT;
@@ -433,6 +437,9 @@ DefineType(ParseState *pstate, List *names, List *parameters)
 		else if (pg_strcasecmp(a, "char") == 0 ||
 				 pg_strcasecmp(a, "pg_catalog.bpchar") == 0)
 			alignment = TYPALIGN_CHAR;
+		else if (pg_strcasecmp(a, "max") == 0 ||
+				 pg_strcasecmp(a, "pg_catalog.max") == 0)
+			alignment = TYPALIGN_MAX;
 		else
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -611,8 +618,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
 	 */
 	array_type = makeArrayTypeName(typeName, typeNamespace);
 
-	/* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for arrays */
-	alignment = (alignment == TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : TYPALIGN_INT;
+	/* alignment must be TYPALIGN_INT or more for arrays */
+	alignment = containerAlignment(alignment);
 
 	TypeCreate(array_oid,		/* force assignment of this type OID */
 			   array_type,		/* type name */
@@ -1095,8 +1102,8 @@ DefineDomain(ParseState *pstate, CreateDomainStmt *stmt)
 	 */
 	domainArrayName = makeArrayTypeName(domainName, domainNamespace);
 
-	/* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for arrays */
-	alignment = (alignment == TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : TYPALIGN_INT;
+	/* alignment must be TYPALIGN_INT or more for arrays */
+	alignment = containerAlignment(alignment);
 
 	TypeCreate(domainArrayOid,	/* force assignment of this type OID */
 			   domainArrayName, /* type name */
@@ -1557,8 +1564,8 @@ DefineRange(ParseState *pstate, CreateRangeStmt *stmt)
 	get_typlenbyvalalign(rangeSubtype,
 						 &subtyplen, &subtypbyval, &subtypalign);
 
-	/* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for ranges */
-	alignment = (subtypalign == TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : TYPALIGN_INT;
+	/* alignment must be TYPALIGN_INT or more for ranges */
+	alignment = containerAlignment(subtypalign);
 
 	/* Allocate OID for array type, its multirange, and its multirange array */
 	rangeArrayOid = AssignTypeArrayOid();
@@ -2005,6 +2012,25 @@ makeMultirangeConstructors(const char *name, Oid namespace,
 	pfree(parameterModes);
 }
 
+/*
+ * Compute the appropriate typalign for a container (array or range)
+ * given the typalign of its members.  The container type requires at
+ * least int alignment, but more if the members need more.
+ */
+static char
+containerAlignment(char elemalign)
+{
+	switch (elemalign)
+	{
+		case TYPALIGN_INT64:
+		case TYPALIGN_DOUBLE:
+		case TYPALIGN_MAX:
+			return elemalign;
+		default:
+			return TYPALIGN_INT;
+	}
+}
+
 /*
  * Find suitable I/O and other support functions for a type.
  *
diff --git a/src/backend/meson.build b/src/backend/meson.build
index 712a857cdb4..6629c827f8e 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -125,6 +125,24 @@ if host_system == 'windows'
     '--FILEDESC', 'PostgreSQL Server',])
 endif
 
+if host_system == 'aix'
+  # The '.' argument leads mkldexport.sh to emit "#! .", which refers to the
+  # main executable, allowing extension libraries to resolve their undefined
+  # symbols to symbols in the postgres binary.
+  postgres_imp = custom_target('postgres.imp',
+    command: [files('port/aix/mkldexport.sh'), '@INPUT@', '.'],
+    input: postgres_lib,
+    output: 'postgres.imp',
+    capture: true,
+    install: true,
+    install_dir: dir_lib,
+    build_by_default: false,
+  )
+  backend_link_args += '-Wl,-bE:@0@'.format(postgres_imp.full_path())
+  backend_link_depends += postgres_imp
+endif
+
+
 postgres = executable('postgres',
   backend_input,
   sources: post_export_backend_sources,
diff --git a/src/backend/port/aix/mkldexport.sh b/src/backend/port/aix/mkldexport.sh
new file mode 100755
index 00000000000..adf3793e868
--- /dev/null
+++ b/src/backend/port/aix/mkldexport.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+#
+# mkldexport
+#	create an AIX exports file from an object file
+#
+# src/backend/port/aix/mkldexport.sh
+#
+# Usage:
+#	mkldexport objectfile [location]
+# where
+#	objectfile is the current location of the object file.
+#	location is the eventual (installed) location of the
+#		object file (if different from the current
+#		working directory).
+#
+# [This file comes from the Postgres 4.2 distribution. - ay 7/95]
+#
+# Header: /usr/local/devel/postgres/src/tools/mkldexport/RCS/mkldexport.sh,v 1.2 1994/03/13 04:59:12 aoki Exp
+#
+
+# setting this to nm -B might be better
+# ... due to changes in AIX 4.x ...
+# ... let us search in different directories - Gerhard Reithofer
+if [ -x /usr/ucb/nm ]
+then NM=/usr/ucb/nm
+elif [ -x /usr/bin/nm ]
+then NM=/usr/bin/nm
+elif [ -x /usr/ccs/bin/nm ]
+then NM=/usr/ccs/bin/nm
+elif [ -x /usr/usg/bin/nm ]
+then NM=/usr/usg/bin/nm
+else echo "Fatal error: cannot find `nm' ... please check your installation."
+     exit 1
+fi
+
+CMDNAME=`basename $0`
+if [ -z "$1" ]; then
+	echo "Usage: $CMDNAME object [location]"
+	exit 1
+fi
+OBJNAME=`basename $1`
+if [ "`basename $OBJNAME`" != "`basename $OBJNAME .o`" ]; then
+	OBJNAME=`basename $OBJNAME .o`.so
+fi
+if [ -z "$2" ]; then
+	echo '#!'
+else
+	if [ "$2" = "." ]; then
+		# for the base executable (AIX 4.2 and up)
+		echo '#! .'
+	else
+		echo '#!' $2
+	fi
+fi
+$NM -BCg $1 | \
+	egrep ' [TDB] ' | \
+	sed -e 's/.* //' | \
+	egrep -v '\$' | \
+	sed -e 's/^[.]//' | \
+	sort | \
+	uniq
diff --git a/src/backend/tsearch/ts_typanalyze.c b/src/backend/tsearch/ts_typanalyze.c
index 0c513d694e7..48ee050e37f 100644
--- a/src/backend/tsearch/ts_typanalyze.c
+++ b/src/backend/tsearch/ts_typanalyze.c
@@ -444,7 +444,7 @@ compute_tsvector_stats(VacAttrStats *stats,
 			stats->statypid[0] = TEXTOID;
 			stats->statyplen[0] = -1;	/* typlen, -1 for varlena */
 			stats->statypbyval[0] = false;
-			stats->statypalign[0] = 'i';
+			stats->statypalign[0] = TYPALIGN_INT;
 		}
 	}
 	else
diff --git a/src/backend/utils/.gitignore b/src/backend/utils/.gitignore
deleted file mode 100644
index 303c01d0515..00000000000
--- a/src/backend/utils/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-/fmgrtab.c
-/fmgroids.h
-/fmgrprotos.h
-/fmgr-stamp
-/guc_tables.inc.c
-/probes.h
-/errcodes.h
diff --git a/src/backend/utils/Makefile b/src/backend/utils/Makefile
index 6df31504f32..81b4a956bda 100644
--- a/src/backend/utils/Makefile
+++ b/src/backend/utils/Makefile
@@ -43,7 +43,7 @@ generated-header-symlinks: $(top_builddir)/src/include/utils/header-stamp submak
 submake-adt-headers:
 	$(MAKE) -C adt jsonpath_gram.h
 
-$(SUBDIRS:%=%-recursive): fmgr-stamp errcodes.h guc_tables.inc.c
+$(SUBDIRS:%=%-recursive): fmgr-stamp errcodes.h guc_tables.inc.c pgstat_wait_event.c wait_event_funcs_data.c wait_event_types.h
 
 # fmgr-stamp records the last time we ran Gen_fmgrtab.pl.  We don't rely on
 # the timestamps of the individual output files, because the Perl script
@@ -58,6 +58,12 @@ errcodes.h: $(top_srcdir)/src/backend/utils/errcodes.txt generate-errcodes.pl
 guc_tables.inc.c: $(top_srcdir)/src/backend/utils/misc/guc_parameters.dat $(top_srcdir)/src/backend/utils/misc/gen_guc_tables.pl
 	$(PERL) $(top_srcdir)/src/backend/utils/misc/gen_guc_tables.pl $< $@
 
+pgstat_wait_event.c: wait_event_types.h
+wait_event_funcs_data.c: wait_event_types.h
+
+wait_event_types.h: $(top_srcdir)/src/backend/utils/activity/wait_event_names.txt $(top_srcdir)/src/backend/utils/activity/generate-wait_event_types.pl
+	$(PERL) $(top_srcdir)/src/backend/utils/activity/generate-wait_event_types.pl --code $<
+
 ifeq ($(enable_dtrace), yes)
 probes.h: postprocess_dtrace.sed probes.h.tmp
 	sed -f $^ >$@
@@ -73,8 +79,8 @@ endif
 # These generated headers must be symlinked into src/include/.
 # We use header-stamp to record that we've done this because the symlinks
 # themselves may appear older than fmgr-stamp.
-$(top_builddir)/src/include/utils/header-stamp: fmgr-stamp errcodes.h probes.h guc_tables.inc.c
-	cd '$(dir $@)' && for file in fmgroids.h fmgrprotos.h errcodes.h probes.h guc_tables.inc.c; do \
+$(top_builddir)/src/include/utils/header-stamp: fmgr-stamp errcodes.h probes.h guc_tables.inc.c pgstat_wait_event.c wait_event_funcs_data.c wait_event_types.h
+	cd '$(dir $@)' && for file in fmgroids.h fmgrprotos.h errcodes.h probes.h guc_tables.inc.c pgstat_wait_event.c wait_event_funcs_data.c wait_event_types.h; do \
 	  rm -f $$file && $(LN_S) "../../../$(subdir)/$$file" . ; \
 	done
 	touch $@
@@ -93,3 +99,4 @@ uninstall-data:
 clean:
 	rm -f probes.h probes.h.tmp
 	rm -f fmgroids.h fmgrprotos.h fmgrtab.c fmgr-stamp errcodes.h guc_tables.inc.c
+	rm -f wait_event_types.h pgstat_wait_event.c wait_event_funcs_data.c
diff --git a/src/backend/utils/activity/.gitignore b/src/backend/utils/activity/.gitignore
deleted file mode 100644
index bd0c0c77729..00000000000
--- a/src/backend/utils/activity/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-/pgstat_wait_event.c
-/wait_event_types.h
-/wait_event_funcs_data.c
diff --git a/src/backend/utils/activity/Makefile b/src/backend/utils/activity/Makefile
index 0eb29ee78aa..c37bfb350bb 100644
--- a/src/backend/utils/activity/Makefile
+++ b/src/backend/utils/activity/Makefile
@@ -36,17 +36,8 @@ OBJS = \
 	wait_event.o \
 	wait_event_funcs.o
 
-include $(top_srcdir)/src/backend/common.mk
-
-wait_event_funcs.o: wait_event_funcs_data.c
-wait_event_funcs_data.c: wait_event_types.h
-
-wait_event.o: pgstat_wait_event.c
-pgstat_wait_event.c: wait_event_types.h
-	touch $@
+# Force these dependencies to be known even without dependency info built:
+wait_event.o: wait_event.c $(top_builddir)/src/backend/utils/pgstat_wait_event.c
+wait_event_funcs.o: wait_event_funcs.c $(top_builddir)/src/backend/utils/wait_event_funcs_data.c
 
-wait_event_types.h: $(top_srcdir)/src/backend/utils/activity/wait_event_names.txt generate-wait_event_types.pl
-	$(PERL) $(srcdir)/generate-wait_event_types.pl --code $<
-
-clean:
-	rm -f wait_event_types.h pgstat_wait_event.c wait_event_funcs_data.c
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/utils/activity/meson.build b/src/backend/utils/activity/meson.build
index 9f48d5970e1..53bd5a246ca 100644
--- a/src/backend/utils/activity/meson.build
+++ b/src/backend/utils/activity/meson.build
@@ -30,7 +30,6 @@ waitevent_sources = files(
 wait_event = static_library('wait_event_names',
   waitevent_sources,
   dependencies: [backend_code],
-  include_directories: include_directories('../../../include/utils'),
   kwargs: internal_lib_args,
 )
 
diff --git a/src/backend/utils/activity/wait_event.c b/src/backend/utils/activity/wait_event.c
index e4f2c440257..aca2c8fc742 100644
--- a/src/backend/utils/activity/wait_event.c
+++ b/src/backend/utils/activity/wait_event.c
@@ -503,4 +503,4 @@ pgstat_get_wait_event(uint32 wait_event_info)
 	return event_name;
 }
 
-#include "pgstat_wait_event.c"
+#include "utils/pgstat_wait_event.c"
diff --git a/src/backend/utils/activity/wait_event_funcs.c b/src/backend/utils/activity/wait_event_funcs.c
index b62ee83ef73..fa10a80b088 100644
--- a/src/backend/utils/activity/wait_event_funcs.c
+++ b/src/backend/utils/activity/wait_event_funcs.c
@@ -31,7 +31,7 @@ static const struct
 
 			waitEventData[] =
 {
-#include "wait_event_funcs_data.c"
+#include "utils/wait_event_funcs_data.c"
 	/* end of list */
 	{NULL, NULL, NULL}
 };
diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt
index 5537a2d2530..efde48e76b7 100644
--- a/src/backend/utils/activity/wait_event_names.txt
+++ b/src/backend/utils/activity/wait_event_names.txt
@@ -14,13 +14,13 @@
 #
 # The files generated from this one are:
 #
-#   src/backend/utils/activity/wait_event_types.h
+#   wait_event_types.h
 #      typedef enum definitions for wait events.
 #
-#   src/backend/utils/activity/pgstat_wait_event.c
+#   pgstat_wait_event.c
 #      C functions to get the wait event name based on the enum.
 #
-#   src/backend/utils/activity/wait_event_types.sgml
+#   wait_event_types.sgml
 #      SGML tables of wait events for inclusion in the documentation.
 #
 # When adding a new wait event, make sure it is placed in the appropriate
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index e71d32773b5..0d185f5be8a 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -3426,7 +3426,7 @@ construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
 		case INT8OID:
 			elmlen = sizeof(int64);
 			elmbyval = true;
-			elmalign = TYPALIGN_DOUBLE;
+			elmalign = TYPALIGN_INT64;
 			break;
 
 		case NAMEOID:
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c
index 3b6da8e36ac..27b8cfa7064 100644
--- a/src/backend/utils/adt/orderedsetaggs.c
+++ b/src/backend/utils/adt/orderedsetaggs.c
@@ -1021,7 +1021,7 @@ percentile_cont_interval_multi_final(PG_FUNCTION_ARGS)
 	return percentile_cont_multi_final_common(fcinfo,
 											  INTERVALOID,
 	/* hard-wired info on type interval */
-											  16, false, TYPALIGN_DOUBLE,
+											  16, false, TYPALIGN_INT64,
 											  interval_lerp);
 }
 
diff --git a/src/backend/utils/adt/rangetypes_typanalyze.c b/src/backend/utils/adt/rangetypes_typanalyze.c
index 38d12dedbc5..278d4e6941a 100644
--- a/src/backend/utils/adt/rangetypes_typanalyze.c
+++ b/src/backend/utils/adt/rangetypes_typanalyze.c
@@ -398,7 +398,7 @@ compute_range_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 		stats->statypid[slot_idx] = FLOAT8OID;
 		stats->statyplen[slot_idx] = sizeof(float8);
 		stats->statypbyval[slot_idx] = true;
-		stats->statypalign[slot_idx] = 'd';
+		stats->statypalign[slot_idx] = TYPALIGN_DOUBLE;
 
 		/* Store the fraction of empty ranges */
 		emptyfrac = palloc_object(float4);
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index aa530d3685e..a71db1cf9d1 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -914,7 +914,9 @@ errcode_for_file_access(void)
 			/* Wrong object type or state */
 		case ENOTDIR:			/* Not a directory */
 		case EISDIR:			/* Is a directory */
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:			/* Directory not empty */
+#endif
 			edata->sqlerrcode = ERRCODE_WRONG_OBJECT_TYPE;
 			break;
 
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index a3980e5535f..e550e9cf0a3 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -1580,7 +1580,7 @@ bootstrap_template1(void)
 	bki_lines = replace_token(bki_lines, "SIZEOF_POINTER", buf);
 
 	bki_lines = replace_token(bki_lines, "ALIGNOF_POINTER",
-							  (sizeof(Pointer) == 4) ? "i" : "d");
+							  (sizeof(Pointer) == 4) ? "i" : "l");
 
 	bki_lines = replace_token(bki_lines, "POSTGRES",
 							  escape_quotes_bki(username));
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 2bebefd0ba2..1b44c03170f 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -12652,8 +12652,12 @@ dumpBaseType(Archive *fout, const TypeInfo *tyinfo)
 		appendPQExpBufferStr(q, ",\n    ALIGNMENT = int2");
 	else if (*typalign == TYPALIGN_INT)
 		appendPQExpBufferStr(q, ",\n    ALIGNMENT = int4");
+	else if (*typalign == TYPALIGN_INT64)
+		appendPQExpBufferStr(q, ",\n    ALIGNMENT = int8");
 	else if (*typalign == TYPALIGN_DOUBLE)
 		appendPQExpBufferStr(q, ",\n    ALIGNMENT = double");
+	else if (*typalign == TYPALIGN_MAX)
+		appendPQExpBufferStr(q, ",\n    ALIGNMENT = max");
 
 	if (*typstorage == TYPSTORAGE_PLAIN)
 		appendPQExpBufferStr(q, ",\n    STORAGE = plain");
diff --git a/src/common/meson.build b/src/common/meson.build
index b757618a9c9..1417ac3bbb7 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -192,6 +192,7 @@ foreach name, opts : pgcommon_variants
           opts.get('include_directories', []),
         ],
         'dependencies': opts['dependencies'] + [ssl],
+        'install': dep_static_lib.found(),
       }
     )
   pgcommon += {name: lib}
diff --git a/src/fe_utils/meson.build b/src/fe_utils/meson.build
index a2420ea2d5c..9c9e0bcc0da 100644
--- a/src/fe_utils/meson.build
+++ b/src/fe_utils/meson.build
@@ -35,5 +35,7 @@ fe_utils = static_library('libpgfeutils',
   include_directories: [postgres_inc, libpq_inc],
   c_args: host_system == 'windows' ? ['-DFD_SETSIZE=1024'] : [],
   dependencies: frontend_common_code,
-  kwargs: default_lib_args,
+  kwargs: default_lib_args + {
+            'install': dep_static_lib.found(),
+          },
 )
diff --git a/src/include/Makefile b/src/include/Makefile
index 4ef060e9050..ac673f4cf17 100644
--- a/src/include/Makefile
+++ b/src/include/Makefile
@@ -105,6 +105,7 @@ uninstall:
 
 clean:
 	rm -f utils/fmgroids.h utils/fmgrprotos.h utils/guc_tables.inc.c utils/errcodes.h utils/header-stamp
+	rm -f utils/pgstat_wait_event.c utils/wait_event_funcs_data.c
 	rm -f storage/lwlocknames.h utils/probes.h utils/wait_event_types.h
 	rm -f nodes/nodetags.h nodes/header-stamp
 	$(MAKE) -C catalog clean
diff --git a/src/include/access/tupmacs.h b/src/include/access/tupmacs.h
index 3e5530658c9..c5462d6fba1 100644
--- a/src/include/access/tupmacs.h
+++ b/src/include/access/tupmacs.h
@@ -146,11 +146,13 @@ fetch_att(const void *T, bool attbyval, int attlen)
 ( \
 	((attalign) == TYPALIGN_INT) ? INTALIGN(cur_offset) : \
 	 (((attalign) == TYPALIGN_CHAR) ? (uintptr_t) (cur_offset) : \
-	  (((attalign) == TYPALIGN_DOUBLE) ? DOUBLEALIGN(cur_offset) : \
-	   ( \
-			AssertMacro((attalign) == TYPALIGN_SHORT), \
-			SHORTALIGN(cur_offset) \
-	   ))) \
+	  (((attalign) == TYPALIGN_INT64) ? INT64ALIGN(cur_offset) : \
+	   (((attalign) == TYPALIGN_DOUBLE) ? DOUBLEALIGN(cur_offset) : \
+		(((attalign) == TYPALIGN_MAX) ? MAXALIGN(cur_offset) : \
+		 ( \
+			 AssertMacro((attalign) == TYPALIGN_SHORT), \
+			 SHORTALIGN(cur_offset) \
+			 ))))) \
 )
 
 /*
diff --git a/src/include/c.h b/src/include/c.h
index c443e75b89f..c7956ce91bc 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -821,7 +821,7 @@ typedef NameData *Name;
 
 #define SHORTALIGN(LEN)			TYPEALIGN(ALIGNOF_SHORT, (LEN))
 #define INTALIGN(LEN)			TYPEALIGN(ALIGNOF_INT, (LEN))
-#define LONGALIGN(LEN)			TYPEALIGN(ALIGNOF_LONG, (LEN))
+#define INT64ALIGN(LEN)			TYPEALIGN(ALIGNOF_INT64_T, (LEN))
 #define DOUBLEALIGN(LEN)		TYPEALIGN(ALIGNOF_DOUBLE, (LEN))
 #define MAXALIGN(LEN)			TYPEALIGN(MAXIMUM_ALIGNOF, (LEN))
 /* MAXALIGN covers only built-in types, not buffers */
@@ -833,7 +833,7 @@ typedef NameData *Name;
 
 #define SHORTALIGN_DOWN(LEN)	TYPEALIGN_DOWN(ALIGNOF_SHORT, (LEN))
 #define INTALIGN_DOWN(LEN)		TYPEALIGN_DOWN(ALIGNOF_INT, (LEN))
-#define LONGALIGN_DOWN(LEN)		TYPEALIGN_DOWN(ALIGNOF_LONG, (LEN))
+#define INT64ALIGN_DOWN(LEN)	TYPEALIGN_DOWN(ALIGNOF_INT64_T, (LEN))
 #define DOUBLEALIGN_DOWN(LEN)	TYPEALIGN_DOWN(ALIGNOF_DOUBLE, (LEN))
 #define MAXALIGN_DOWN(LEN)		TYPEALIGN_DOWN(MAXIMUM_ALIGNOF, (LEN))
 #define BUFFERALIGN_DOWN(LEN)	TYPEALIGN_DOWN(ALIGNOF_BUFFER, (LEN))
diff --git a/src/include/catalog/pg_type.dat b/src/include/catalog/pg_type.dat
index a1a753d1797..d511493f761 100644
--- a/src/include/catalog/pg_type.dat
+++ b/src/include/catalog/pg_type.dat
@@ -56,7 +56,7 @@
   descr => '~18 digit integer, 8-byte storage',
   typname => 'int8', typlen => '8', typbyval => 't',
   typcategory => 'N', typinput => 'int8in', typoutput => 'int8out',
-  typreceive => 'int8recv', typsend => 'int8send', typalign => 'd' },
+  typreceive => 'int8recv', typsend => 'int8send', typalign => 'l' },
 { oid => '21', array_type_oid => '1005',
   descr => '-32 thousand to 32 thousand, 2-byte storage',
   typname => 'int2', typlen => '2', typbyval => 't', typcategory => 'N',
@@ -116,22 +116,22 @@
   typname => 'pg_type', typlen => '-1', typbyval => 'f', typtype => 'c',
   typcategory => 'C', typrelid => 'pg_type', typinput => 'record_in',
   typoutput => 'record_out', typreceive => 'record_recv',
-  typsend => 'record_send', typalign => 'd', typstorage => 'x' },
+  typsend => 'record_send', typalign => 'm', typstorage => 'x' },
 { oid => '75', array_type_oid => '270',
   typname => 'pg_attribute', typlen => '-1', typbyval => 'f', typtype => 'c',
   typcategory => 'C', typrelid => 'pg_attribute', typinput => 'record_in',
   typoutput => 'record_out', typreceive => 'record_recv',
-  typsend => 'record_send', typalign => 'd', typstorage => 'x' },
+  typsend => 'record_send', typalign => 'm', typstorage => 'x' },
 { oid => '81', array_type_oid => '272',
   typname => 'pg_proc', typlen => '-1', typbyval => 'f', typtype => 'c',
   typcategory => 'C', typrelid => 'pg_proc', typinput => 'record_in',
   typoutput => 'record_out', typreceive => 'record_recv',
-  typsend => 'record_send', typalign => 'd', typstorage => 'x' },
+  typsend => 'record_send', typalign => 'm', typstorage => 'x' },
 { oid => '83', array_type_oid => '273',
   typname => 'pg_class', typlen => '-1', typbyval => 'f', typtype => 'c',
   typcategory => 'C', typrelid => 'pg_class', typinput => 'record_in',
   typoutput => 'record_out', typreceive => 'record_recv',
-  typsend => 'record_send', typalign => 'd', typstorage => 'x' },
+  typsend => 'record_send', typalign => 'm', typstorage => 'x' },
 
 # OIDS 100 - 199
 
@@ -174,7 +174,7 @@
 { oid => '5069', array_type_oid => '271', descr => 'full transaction id',
   typname => 'xid8', typlen => '8', typbyval => 't',
   typcategory => 'U', typinput => 'xid8in', typoutput => 'xid8out',
-  typreceive => 'xid8recv', typsend => 'xid8send', typalign => 'd' },
+  typreceive => 'xid8recv', typsend => 'xid8send', typalign => 'l' },
 
 # OIDS 600 - 699
 
@@ -239,7 +239,7 @@
   descr => 'monetary amounts, $d,ddd.cc',
   typname => 'money', typlen => '8', typbyval => 't',
   typcategory => 'N', typinput => 'cash_in', typoutput => 'cash_out',
-  typreceive => 'cash_recv', typsend => 'cash_send', typalign => 'd' },
+  typreceive => 'cash_recv', typsend => 'cash_send', typalign => 'l' },
 
 # OIDS 800 - 899
 
@@ -270,7 +270,7 @@
 { oid => '1033', array_type_oid => '1034', descr => 'access control list',
   typname => 'aclitem', typlen => '16', typbyval => 'f', typcategory => 'U',
   typinput => 'aclitemin', typoutput => 'aclitemout', typreceive => '-',
-  typsend => '-', typalign => 'd' },
+  typsend => '-', typalign => 'l' },
 { oid => '1042', array_type_oid => '1014',
   descr => '\'char(length)\' blank-padded string, fixed storage length',
   typname => 'bpchar', typlen => '-1', typbyval => 'f', typcategory => 'S',
@@ -293,7 +293,7 @@
   typname => 'time', typlen => '8', typbyval => 't',
   typcategory => 'D', typinput => 'time_in', typoutput => 'time_out',
   typreceive => 'time_recv', typsend => 'time_send', typmodin => 'timetypmodin',
-  typmodout => 'timetypmodout', typalign => 'd' },
+  typmodout => 'timetypmodout', typalign => 'l' },
 
 # OIDS 1100 - 1199
 
@@ -302,21 +302,21 @@
   typcategory => 'D', typinput => 'timestamp_in', typoutput => 'timestamp_out',
   typreceive => 'timestamp_recv', typsend => 'timestamp_send',
   typmodin => 'timestamptypmodin', typmodout => 'timestamptypmodout',
-  typalign => 'd' },
+  typalign => 'l' },
 { oid => '1184', array_type_oid => '1185',
   descr => 'date and time with time zone',
   typname => 'timestamptz', typlen => '8', typbyval => 't',
   typcategory => 'D', typispreferred => 't', typinput => 'timestamptz_in',
   typoutput => 'timestamptz_out', typreceive => 'timestamptz_recv',
   typsend => 'timestamptz_send', typmodin => 'timestamptztypmodin',
-  typmodout => 'timestamptztypmodout', typalign => 'd' },
+  typmodout => 'timestamptztypmodout', typalign => 'l' },
 { oid => '1186', array_type_oid => '1187',
   descr => 'time interval, format \'number units ...\'',
   typname => 'interval', typlen => '16', typbyval => 'f', typcategory => 'T',
   typispreferred => 't', typinput => 'interval_in', typoutput => 'interval_out',
   typreceive => 'interval_recv', typsend => 'interval_send',
   typmodin => 'intervaltypmodin', typmodout => 'intervaltypmodout',
-  typalign => 'd' },
+  typalign => 'l' },
 
 # OIDS 1200 - 1299
 
@@ -326,7 +326,7 @@
   typinput => 'timetz_in', typoutput => 'timetz_out',
   typreceive => 'timetz_recv', typsend => 'timetz_send',
   typmodin => 'timetztypmodin', typmodout => 'timetztypmodout',
-  typalign => 'd' },
+  typalign => 'l' },
 
 # OIDS 1500 - 1599
 
@@ -415,7 +415,7 @@
 { oid => '3220', array_type_oid => '3221', descr => 'PostgreSQL LSN',
   typname => 'pg_lsn', typlen => '8', typbyval => 't',
   typcategory => 'U', typinput => 'pg_lsn_in', typoutput => 'pg_lsn_out',
-  typreceive => 'pg_lsn_recv', typsend => 'pg_lsn_send', typalign => 'd' },
+  typreceive => 'pg_lsn_recv', typsend => 'pg_lsn_send', typalign => 'l' },
 
 # text search
 { oid => '3614', array_type_oid => '3643',
@@ -462,12 +462,12 @@
   typname => 'txid_snapshot', typlen => '-1', typbyval => 'f',
   typcategory => 'U', typinput => 'txid_snapshot_in',
   typoutput => 'txid_snapshot_out', typreceive => 'txid_snapshot_recv',
-  typsend => 'txid_snapshot_send', typalign => 'd', typstorage => 'x' },
+  typsend => 'txid_snapshot_send', typalign => 'l', typstorage => 'x' },
 { oid => '5038', array_type_oid => '5039', descr => 'transaction snapshot',
   typname => 'pg_snapshot', typlen => '-1', typbyval => 'f', typcategory => 'U',
   typinput => 'pg_snapshot_in', typoutput => 'pg_snapshot_out',
   typreceive => 'pg_snapshot_recv', typsend => 'pg_snapshot_send',
-  typalign => 'd', typstorage => 'x' },
+  typalign => 'l', typstorage => 'x' },
 
 # range types
 { oid => '3904', array_type_oid => '3905', descr => 'range of integers',
@@ -485,13 +485,13 @@
   typname => 'tsrange', typlen => '-1', typbyval => 'f', typtype => 'r',
   typcategory => 'R', typinput => 'range_in', typoutput => 'range_out',
   typreceive => 'range_recv', typsend => 'range_send',
-  typanalyze => 'range_typanalyze', typalign => 'd', typstorage => 'x' },
+  typanalyze => 'range_typanalyze', typalign => 'l', typstorage => 'x' },
 { oid => '3910', array_type_oid => '3911',
   descr => 'range of timestamps with time zone',
   typname => 'tstzrange', typlen => '-1', typbyval => 'f', typtype => 'r',
   typcategory => 'R', typinput => 'range_in', typoutput => 'range_out',
   typreceive => 'range_recv', typsend => 'range_send',
-  typanalyze => 'range_typanalyze', typalign => 'd', typstorage => 'x' },
+  typanalyze => 'range_typanalyze', typalign => 'l', typstorage => 'x' },
 { oid => '3912', array_type_oid => '3913', descr => 'range of dates',
   typname => 'daterange', typlen => '-1', typbyval => 'f', typtype => 'r',
   typcategory => 'R', typinput => 'range_in', typoutput => 'range_out',
@@ -501,7 +501,7 @@
   typname => 'int8range', typlen => '-1', typbyval => 'f', typtype => 'r',
   typcategory => 'R', typinput => 'range_in', typoutput => 'range_out',
   typreceive => 'range_recv', typsend => 'range_send',
-  typanalyze => 'range_typanalyze', typalign => 'd', typstorage => 'x' },
+  typanalyze => 'range_typanalyze', typalign => 'l', typstorage => 'x' },
 
 # multirange types
 { oid => '4451', array_type_oid => '6150', descr => 'multirange of integers',
@@ -522,14 +522,14 @@
   typcategory => 'R', typinput => 'multirange_in',
   typoutput => 'multirange_out', typreceive => 'multirange_recv',
   typsend => 'multirange_send', typanalyze => 'multirange_typanalyze',
-  typalign => 'd', typstorage => 'x' },
+  typalign => 'l', typstorage => 'x' },
 { oid => '4534', array_type_oid => '6153',
   descr => 'multirange of timestamps with time zone',
   typname => 'tstzmultirange', typlen => '-1', typbyval => 'f', typtype => 'm',
   typcategory => 'R', typinput => 'multirange_in',
   typoutput => 'multirange_out', typreceive => 'multirange_recv',
   typsend => 'multirange_send', typanalyze => 'multirange_typanalyze',
-  typalign => 'd', typstorage => 'x' },
+  typalign => 'l', typstorage => 'x' },
 { oid => '4535', array_type_oid => '6155', descr => 'multirange of dates',
   typname => 'datemultirange', typlen => '-1', typbyval => 'f', typtype => 'm',
   typcategory => 'R', typinput => 'multirange_in',
@@ -541,7 +541,7 @@
   typcategory => 'R', typinput => 'multirange_in',
   typoutput => 'multirange_out', typreceive => 'multirange_recv',
   typsend => 'multirange_send', typanalyze => 'multirange_typanalyze',
-  typalign => 'd', typstorage => 'x' },
+  typalign => 'l', typstorage => 'x' },
 
 # pseudo-types
 # types with typtype='p' represent various special cases in the type system.
@@ -556,14 +556,14 @@
   typname => 'record', typlen => '-1', typbyval => 'f', typtype => 'p',
   typcategory => 'P', typarray => '_record', typinput => 'record_in',
   typoutput => 'record_out', typreceive => 'record_recv',
-  typsend => 'record_send', typalign => 'd', typstorage => 'x' },
+  typsend => 'record_send', typalign => 'm', typstorage => 'x' },
 # Arrays of records have typcategory P, so they can't be autogenerated.
 { oid => '2287',
   typname => '_record', typlen => '-1', typbyval => 'f', typtype => 'p',
   typcategory => 'P', typsubscript => 'array_subscript_handler',
   typelem => 'record', typinput => 'array_in', typoutput => 'array_out',
   typreceive => 'array_recv', typsend => 'array_send',
-  typanalyze => 'array_typanalyze', typalign => 'd', typstorage => 'x' },
+  typanalyze => 'array_typanalyze', typalign => 'm', typstorage => 'x' },
 { oid => '2275', array_type_oid => '1263', descr => 'C-style string',
   typname => 'cstring', typlen => '-2', typbyval => 'f', typtype => 'p',
   typcategory => 'P', typinput => 'cstring_in', typoutput => 'cstring_out',
@@ -575,7 +575,7 @@
 { oid => '2277', descr => 'pseudo-type representing a polymorphic array type',
   typname => 'anyarray', typlen => '-1', typbyval => 'f', typtype => 'p',
   typcategory => 'P', typinput => 'anyarray_in', typoutput => 'anyarray_out',
-  typreceive => 'anyarray_recv', typsend => 'anyarray_send', typalign => 'd',
+  typreceive => 'anyarray_recv', typsend => 'anyarray_send', typalign => 'm',
   typstorage => 'x' },
 { oid => '2278',
   descr => 'pseudo-type for the result of a function with no real result',
@@ -648,7 +648,7 @@
   descr => 'pseudo-type representing a range over a polymorphic base type',
   typname => 'anyrange', typlen => '-1', typbyval => 'f', typtype => 'p',
   typcategory => 'P', typinput => 'anyrange_in', typoutput => 'anyrange_out',
-  typreceive => '-', typsend => '-', typalign => 'd', typstorage => 'x' },
+  typreceive => '-', typsend => '-', typalign => 'm', typstorage => 'x' },
 { oid => '5077',
   descr => 'pseudo-type representing a polymorphic common type',
   typname => 'anycompatible', typlen => '4', typbyval => 't', typtype => 'p',
@@ -661,7 +661,7 @@
   typtype => 'p', typcategory => 'P', typinput => 'anycompatiblearray_in',
   typoutput => 'anycompatiblearray_out',
   typreceive => 'anycompatiblearray_recv', typsend => 'anycompatiblearray_send',
-  typalign => 'd', typstorage => 'x' },
+  typalign => 'm', typstorage => 'x' },
 { oid => '5079',
   descr => 'pseudo-type representing a polymorphic common type that is not an array',
   typname => 'anycompatiblenonarray', typlen => '4', typbyval => 't',
@@ -673,19 +673,19 @@
   typname => 'anycompatiblerange', typlen => '-1', typbyval => 'f',
   typtype => 'p', typcategory => 'P', typinput => 'anycompatiblerange_in',
   typoutput => 'anycompatiblerange_out', typreceive => '-', typsend => '-',
-  typalign => 'd', typstorage => 'x' },
+  typalign => 'm', typstorage => 'x' },
 { oid => '4537',
   descr => 'pseudo-type representing a polymorphic base type that is a multirange',
   typname => 'anymultirange', typlen => '-1', typbyval => 'f', typtype => 'p',
   typcategory => 'P', typinput => 'anymultirange_in',
   typoutput => 'anymultirange_out', typreceive => '-', typsend => '-',
-  typalign => 'd', typstorage => 'x' },
+  typalign => 'm', typstorage => 'x' },
 { oid => '4538',
   descr => 'pseudo-type representing a multirange over a polymorphic common type',
   typname => 'anycompatiblemultirange', typlen => '-1', typbyval => 'f',
   typtype => 'p', typcategory => 'P', typinput => 'anycompatiblemultirange_in',
   typoutput => 'anycompatiblemultirange_out', typreceive => '-', typsend => '-',
-  typalign => 'd', typstorage => 'x' },
+  typalign => 'm', typstorage => 'x' },
 { oid => '4600', descr => 'pseudo-type representing BRIN bloom summary',
   typname => 'pg_brin_bloom_summary', typlen => '-1', typbyval => 'f',
   typcategory => 'Z', typinput => 'brin_bloom_summary_in',
@@ -704,5 +704,5 @@
   descr => 'object identifier(oid8), 8 bytes',
   typname => 'oid8', typlen => '8', typbyval => 't', typcategory => 'N',
   typinput => 'oid8in', typoutput => 'oid8out', typreceive => 'oid8recv',
-  typsend => 'oid8send', typalign => 'd' },
+  typsend => 'oid8send', typalign => 'l' },
 ]
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 70d4a20c02b..b749a47d651 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -302,7 +302,9 @@ MAKE_SYSCACHE(TYPENAMENSP, pg_type_typname_nsp_index, 64);
 #define  TYPALIGN_CHAR			'c' /* char alignment (i.e. unaligned) */
 #define  TYPALIGN_SHORT			's' /* short alignment (typically 2 bytes) */
 #define  TYPALIGN_INT			'i' /* int alignment (typically 4 bytes) */
+#define  TYPALIGN_INT64			'l' /* int64 alignment (often 8 bytes) */
 #define  TYPALIGN_DOUBLE		'd' /* double alignment (often 8 bytes) */
+#define  TYPALIGN_MAX			'm' /* maximum alignment (usually 8 bytes) */
 
 #define  TYPSTORAGE_PLAIN		'p' /* type not prepared for toasting */
 #define  TYPSTORAGE_EXTERNAL	'e' /* toastable, don't try to compress */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 339268dc8ef..5699c033ade 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -12,9 +12,6 @@
 /* The normal alignment of `int64_t', in bytes. */
 #undef ALIGNOF_INT64_T
 
-/* The normal alignment of `long', in bytes. */
-#undef ALIGNOF_LONG
-
 /* The normal alignment of `PG_INT128_TYPE', in bytes. */
 #undef ALIGNOF_PG_INT128_TYPE
 
diff --git a/src/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 2522cae0c31..0b544bd184c 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -398,60 +398,19 @@ typedef unsigned int slock_t;
 
 #define TAS(lock) tas(lock)
 
-/* On PPC, it's a win to use a non-locking test before the lwarx */
+/* On PPC, use the compiler provided Built-in functions for atomic memory
+ * exchange operations.
+ */
 #define TAS_SPIN(lock)	(*(lock) ? 1 : TAS(lock))
 
-/*
- * The second operand of addi can hold a constant zero or a register number,
- * hence constraint "=&b" to avoid allocating r0.  "b" stands for "address
- * base register"; most operands having this register-or-zero property are
- * address bases, e.g. the second operand of lwax.
- *
- * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002,
- * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop.
- * But if the spinlock is in ordinary memory, we can use lwsync instead for
- * better performance.
- */
 static __inline__ int
 tas(volatile slock_t *lock)
 {
-	slock_t _t;
-	int _res;
-
-	__asm__ __volatile__(
-"	lwarx   %0,0,%3,1	\n"
-"	cmpwi   %0,0		\n"
-"	bne     1f			\n"
-"	addi    %0,%0,1		\n"
-"	stwcx.  %0,0,%3		\n"
-"	beq     2f			\n"
-"1: \n"
-"	li      %1,1		\n"
-"	b       3f			\n"
-"2: \n"
-"	lwsync				\n"
-"	li      %1,0		\n"
-"3: \n"
-:	"=&b"(_t), "=r"(_res), "+m"(*lock)
-:	"r"(lock)
-:	"memory", "cc");
-	return _res;
+  return __sync_lock_test_and_set(lock, 1);
 }
-
-/*
- * PowerPC S_UNLOCK is almost standard but requires a "sync" instruction.
- * But we can use lwsync instead for better performance.
- */
-#define S_UNLOCK(lock)	\
-do \
-{ \
-	__asm__ __volatile__ ("	lwsync \n" ::: "memory"); \
-	*((volatile slock_t *) (lock)) = 0; \
-} while (0)
-
+#define S_UNLOCK(lock) __sync_lock_release(lock)
 #endif /* powerpc */
 
-
 #if defined(__mips__) && !defined(__sgi)	/* non-SGI MIPS */
 #define HAS_TEST_AND_SET
 
diff --git a/src/include/utils/.gitignore b/src/include/utils/.gitignore
index 30f921429c6..ff6f61cd7ee 100644
--- a/src/include/utils/.gitignore
+++ b/src/include/utils/.gitignore
@@ -4,4 +4,6 @@
 /probes.h
 /errcodes.h
 /header-stamp
+/pgstat_wait_event.c
+/wait_event_funcs_data.c
 /wait_event_types.h
diff --git a/src/interfaces/ecpg/compatlib/meson.build b/src/interfaces/ecpg/compatlib/meson.build
index 6cb1be73407..94dcc67c03c 100644
--- a/src/interfaces/ecpg/compatlib/meson.build
+++ b/src/interfaces/ecpg/compatlib/meson.build
@@ -20,17 +20,19 @@ ecpg_compat_st = static_library('libecpg_compat',
   ecpg_compat_sources,
   include_directories: ecpg_compat_inc,
   c_args: ecpg_compat_c_args,
-  dependencies: [frontend_stlib_code, thread_dep],
+  dependencies: [dep_static_lib, frontend_stlib_code, thread_dep],
   link_with: [ecpglib_st, ecpg_pgtypes_st],
   kwargs: default_lib_args,
 )
-ecpg_targets += ecpg_compat_st
+if dep_static_lib.found()
+  ecpg_targets += ecpg_compat_st
+endif
 
 ecpg_compat_so = shared_library('libecpg_compat',
   ecpg_compat_sources + ecpg_compat_so_sources,
   include_directories: ecpg_compat_inc,
   c_args: ecpg_compat_c_args,
-  dependencies: [frontend_shlib_code, thread_dep],
+  dependencies: [dep_shared_lib, frontend_shlib_code, thread_dep],
   link_with: [ecpglib_so, ecpg_pgtypes_so],
   soversion: host_system != 'windows' ? '3' : '',
   darwin_versions: ['3', '3.' + pg_version_major.to_string()],
diff --git a/src/interfaces/ecpg/ecpglib/meson.build b/src/interfaces/ecpg/ecpglib/meson.build
index 889bd9efd65..a81d772aa69 100644
--- a/src/interfaces/ecpg/ecpglib/meson.build
+++ b/src/interfaces/ecpg/ecpglib/meson.build
@@ -30,18 +30,20 @@ ecpglib_st = static_library('libecpg',
   include_directories: ecpglib_inc,
   c_args: ecpglib_c_args,
   c_pch: pch_postgres_fe_h,
-  dependencies: [frontend_stlib_code, thread_dep, libpq],
+  dependencies: [dep_static_lib, frontend_stlib_code, thread_dep, libpq],
   link_with: [ecpg_pgtypes_st],
   kwargs: default_lib_args,
 )
-ecpg_targets += ecpglib_st
+if dep_static_lib.found()
+  ecpg_targets += ecpglib_st
+endif
 
 ecpglib_so = shared_library('libecpg',
   ecpglib_sources + ecpglib_so_sources,
   include_directories: ecpglib_inc,
   c_args: ecpglib_c_args,
   c_pch: pch_postgres_fe_h,
-  dependencies: [frontend_shlib_code, libpq, thread_dep],
+  dependencies: [dep_shared_lib, frontend_shlib_code, libpq, thread_dep],
   link_with: ecpg_pgtypes_so,
   soversion: host_system != 'windows' ? '6' : '',
   darwin_versions: ['6', '6.' + pg_version_major.to_string()],
diff --git a/src/interfaces/ecpg/pgtypeslib/meson.build b/src/interfaces/ecpg/pgtypeslib/meson.build
index 6b78f529e53..019cf0e36f6 100644
--- a/src/interfaces/ecpg/pgtypeslib/meson.build
+++ b/src/interfaces/ecpg/pgtypeslib/meson.build
@@ -26,17 +26,20 @@ ecpg_pgtypes_st = static_library('libpgtypes',
   include_directories: ecpg_pgtypes_inc,
   c_args: ecpg_pgtypes_c_args,
   c_pch: pch_postgres_fe_h,
-  dependencies: frontend_stlib_code,
+  dependencies: [dep_static_lib, frontend_stlib_code],
   kwargs: default_lib_args,
 )
-ecpg_targets += ecpg_pgtypes_st
+
+if dep_static_lib.found()
+  ecpg_targets += ecpg_pgtypes_st
+endif
 
 ecpg_pgtypes_so = shared_library('libpgtypes',
   ecpg_pgtypes_sources + ecpg_pgtypes_so_sources,
   include_directories: ecpg_pgtypes_inc,
   c_args: ecpg_pgtypes_c_args,
   c_pch: pch_postgres_fe_h,
-  dependencies: frontend_shlib_code,
+  dependencies: [dep_shared_lib, frontend_shlib_code],
   version: '3.' + pg_version_major.to_string(),
   soversion: host_system != 'windows' ? '3' : '',
   darwin_versions: ['3', '3.' + pg_version_major.to_string()],
diff --git a/src/interfaces/libpq-oauth/meson.build b/src/interfaces/libpq-oauth/meson.build
index d8a0c04095a..b0083f279aa 100644
--- a/src/interfaces/libpq-oauth/meson.build
+++ b/src/interfaces/libpq-oauth/meson.build
@@ -26,6 +26,7 @@ libpq_oauth_st = static_library('libpq-oauth',
   include_directories: [libpq_oauth_inc, postgres_inc],
   c_pch: pch_postgres_fe_h,
   dependencies: [
+    dep_static_lib,
     frontend_stlib_code,
     libpq_oauth_deps,
     ssl, # libpq-int.h includes OpenSSL headers
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index c5ecd9c3a87..cb75f96c6a2 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -62,7 +62,7 @@ libpq_st = static_library('libpq',
   include_directories: [libpq_inc],
   c_args: libpq_c_args,
   c_pch: pch_postgres_fe_h,
-  dependencies: [frontend_stlib_code, libpq_deps],
+  dependencies: [dep_static_lib, frontend_stlib_code, libpq_deps],
   kwargs: default_lib_args,
 )
 
@@ -74,7 +74,7 @@ libpq_so = shared_library('libpq',
   version: '5.' + pg_version_major.to_string(),
   soversion: host_system != 'windows' ? '5' : '',
   darwin_versions: ['5', '5.' + pg_version_major.to_string()],
-  dependencies: [frontend_shlib_code, libpq_deps],
+  dependencies: [dep_shared_lib, frontend_shlib_code, libpq_deps],
   link_depends: export_file,
   link_args: export_fmt.format(export_file.full_path()),
   kwargs: default_lib_args,
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100755
index 00000000000..42bdbade5bb
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,39 @@
+# -blibpath:
+# The path to be inserted into the default path (Index 0 path) field of the
+# loader section. When this flag is presented, the -L paths will not be stored.
+# AIX uses a stricter, more explicit approach. The runtime linker expects to
+# tell it exactly where to look using -blibpath.
+# -blibpath must contain ALL directories where we should look for libraries
+libpath := $(shell echo $(subst -L,:,$(filter -L/%,$(LDFLAGS))) | sed -e's/ //g'):/usr/lib:/lib
+
+# when building with gcc, need to make sure that libgcc can be found
+ifeq ($(GCC), yes)
+libpath += :$(libpath):$(dir $(shell gcc -print-libgcc-file-name))
+endif
+
+# AIX uses a stricter, more explicit approach. The runtime linker expects
+# to tell it exactly where to look using -blibpath.
+rpath = -Wl,-blibpath:'$(rpathdir)$(libpath)'
+
+# gcc needs to know it's building a shared lib, otherwise it'll not emit
+# correct code / link to the right support libraries
+ifeq ($(GCC), yes)
+LDFLAGS_SL += -shared
+endif
+
+# env var name to use in place of LD_LIBRARY_PATH
+ld_library_path_var = LIBPATH
+
+POSTGRES_IMP= postgres.imp
+
+ifdef PGXS
+BE_DLLLIBS= -Wl,-bI:$(pkglibdir)/$(POSTGRES_IMP)
+else
+BE_DLLLIBS= -Wl,-bI:$(top_builddir)/src/backend/$(POSTGRES_IMP)
+endif
+
+MKLDEXPORT_DIR=src/backend/port/aix
+MKLDEXPORT=$(top_srcdir)/$(MKLDEXPORT_DIR)/mkldexport.sh
+
+%$(DLSUFFIX): %.o
+    $(CC) $(CFLAGS) $*.o $(LDFLAGS) $(LDFLAGS_SL) -o $@ $(BE_DLLLIBS)
diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c
index 1f69109b081..91e40327788 100644
--- a/src/pl/plpython/plpy_typeio.c
+++ b/src/pl/plpython/plpy_typeio.c
@@ -329,7 +329,7 @@ PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt,
 		/* hard-wired knowledge about type RECORD: */
 		arg->typbyval = false;
 		arg->typlen = -1;
-		arg->typalign = TYPALIGN_DOUBLE;
+		arg->typalign = TYPALIGN_MAX;
 	}
 
 	/*
@@ -452,7 +452,7 @@ PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt,
 		/* hard-wired knowledge about type RECORD: */
 		arg->typbyval = false;
 		arg->typlen = -1;
-		arg->typalign = TYPALIGN_DOUBLE;
+		arg->typalign = TYPALIGN_MAX;
 	}
 
 	/*
diff --git a/src/port/meson.build b/src/port/meson.build
index d7d4e705b89..a8d92937581 100644
--- a/src/port/meson.build
+++ b/src/port/meson.build
@@ -192,6 +192,7 @@ foreach name, opts : pgport_variants
       c_pch: pch_c_h,
       kwargs: opts + {
         'dependencies': opts['dependencies'] + [ssl],
+        'install': dep_static_lib.found(),
       }
     )
   pgport += {name: lib}
diff --git a/src/port/strerror.c b/src/port/strerror.c
index 76af67ec2d0..ebd91bda73b 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,7 +214,9 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
+#endif
 			return "ENOTEMPTY";
 		case ENOTSOCK:
 			return "ENOTSOCK";
diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expected/float8.out
index 9c519f1a1a1..a688cbc3c83 100644
--- a/src/test/regress/expected/float8.out
+++ b/src/test/regress/expected/float8.out
@@ -1088,8 +1088,10 @@ LINE 1: ...8 (input = xfloat8in, output = xfloat8out, like = no_such_ty...
 create type xfloat8 (input = xfloat8in, output = xfloat8out, like = float8);
 create cast (xfloat8 as float8) without function;
 create cast (float8 as xfloat8) without function;
-create cast (xfloat8 as bigint) without function;
-create cast (bigint as xfloat8) without function;
+-- this hack depends on bigint and float8 having the same pass-by-value-ness:
+create function bigint_xfloat8(bigint) returns xfloat8 immutable strict
+  language internal as 'int8up';
+create cast (bigint as xfloat8) with function bigint_xfloat8(bigint);
 -- float8: seeeeeee eeeeeeee eeeeeeee mmmmmmmm mmmmmmmm(x4)
 -- we don't care to assume the platform's strtod() handles subnormals
 -- correctly; those are "use at your own risk". However we do test
@@ -1503,5 +1505,5 @@ DETAIL:  drop cascades to function xfloat8in(cstring)
 drop cascades to function xfloat8out(xfloat8)
 drop cascades to cast from xfloat8 to double precision
 drop cascades to cast from double precision to xfloat8
-drop cascades to cast from xfloat8 to bigint
+drop cascades to function bigint_xfloat8(bigint)
 drop cascades to cast from bigint to xfloat8
diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out
index 1d21d3eb446..936fa36a600 100644
--- a/src/test/regress/expected/type_sanity.out
+++ b/src/test/regress/expected/type_sanity.out
@@ -23,7 +23,7 @@ WHERE t1.typnamespace = 0 OR
     (t1.typlen <= 0 AND t1.typlen != -1 AND t1.typlen != -2) OR
     (t1.typtype not in ('b', 'c', 'd', 'e', 'm', 'p', 'r')) OR
     NOT t1.typisdefined OR
-    (t1.typalign not in ('c', 's', 'i', 'd')) OR
+    (t1.typalign not in ('c', 's', 'i', 'l', 'd', 'm')) OR
     (t1.typstorage not in ('p', 'x', 'e', 'm'));
  oid | typname 
 -----+---------
@@ -36,7 +36,7 @@ WHERE t1.typbyval AND
     (t1.typlen != 1 OR t1.typalign != 'c') AND
     (t1.typlen != 2 OR t1.typalign != 's') AND
     (t1.typlen != 4 OR t1.typalign != 'i') AND
-    (t1.typlen != 8 OR t1.typalign != 'd');
+    (t1.typlen != 8 OR (t1.typalign != 'l' AND t1.typalign != 'd'));
  oid | typname 
 -----+---------
 (0 rows)
@@ -108,6 +108,8 @@ FROM pg_type as t1
      LEFT JOIN pg_type as t2 ON rngsubtype = t2.oid
 WHERE t1.typtype = 'r' AND
     (t1.typalign != (CASE WHEN t2.typalign = 'd' THEN 'd'::"char"
+                          WHEN t2.typalign = 'l' THEN 'l'::"char"
+                          WHEN t2.typalign = 'm' THEN 'm'::"char"
                           ELSE 'i'::"char" END)
      OR t2.oid IS NULL);
  oid | typname | typalign | typname | typalign 
@@ -423,6 +425,8 @@ SELECT t1.oid, t1.typname, t1.typalign, t2.typname, t2.typalign
 FROM pg_type AS t1, pg_type AS t2
 WHERE t1.typarray = t2.oid AND
     t2.typalign != (CASE WHEN t1.typalign = 'd' THEN 'd'::"char"
+                         WHEN t1.typalign = 'l' THEN 'l'::"char"
+                         WHEN t1.typalign = 'm' THEN 'm'::"char"
                          ELSE 'i'::"char" END);
  oid | typname | typalign | typname | typalign 
 -----+---------+----------+---------+----------
diff --git a/src/test/regress/sql/float8.sql b/src/test/regress/sql/float8.sql
index 0ef271f2702..c6b59a322ab 100644
--- a/src/test/regress/sql/float8.sql
+++ b/src/test/regress/sql/float8.sql
@@ -355,8 +355,10 @@ create type xfloat8 (input = xfloat8in, output = xfloat8out, like = no_such_type
 create type xfloat8 (input = xfloat8in, output = xfloat8out, like = float8);
 create cast (xfloat8 as float8) without function;
 create cast (float8 as xfloat8) without function;
-create cast (xfloat8 as bigint) without function;
-create cast (bigint as xfloat8) without function;
+-- this hack depends on bigint and float8 having the same pass-by-value-ness:
+create function bigint_xfloat8(bigint) returns xfloat8 immutable strict
+  language internal as 'int8up';
+create cast (bigint as xfloat8) with function bigint_xfloat8(bigint);
 
 -- float8: seeeeeee eeeeeeee eeeeeeee mmmmmmmm mmmmmmmm(x4)
 
diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql
index 95d5b6e0915..625305c42bc 100644
--- a/src/test/regress/sql/type_sanity.sql
+++ b/src/test/regress/sql/type_sanity.sql
@@ -28,7 +28,7 @@ WHERE t1.typnamespace = 0 OR
     (t1.typlen <= 0 AND t1.typlen != -1 AND t1.typlen != -2) OR
     (t1.typtype not in ('b', 'c', 'd', 'e', 'm', 'p', 'r')) OR
     NOT t1.typisdefined OR
-    (t1.typalign not in ('c', 's', 'i', 'd')) OR
+    (t1.typalign not in ('c', 's', 'i', 'l', 'd', 'm')) OR
     (t1.typstorage not in ('p', 'x', 'e', 'm'));
 
 -- Look for "pass by value" types that can't be passed by value.
@@ -39,7 +39,7 @@ WHERE t1.typbyval AND
     (t1.typlen != 1 OR t1.typalign != 'c') AND
     (t1.typlen != 2 OR t1.typalign != 's') AND
     (t1.typlen != 4 OR t1.typalign != 'i') AND
-    (t1.typlen != 8 OR t1.typalign != 'd');
+    (t1.typlen != 8 OR (t1.typalign != 'l' AND t1.typalign != 'd'));
 
 -- Look for "toastable" types that aren't varlena.
 
@@ -90,6 +90,8 @@ FROM pg_type as t1
      LEFT JOIN pg_type as t2 ON rngsubtype = t2.oid
 WHERE t1.typtype = 'r' AND
     (t1.typalign != (CASE WHEN t2.typalign = 'd' THEN 'd'::"char"
+                          WHEN t2.typalign = 'l' THEN 'l'::"char"
+                          WHEN t2.typalign = 'm' THEN 'm'::"char"
                           ELSE 'i'::"char" END)
      OR t2.oid IS NULL);
 
@@ -302,6 +304,8 @@ SELECT t1.oid, t1.typname, t1.typalign, t2.typname, t2.typalign
 FROM pg_type AS t1, pg_type AS t2
 WHERE t1.typarray = t2.oid AND
     t2.typalign != (CASE WHEN t1.typalign = 'd' THEN 'd'::"char"
+                         WHEN t1.typalign = 'l' THEN 'l'::"char"
+                         WHEN t1.typalign = 'm' THEN 'm'::"char"
                          ELSE 'i'::"char" END);
 
 -- Check for typelem set without a handler
diff --git a/src/tools/gen_export.pl b/src/tools/gen_export.pl
index 515f6d4a7a6..b385fa62c3b 100644
--- a/src/tools/gen_export.pl
+++ b/src/tools/gen_export.pl
@@ -18,7 +18,8 @@ GetOptions(
 
 if (not(   $format eq 'darwin'
 		or $format eq 'gnu'
-		or $format eq 'win'))
+		or $format eq 'win'
+        or $format eq 'aix'))
 {
 	die "$0: $format is not yet handled (only darwin, gnu, win are)\n";
 }
@@ -46,6 +47,10 @@ elsif ($format eq 'win')
 	}
 	print $output_handle "EXPORTS\n";
 }
+elsif ($format eq 'aix')
+{
+	print $output_handle "#!\n";
+}
 
 while (<$input_handle>)
 {
@@ -63,6 +68,10 @@ while (<$input_handle>)
 		{
 			print $output_handle "    $1;\n";
 		}
+        elsif ($format eq 'aix')
+        {
+            print $output_handle "$1\n";
+        }
 		elsif ($format eq 'win')
 		{
 			print $output_handle "$1 @ $2\n";
-- 
2.51.2

