AIX support

Started by Sriram RKalmost 2 years ago126 messages
#1Sriram RK
sriram.rk@outlook.com

Hello Team,

We are working on AIX systems and noticed that the thread on removing AIX support in Postgres going forward.

https://github.com/postgres/postgres/commit/0b16bb8776bb834eb1ef8204ca95dd7667ab948b”

We would be glad to understand any outstanding issues hindering the support on AIX.
It is important for us to have Postgres to be supported on AIX. As we are using Postgres extensively on AIX.
Also we would like to provide any feasible support from our end for enabling the support on AIX.

We would request the community to extend the support on AIX ..

Thanks & regards,
Sriram.

#2Alvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Sriram RK (#1)
Re: AIX support

On 2024-Mar-21, Sriram RK wrote:

Hello Team,

We are working on AIX systems and noticed that the thread on removing AIX support in Postgres going forward.

https://github.com/postgres/postgres/commit/0b16bb8776bb834eb1ef8204ca95dd7667ab948b”

We would be glad to understand any outstanding issues hindering the support on AIX.

There's a Discussion link at the bottom of that commit message. I
suggest you read that discussion complete, and consider how much effort
you or your company are willing to spend on doing the maintenance of the
port yourselves for the community. Maybe ponder this question: would it
be less onerous to migrate your Postgres servers to Linux, like Phil
Florent described on the currently-last message of that thread?

--
Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/
"Para tener más hay que desear menos"

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Sriram RK (#1)
Re: AIX support

Sriram RK <sriram.rk@outlook.com> writes:

We are working on AIX systems and noticed that the thread on removing AIX support in Postgres going forward.
https://github.com/postgres/postgres/commit/0b16bb8776bb834eb1ef8204ca95dd7667ab948b
We would be glad to understand any outstanding issues hindering the
support on AIX.

Did you read the linked thread? Starting say about here:

/messages/by-id/20240224172345.32@rfd.leadboat.com

Also we would like to provide any feasible support from our end for enabling the support on AIX.

Who is "we", and how much resources are you prepared to put into this?

We would request the community to extend the support on AIX ..

The community, in the sense of the existing people doing significant
work on Postgres, are absolutely not going to do that. If you can
bring a bunch of work to fix all the problems noted in the discussion
thread, and commit to providing ongoing development manpower and
hardware to keep it working, maybe something could happen. But I
suspect you will find it cheaper to start thinking about migrating
off AIX.

regards, tom lane

#4Sriram RK
sriram.rk@outlook.com
In reply to: Tom Lane (#3)
Re: AIX support

Thanks, Tom and Alvaro, for the info.
We shall look into to details and get back.

From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thursday, 21 March 2024 at 7:27 PM
To: Sriram RK <sriram.rk@outlook.com>
Cc: pgsql-hackers@postgresql.org <pgsql-hackers@postgresql.org>
Subject: Re: AIX support
Sriram RK <sriram.rk@outlook.com> writes:

We are working on AIX systems and noticed that the thread on removing AIX support in Postgres going forward.
https://github.com/postgres/postgres/commit/0b16bb8776bb834eb1ef8204ca95dd7667ab948b
We would be glad to understand any outstanding issues hindering the
support on AIX.

Did you read the linked thread? Starting say about here:

/messages/by-id/20240224172345.32@rfd.leadboat.com

Also we would like to provide any feasible support from our end for enabling the support on AIX.

Who is "we", and how much resources are you prepared to put into this?

We would request the community to extend the support on AIX ..

The community, in the sense of the existing people doing significant
work on Postgres, are absolutely not going to do that. If you can
bring a bunch of work to fix all the problems noted in the discussion
thread, and commit to providing ongoing development manpower and
hardware to keep it working, maybe something could happen. But I
suspect you will find it cheaper to start thinking about migrating
off AIX.

regards, tom lane

#5Sriram RK
sriram.rk@outlook.com
In reply to: Sriram RK (#4)
Re: AIX support

Hi Team,

We are setting up the build environment and trying to build the source and also trying to analyze the assert from the Aix point of view.

Also, would like to know if we can access the buildfarm(power machines) to run any of the specific tests to hit this assert.

Thanks & regards,
Sriram.

Show quoted text

From: Sriram RK <sriram.rk@outlook.com>
Date: Thursday, 21 March 2024 at 10:05 PM
To: Tom Lane tgl@sss.pgh.pa.us<mailto:tgl@sss.pgh.pa.us>, Alvaro Herrera <alvherre@alvh.no-ip.org>
Cc: pgsql-hackers@postgresql.org<mailto:pgsql-hackers@postgresql.org> <pgsql-hackers@postgresql.org>
Subject: Re: AIX support
Thanks, Tom and Alvaro, for the info.
We shall look into to details and get back.

#6Noah Misch
noah@leadboat.com
In reply to: Sriram RK (#5)
Re: AIX support

On Thu, Mar 28, 2024 at 11:09:43AM +0000, Sriram RK wrote:

We are setting up the build environment and trying to build the source and also trying to analyze the assert from the Aix point of view.

The thread Alvaro and Tom cited contains an analysis. It's a compiler bug.
You can get past the compiler bug by upgrading your compiler; both ibm-clang
17.1.1.2 and gcc 13.2.0 are free from the bug.

Also, would like to know if we can access the buildfarm(power machines) to run any of the specific tests to hit this assert.

https://portal.cfarm.net/users/new/ is the form to request access. It lists
the eligibility criteria.

#7Thomas Munro
thomas.munro@gmail.com
In reply to: Noah Misch (#6)
Re: AIX support

On Fri, Mar 29, 2024 at 3:48 PM Noah Misch <noah@leadboat.com> wrote:

On Thu, Mar 28, 2024 at 11:09:43AM +0000, Sriram RK wrote:

We are setting up the build environment and trying to build the source and also trying to analyze the assert from the Aix point of view.

The thread Alvaro and Tom cited contains an analysis. It's a compiler bug.
You can get past the compiler bug by upgrading your compiler; both ibm-clang
17.1.1.2 and gcc 13.2.0 are free from the bug.

For the specific issue that triggered that, I strongly suspect that it
would go away if we just used smgrzeroextend() instead of smgrextend()
using that variable with the alignment requirement, since, as far as I
can tell from build farm clues, the otherwise similar function-local
static variable used by the former (ie one that the linker must still
control the location of AFAIK?) seems to work fine.

But we didn't remove AIX because of that, it was just the straw that
broke the camel's back.

#8Tom Lane
tgl@sss.pgh.pa.us
In reply to: Noah Misch (#6)
Re: AIX support

Noah Misch <noah@leadboat.com> writes:

On Thu, Mar 28, 2024 at 11:09:43AM +0000, Sriram RK wrote:

Also, would like to know if we can access the buildfarm(power machines) to run any of the specific tests to hit this assert.

https://portal.cfarm.net/users/new/ is the form to request access. It lists
the eligibility criteria.

There might be some confusion here about what system we are talking
about. The Postgres buildfarm is described at
https://buildfarm.postgresql.org/index.html
but it consists of a large number of individual machines run by
individual owners. There would not be a lot of point in adding a
new AIX machine to the Postgres buildfarm right now, because it
would surely fail to build HEAD. What Noah is referencing is
the GCC compile farm, which happens to include some AIX machines.
The existing AIX entries in the Postgres buildfarm are run (by Noah)
on those GCC compile farm machines, which really the GCC crowd have
been *very* forgiving about letting us abuse like that. If you have
your own AIX hardware there's not a lot of reason that you should
need to access the GCC farm.

What you do need to do to reproduce the described problems is
check out the Postgres git tree and rewind to just before
commit 0b16bb877, where we deleted AIX support. Any attempt
to restore AIX support would have to start with reverting that
commit (and perhaps the followup f0827b443).

regards, tom lane

#9Thomas Munro
thomas.munro@gmail.com
In reply to: Thomas Munro (#7)
Re: AIX support

On Fri, Mar 29, 2024 at 4:00 PM Thomas Munro <thomas.munro@gmail.com> wrote:

On Fri, Mar 29, 2024 at 3:48 PM Noah Misch <noah@leadboat.com> wrote:

The thread Alvaro and Tom cited contains an analysis. It's a compiler bug.
You can get past the compiler bug by upgrading your compiler; both ibm-clang
17.1.1.2 and gcc 13.2.0 are free from the bug.

For the specific issue that triggered that, I strongly suspect that it
would go away if we just used smgrzeroextend() instead of smgrextend()
using that variable with the alignment requirement, since, as far as I
can tell from build farm clues, the otherwise similar function-local
static variable used by the former (ie one that the linker must still
control the location of AFAIK?) seems to work fine.

Oh, sorry, I had missed the part where newer compilers fix the issue
too. Old out-of-support versions of AIX running old compilers, what
fun.

#10Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Munro (#9)
Re: AIX support

Thomas Munro <thomas.munro@gmail.com> writes:

Oh, sorry, I had missed the part where newer compilers fix the issue
too. Old out-of-support versions of AIX running old compilers, what
fun.

Indeed. One of the topics that needs investigation if you want to
pursue this is which AIX system and compiler versions still deserve
support, and which of the AIX hacks we had been carrying still need
to be there based on that analysis. For context, we've been pruning
support for extinct-in-the-wild OS versions pretty aggressively
over the past couple of years, and I'd expect to apply the same
standard to AIX.

regards, tom lane

#11Sriram RK
sriram.rk@outlook.com
In reply to: Tom Lane (#10)
Re: AIX support

What you do need to do to reproduce the described problems is
check out the Postgres git tree and rewind to just before
commit 0b16bb877, where we deleted AIX support. Any attempt
to restore AIX support would have to start with reverting that
commit (and perhaps the followup f0827b443).

regards, tom lane

Hi Team, thank you for all the info.

We progressed to build the source on our nodes and the build was successful with the below configuration.

Postgres - github-bcdfa5f2e2f
AIX - 71c
Xlc - 13.1.0
Bison - 3.0.5

Going ahead, we want to build the changes that were removed as part of “0b16bb8776bb8”, with latest Xlc and gcc version.

We were building the source from the postgres ftp server(https://ftp.postgresql.org/pub/source/), would like to understand if there are any source level changes between the ftp server and the source on github?

Regards,
Sriram.

From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Friday, 29 March 2024 at 9:03 AM
To: Thomas Munro <thomas.munro@gmail.com>
Cc: Noah Misch <noah@leadboat.com>, Sriram RK <sriram.rk@outlook.com>, Alvaro Herrera <alvherre@alvh.no-ip.org>, pgsql-hackers@postgresql.org <pgsql-hackers@postgresql.org>
Subject: Re: AIX support
Thomas Munro <thomas.munro@gmail.com> writes:

Oh, sorry, I had missed the part where newer compilers fix the issue
too. Old out-of-support versions of AIX running old compilers, what
fun.

Indeed. One of the topics that needs investigation if you want to
pursue this is which AIX system and compiler versions still deserve
support, and which of the AIX hacks we had been carrying still need
to be there based on that analysis. For context, we've been pruning
support for extinct-in-the-wild OS versions pretty aggressively
over the past couple of years, and I'd expect to apply the same
standard to AIX.

regards, tom lane

#12Noah Misch
noah@leadboat.com
In reply to: Sriram RK (#11)
Re: AIX support

On Fri, Apr 05, 2024 at 04:12:06PM +0000, Sriram RK wrote:

What you do need to do to reproduce the described problems is
check out the Postgres git tree and rewind to just before
commit 0b16bb877, where we deleted AIX support. Any attempt
to restore AIX support would have to start with reverting that
commit (and perhaps the followup f0827b443).

Going ahead, we want to build the changes that were removed as part of “0b16bb8776bb8”, with latest Xlc and gcc version.

We were building the source from the postgres ftp server(https://ftp.postgresql.org/pub/source/), would like to understand if there are any source level changes between the ftp server and the source on github?

To succeed in this endeavor, you'll need to develop fluency in the tools to
answer questions like that, or bring in someone who is fluent. In this case,
GNU diff is the standard tool for answering your question. These resources
cover other topics you would need to learn:

https://wiki.postgresql.org/wiki/Developer_FAQ
https://wiki.postgresql.org/wiki/So,_you_want_to_be_a_developer%3F

#13Sriram RK
sriram.rk@outlook.com
In reply to: Noah Misch (#12)
Re: AIX support

Thanks Noah and Team,

We (IBM-AIX team) looked into this issue

/messages/by-id/20240225194322.a5@rfd.leadboat.com

This is related to the compiler issue. The compilers xlc(13.1) and gcc(8.0) have issues. But we verified that this issue is resolved with the newer compiler versions openXL(xlc17.1) and gcc(12.0) onwards.

We reported this issue to the xlc team and they have noted this issue. A fix might be possible in May for this issue in xlc v16. We would like to understand if the community can start using the latest compilers to build the source.

Also as part of the support, we will help in fixing all the issues related to AIX and continue to support AIX for Postgres. If we need another CI environment we can work to make one available. But for time being can we start reverting the patch that has removed AIX support.

We want to make a note that postgres is used extensively in our IBM product and is being exploited by multiple customers.

Please let us know if there are any specific details you'd like to discuss further.

Regards,
Sriram.

#14Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Sriram RK (#13)
Re: AIX support

On 18 April 2024 14:15:43 GMT+03:00, Sriram RK <sriram.rk@outlook.com> wrote:

Thanks Noah and Team,

We (IBM-AIX team) looked into this issue

/messages/by-id/20240225194322.a5@rfd.leadboat.com

This is related to the compiler issue. The compilers xlc(13.1) and gcc(8.0) have issues. But we verified that this issue is resolved with the newer compiler versions openXL(xlc17.1) and gcc(12.0) onwards.

We reported this issue to the xlc team and they have noted this issue. A fix might be possible in May for this issue in xlc v16. We would like to understand if the community can start using the latest compilers to build the source.

Also as part of the support, we will help in fixing all the issues related to AIX and continue to support AIX for Postgres. If we need another CI environment we can work to make one available. But for time being can we start reverting the patch that has removed AIX support.

Let's start by setting up a new AIX buildfarm member. Regardless of what we do with v17, we continue to support AIX on the stable branches, and we really need a buildfarm member to keep the stable branches working anyway.

We want to make a note that postgres is used extensively in our IBM product and is being exploited by multiple customers.

Noted. I'm glad to hear you are interested to put in some effort for this. The situation from the current maintainers is that none of us have much interest, or resources or knowledge to keep the AIX build working, so we'll definitely need the help.

No promises on v17, but let's at least make sure the stable branches keep working. And with the patches and buildfarm support from you, maybe v17 is feasible too.

- Heikki

#15Sriram RK
sriram.rk@outlook.com
In reply to: Heikki Linnakangas (#14)
Re: AIX support

Let's start by setting up a new AIX buildfarm member. Regardless of what we do with v17, we continue to support AIX on the stable branches, and we really need a buildfarm member to keep the stable branches working anyway.

Thanks Heikki. We had already build the source code(v17+ bcdfa5f2e2f) on our local nodes. We will try to setup the buildfarm and let you know.
Is there any specific configuration we are looking for?

Regards,
Sriram.

#16Andres Freund
andres@anarazel.de
In reply to: Sriram RK (#13)
Re: AIX support

Hi,

On 2024-04-18 11:15:43 +0000, Sriram RK wrote:

We (IBM-AIX team) looked into this issue

/messages/by-id/20240225194322.a5@rfd.leadboat.com

This is related to the compiler issue. The compilers xlc(13.1) and gcc(8.0)
have issues. But we verified that this issue is resolved with the newer
compiler versions openXL(xlc17.1) and gcc(12.0) onwards.

The reason we used these compilers was that those were the only ones we had
kinda somewhat reasonable access to, via the gcc projects'
"compile farm" https://portal.cfarm.net/
We have to rely on whatever the aix machines there provide. They're not
particularly plentiful resource-wise either.

This is generally one of the big issues with AIX support. There are other
niche-y OSs that don't have a lot of users, e.g. openbsd, but in contrast to
AIX I can just start an openbsd VM within a few minutes and iron out whatever
portability issue I'm dealing with.

Not being AIX customers we also can't raise bugs about compiler bugs, so we're
stuck doing bad workarounds.

Also as part of the support, we will help in fixing all the issues related
to AIX and continue to support AIX for Postgres. If we need another CI
environment we can work to make one available. But for time being can we
start reverting the patch that has removed AIX support.

The state when was removed was not in a state that I am OK with adding back.

We want to make a note that postgres is used extensively in our IBM product
and is being exploited by multiple customers.

To be blunt: Then it'd have been nice to see some investment in that before
now. Both on the code level and the infrastructure level (i.e. access to
machines etc).

Greetings,

Andres Freund

#17Thomas Munro
thomas.munro@gmail.com
In reply to: Andres Freund (#16)
Re: AIX support

On Fri, Apr 19, 2024 at 6:01 AM Andres Freund <andres@anarazel.de> wrote:

On 2024-04-18 11:15:43 +0000, Sriram RK wrote:

We (IBM-AIX team) looked into this issue

/messages/by-id/20240225194322.a5@rfd.leadboat.com

This is related to the compiler issue. The compilers xlc(13.1) and gcc(8.0)
have issues. But we verified that this issue is resolved with the newer
compiler versions openXL(xlc17.1) and gcc(12.0) onwards.

The reason we used these compilers was that those were the only ones we had
kinda somewhat reasonable access to, via the gcc projects'
"compile farm" https://portal.cfarm.net/
We have to rely on whatever the aix machines there provide. They're not
particularly plentiful resource-wise either.

To be fair, those OSUOSL machines are donated by IBM:

https://osuosl.org/services/powerdev/

It's just that they seem to be mostly focused on supporting Linux on
POWER, with only a couple of AIX hosts (partitions/virtual machines?)
made available via portal.cfarm.net, and they only very recently added
a modern AIX 7.3 host. That's cfarm119, upgraded in September-ish,
long after many threads on this list that between-the-lines threatened
to drop support.

This is generally one of the big issues with AIX support. There are other
niche-y OSs that don't have a lot of users, e.g. openbsd, but in contrast to
AIX I can just start an openbsd VM within a few minutes and iron out whatever
portability issue I'm dealing with.

Yeah. It is a known secret that you can run AIX inside Qemu/kvm (it
appears that IBM has made changes to it to make that possible, because
earlier AIX versions didn't like Qemu's POWER emulation or
virtualisation, there are blog posts about it), but IBM doesn't
actually make the images available to non-POWER-hardware owners (you
need a serial number). If I were an OS vendor and wanted developers
to target my OS for free, at the very top of my TODO list I would
have: provide an easy to use image for developers to be able to spin
something up in minutes and possibly even use in CI systems. That's
the reason I can fix any minor portability issue on Linux, illumos,
*BSD quickly and Windows with only moderate extra pain. Even Oracle
knows this, see Solaris CBE.

We want to make a note that postgres is used extensively in our IBM product
and is being exploited by multiple customers.

To be blunt: Then it'd have been nice to see some investment in that before
now. Both on the code level and the infrastructure level (i.e. access to
machines etc).

In the AIX space generally, there were even clues that funding had
been completely cut even for packaging PostgreSQL. I was aware of two
packaging projects (not sure how they were related):

1. The ATOS packaging group, who used to show up on our mailing lists
and discuss code changes, which announced it was shutting down:

https://github.com/power-devops/bullfreeware

2. And last time I looked a few months back, the IBM AIX Toolbox
packaging project only had PostgreSQL 10 or 11 packages, already out
of support by us, meaning that their maintainer had given up, too:

https://www.ibm.com/support/pages/aix-toolbox-open-source-software-downloads-alpha

However I see that recently (last month?) someone has added PostgreSQL
15, so something has only just reawoken there?

There are quite a lot of threads about AIX problems, but they are
almost all just us non-AIX-users trying to unbreak stupid stuff on the
build farm, which at some points began to seem distinctly quixotic:
chivalric hackers valiantly trying to keep the entire Unix family tree
working even though we don't remember why and th versions involved are
out of support even by the vendor. Of the three old giant commercial
Unixes, HP-UX was dropped without another mention (it really was a
windmill after all), Solaris is somehow easier to deal with (I could
guess it's because it influenced Linux and BSD so much, ELF and linker
details spring to mind), while AIX fails on every dimension:
unrepresented by users, lacking in build farm, unavailable to
non-customers, and unusual among Unixen.

#18Sriram RK
sriram.rk@outlook.com
In reply to: Andres Freund (#16)
Re: AIX support

For any complier/hardware related issue we should able to provide support.
We are in the process of identifying the AIX systems that can be added to the CI/buildfarm environment.

Regards,
Sriram.

#19Peter Eisentraut
peter@eisentraut.org
In reply to: Sriram RK (#18)
Re: AIX support

On 19.04.24 13:04, Sriram RK wrote:

For any complier/hardware related issue we should able to provide support.

We are in the process of identifying the AIX systems that can be added
to the CI/buildfarm environment.

I think we should manage expectations here, if there is any hope of
getting AIX support back into PG17.

I have some sympathy for this. The discussion about removing AIX
support had a very short turnaround and happened in an unrelated thread,
without any sort of public announcement or consultation. So this report
of "hey, we were still using that" is timely and fair.

But the underlying issue that led to the removal (something to do with
direct I/O support and alignment) would still need to be addressed. And
this probably wouldn't just need some infrastructure support; it would
require contributions from someone who actively knows how to develop on
this platform. Now, direct I/O is currently sort of an experimental
feature, so disabling it on AIX, as was initially suggested in that
discussion, might be okay for now, but the issue will come up again.

Even if this new buildfarm support is forthcoming, there has to be some
sort of deadline in any resurrection attempts for PG17. The first beta
date has been set for 23 May. If we are making the reinstatement of AIX
support contingent on new buildfarm support, those machines need to be
available, at least initially, at least for backbranches, like in a
week. Which seems tight.

I can see several ways going forward:

1. We revert the removal of AIX support and carry on with the status quo
ante. (The removal of AIX is a regression; it is timely and in scope
now to revert the change.)

2. Like (1), but we consider that notice has been given, and we will
remove it early in PG18 (like August) unless the situation improves.

3. We leave it out of PG17 and consider a new AIX port for PG18 on its
own merits.

Note that such a "new" port would probably require quite a bit of
development and research work, to clean up all the cruft that had
accumulated over the years in the old port. Another looming issue is
that the meson build system only supported AIX with gcc before the
removal. I don't know what it would take to expand that to support
xclang, but if it requires meson upstream work, you have that to do, too.

#20Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#19)
Re: AIX support

Peter Eisentraut <peter@eisentraut.org> writes:

I have some sympathy for this. The discussion about removing AIX
support had a very short turnaround and happened in an unrelated thread,
without any sort of public announcement or consultation. So this report
of "hey, we were still using that" is timely and fair.

Yup, that's a totally fair complaint. Still ...

I can see several ways going forward:
1. We revert the removal of AIX support and carry on with the status quo
ante. (The removal of AIX is a regression; it is timely and in scope
now to revert the change.)
2. Like (1), but we consider that notice has been given, and we will
remove it early in PG18 (like August) unless the situation improves.
3. We leave it out of PG17 and consider a new AIX port for PG18 on its
own merits.

Andres has ably summarized the reasons why the status quo ante was
getting untenable. The direct-I/O problem could have been tolerable
on its own, but in reality it was the straw that broke the camel's
back so far as our willingness to maintain AIX support went. There
were just too many hacks and workarounds for too many problems,
with too few people interested in looking for better answers.

So I'm totally not in favor of #1, at least not without some hard
commitments and follow-through on really cleaning up the mess
(which maybe looks more like your #2). What's needed here, as
you said, is for someone with a decent amount of expertise in
modern AIX to review all the issues. Maybe framing that as a
"new port" per #3 would be a good way to think about it. But
I don't want to just revert the AIX-ectomy and continue drifting.

On the whole, it wouldn't be the worst thing in the world if PG 17
lacks AIX support but that comes back in PG 18. That approach would
solve the schedule-crunch aspect and give time for considered review
of how many of the hacks removed in 0b16bb877 really need to be put
back, versus being obsolete or amenable to a nicer solution in
late-model AIX. If we take a "new port" mindset then it would be
totally reasonable to say that it only supports very recent AIX
releases, so I'd hope at least some of the cruft could be removed.

regards, tom lane

#21Sriram RK
sriram.rk@outlook.com
In reply to: Tom Lane (#20)
Re: AIX support

Hi Team,

I have some sympathy for this. The discussion about removing AIX

support had a very short turnaround and happened in an unrelated thread,

without any sort of public announcement or consultation. So this report

of "hey, we were still using that" is timely and fair.

We would really like to thank you & the team for considering our request,

and really appreciate for providing all the possible options to support AIX.

But the underlying issue that led to the removal (something to do with

direct I/O support and alignment) would still need to be addressed.

As we already validated that these alignment specific issues are resolved

with the latest versions of the compilers (gcc/ibm-clang). We would request

you to use the latest versions for the build.

If we are making the reinstatement of AIX

support contingent on new buildfarm support, those machines need to be

available, at least initially, at least for back branches, like in a

week. Which seems tight.

We are already working with the internal team in procuring the nodes

for the buildfarm, which can be accessible by the community.

I can see several ways going forward:

1. We revert the removal of AIX support and carry on with the status quo

ante. (The removal of AIX is a regression; it is timely and in scope

now to revert the change.)

2. Like (1), but we consider that notice has been given, and we will

remove it early in PG18 (like August) unless the situation improves.

We would really appreciate you for providing the possible options

and we are very much inclined to these above approaches.

Regards,

Sriram.

#22Tristan Partin
tristan@neon.tech
In reply to: Peter Eisentraut (#19)
Re: AIX support

On Sat Apr 20, 2024 at 10:42 AM CDT, Peter Eisentraut wrote:

3. We leave it out of PG17 and consider a new AIX port for PG18 on its
own merits.

Note that such a "new" port would probably require quite a bit of
development and research work, to clean up all the cruft that had
accumulated over the years in the old port. Another looming issue is
that the meson build system only supported AIX with gcc before the
removal. I don't know what it would take to expand that to support
xclang, but if it requires meson upstream work, you have that to do, too.

Happy to help advocate for any PRs from AIX folks on the Meson side. You
can find me as @tristan957 on github.

--
Tristan Partin
Neon (https://neon.tech)

#23Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#20)
Re: AIX support

On Sat, Apr 20, 2024 at 12:25:47PM -0400, Tom Lane wrote:

I can see several ways going forward:
1. We revert the removal of AIX support and carry on with the status quo
ante. (The removal of AIX is a regression; it is timely and in scope
now to revert the change.)
2. Like (1), but we consider that notice has been given, and we will
remove it early in PG18 (like August) unless the situation improves.
3. We leave it out of PG17 and consider a new AIX port for PG18 on its
own merits.

Andres has ably summarized the reasons why the status quo ante was
getting untenable. The direct-I/O problem could have been tolerable
on its own, but in reality it was the straw that broke the camel's
back so far as our willingness to maintain AIX support went. There
were just too many hacks and workarounds for too many problems,
with too few people interested in looking for better answers.

So I'm totally not in favor of #1, at least not without some hard
commitments and follow-through on really cleaning up the mess
(which maybe looks more like your #2). What's needed here, as
you said, is for someone with a decent amount of expertise in
modern AIX to review all the issues. Maybe framing that as a
"new port" per #3 would be a good way to think about it. But
I don't want to just revert the AIX-ectomy and continue drifting.

On the whole, it wouldn't be the worst thing in the world if PG 17
lacks AIX support but that comes back in PG 18. That approach would
solve the schedule-crunch aspect and give time for considered review
of how many of the hacks removed in 0b16bb877 really need to be put
back, versus being obsolete or amenable to a nicer solution in
late-model AIX. If we take a "new port" mindset then it would be
totally reasonable to say that it only supports very recent AIX
releases, so I'd hope at least some of the cruft could be removed.

I agree that targeting PG 18 for a new-er AIX port is the reasonable
approach. If there is huge demand, someone can create an AIX fork for
PG 17 using the reverted patches --- yeah, lots of pain there, but we
have carried the AIX pain for too long with too little support.

--
Bruce Momjian <bruce@momjian.us> https://momjian.us
EDB https://enterprisedb.com

Only you can decide what is important to you.

#24Michael Paquier
michael@paquier.xyz
In reply to: Bruce Momjian (#23)
Re: AIX support

On Wed, Apr 24, 2024 at 11:39:37PM -0400, Bruce Momjian wrote:

On Sat, Apr 20, 2024 at 12:25:47PM -0400, Tom Lane wrote:

So I'm totally not in favor of #1, at least not without some hard
commitments and follow-through on really cleaning up the mess
(which maybe looks more like your #2). What's needed here, as
you said, is for someone with a decent amount of expertise in
modern AIX to review all the issues. Maybe framing that as a
"new port" per #3 would be a good way to think about it. But
I don't want to just revert the AIX-ectomy and continue drifting.

On the whole, it wouldn't be the worst thing in the world if PG 17
lacks AIX support but that comes back in PG 18. That approach would
solve the schedule-crunch aspect and give time for considered review
of how many of the hacks removed in 0b16bb877 really need to be put
back, versus being obsolete or amenable to a nicer solution in
late-model AIX. If we take a "new port" mindset then it would be
totally reasonable to say that it only supports very recent AIX
releases, so I'd hope at least some of the cruft could be removed.

I agree that targeting PG 18 for a new-er AIX port is the reasonable
approach. If there is huge demand, someone can create an AIX fork for
PG 17 using the reverted patches --- yeah, lots of pain there, but we
have carried the AIX pain for too long with too little support.

Some of the portability changes removed in 0b16bb877 feel indeed
obsolete, so it may not hurt to start an analysis from scratch to see
the minimum amount of work that would be really required with the
latest versions of xlc, using the newest compilers as a supported
base. I'd like to think backporting these to stable branches should
be OK at some point, once the new port is proving baked enough.

Anyway, getting an access to such compilers to be able to debug issues
on hosts that take less than 12h to just compile the code would
certainly help its adoption. So seeing commitment in the form of
patches and access to environments would help a lot. Overall,
studying that afresh with v18 looks like a good idea, assuming that
anybody who commits such patches has access to hosts to evaluate them,
with buildfarm members running on top, of course.

My 2c.
--
Michael

#25Tom Lane
tgl@sss.pgh.pa.us
In reply to: Michael Paquier (#24)
Re: AIX support

Michael Paquier <michael@paquier.xyz> writes:

Some of the portability changes removed in 0b16bb877 feel indeed
obsolete, so it may not hurt to start an analysis from scratch to see
the minimum amount of work that would be really required with the
latest versions of xlc, using the newest compilers as a supported
base.

Something I've been mulling over is whether to suggest that the
proposed "new port" should only target building with gcc.

On the one hand, that would (I think) remove a number of annoying
issues, and the average end user is unlikely to care which compiler
their database server was built with. On the other hand, I'm a strong
proponent of avoiding software monocultures, and xlc is one of the few
C compilers still standing that aren't gcc or clang.

It would definitely make sense for a new port to start by getting
things going with gcc only, and then look at resurrecting xlc
support.

I'd like to think backporting these to stable branches should
be OK at some point, once the new port is proving baked enough.

If things go as I expect, the "new port" would effectively drop
support for older AIX and/or older compiler versions. So back-
porting seems like an unlikely decision.

Anyway, getting an access to such compilers to be able to debug issues
on hosts that take less than 12h to just compile the code would
certainly help its adoption.

+many

regards, tom lane

#26Michael Paquier
michael@paquier.xyz
In reply to: Tom Lane (#25)
Re: AIX support

On Thu, Apr 25, 2024 at 12:20:05AM -0400, Tom Lane wrote:

It would definitely make sense for a new port to start by getting
things going with gcc only, and then look at resurrecting xlc
support.

Sriram mentioned upthread that he was looking at both of them. I'd be
ready to assume that most of the interest is in xlc, not gcc. But I
may be wrong.

Saying that, dividing the effort into more successive steps is
sensible here (didn't consider that previously, you have a good
point).
--
Michael

#27Peter Eisentraut
peter@eisentraut.org
In reply to: Tom Lane (#25)
Re: AIX support

On 25.04.24 06:20, Tom Lane wrote:

Something I've been mulling over is whether to suggest that the
proposed "new port" should only target building with gcc.

On the one hand, that would (I think) remove a number of annoying
issues, and the average end user is unlikely to care which compiler
their database server was built with. On the other hand, I'm a strong
proponent of avoiding software monocultures, and xlc is one of the few
C compilers still standing that aren't gcc or clang.

My understanding is that the old xlc is dead and has been replaced by
"xlclang", which is presumably an xlc-compatible frontend on top of
clang/llvm. Hopefully, that will have fewer issues.

#28Alvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Bruce Momjian (#23)
Re: AIX support

On 2024-Apr-24, Bruce Momjian wrote:

I agree that targeting PG 18 for a new-er AIX port is the reasonable
approach. If there is huge demand, someone can create an AIX fork for
PG 17 using the reverted patches --- yeah, lots of pain there, but we
have carried the AIX pain for too long with too little support.

I'm not sure how large the demand would be for an AIX port specifically
of 17, though. I mean, people using older versions can continue to use
16 until 18 is released. Upgrading past one major version is hardly
unheard of.

--
Álvaro Herrera Breisgau, Deutschland — https://www.EnterpriseDB.com/
"If you want to have good ideas, you must have many ideas. Most of them
will be wrong, and what you have to learn is which ones to throw away."
(Linus Pauling)

#29Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#27)
Re: AIX support

Peter Eisentraut <peter@eisentraut.org> writes:

On 25.04.24 06:20, Tom Lane wrote:

Something I've been mulling over is whether to suggest that the
proposed "new port" should only target building with gcc.

My understanding is that the old xlc is dead and has been replaced by
"xlclang", which is presumably an xlc-compatible frontend on top of
clang/llvm. Hopefully, that will have fewer issues.

[ googles... ] Actually it seems to be the other way around:
per [1]https://www.ibm.com/docs/en/xl-c-and-cpp-aix/16.1?topic=new-clang-based-front-end xlclang is a clang-based front end to IBM's existing
codegen+optimization logic, and the xlc front end is still there too.
It's not at all clear that they have any intention of killing off xlc.

Not sure where that leaves us in terms of either one being an
interesting target to support. xlclang is presumably an easier lift
to get working, but that also makes it much less interesting from
the preserve-our-portability standpoint.

regards, tom lane

[1]: https://www.ibm.com/docs/en/xl-c-and-cpp-aix/16.1?topic=new-clang-based-front-end

#30Andres Freund
andres@anarazel.de
In reply to: Tom Lane (#25)
Re: AIX support

Hi,

On 2024-04-25 00:20:05 -0400, Tom Lane wrote:

Something I've been mulling over is whether to suggest that the
proposed "new port" should only target building with gcc.

Yes. I also wonder if such a port should only support building with sysv
style shared library support, rather than the AIX (and windows) style. That'd
make it considerably less impactful on the buildsystem level. I don't know
what the performance difference is these days.

Greetings,

Andres Freund

#31Bruce Momjian
bruce@momjian.us
In reply to: Alvaro Herrera (#28)
Re: AIX support

On Thu, Apr 25, 2024 at 10:16:34AM +0200, Álvaro Herrera wrote:

On 2024-Apr-24, Bruce Momjian wrote:

I agree that targeting PG 18 for a new-er AIX port is the reasonable
approach. If there is huge demand, someone can create an AIX fork for
PG 17 using the reverted patches --- yeah, lots of pain there, but we
have carried the AIX pain for too long with too little support.

I'm not sure how large the demand would be for an AIX port specifically
of 17, though. I mean, people using older versions can continue to use
16 until 18 is released. Upgrading past one major version is hardly
unheard of.

Agreed. They seem to have packages for 11/12, and only 15 recently. I
don't see how PG 17 would be missed, unless there are many people
compiling from source.

--
Bruce Momjian <bruce@momjian.us> https://momjian.us
EDB https://enterprisedb.com

Only you can decide what is important to you.

#32Bruce Momjian
bruce@momjian.us
In reply to: Michael Paquier (#24)
Re: AIX support

On Thu, Apr 25, 2024 at 01:06:24PM +0900, Michael Paquier wrote:

Anyway, getting an access to such compilers to be able to debug issues
on hosts that take less than 12h to just compile the code would
certainly help its adoption. So seeing commitment in the form of
patches and access to environments would help a lot. Overall,
studying that afresh with v18 looks like a good idea, assuming that
anybody who commits such patches has access to hosts to evaluate them,
with buildfarm members running on top, of course.

Agreed. They can't even have buildfarm member for PG 17 since it
doesn't compile anymore, so someone has to go over the reverted patch,
figure out which ones are still valid, and report back. Trying to add a
port, with possible breakage, during beta seems too risky compared to
the value.

--
Bruce Momjian <bruce@momjian.us> https://momjian.us
EDB https://enterprisedb.com

Only you can decide what is important to you.

#33Sriram RK
sriram.rk@outlook.com
In reply to: Michael Paquier (#26)
Re: AIX support

It would definitely make sense for a new port to start by getting
things going with gcc only, and then look at resurrecting xlc
support.

Sriram mentioned upthread that he was looking at both of them. I'd be
ready to assume that most of the interest is in xlc, not gcc. But I
may be wrong.

Just a heads-up, we got a node in the OSU lab for the buildfarm. Will let you know once we have the buildfarm setup on that node.

Also, we are making progress on setting up the buildfarm on a local node as well.
But currently there are some tests failing, seems some issue with plperl.

aix01::build-farm-17#
./run_build.pl --keepall --nosend --nostatus --verbose=5 --force REL_16_STABLE

Fri Apr 26 00:53:50 2024: buildfarm run for AIXnode01:REL_16_STABLE starting
AIXnode01:REL_16_STABLE [00:53:50] checking out source ...
AIXnode01:REL_16_STABLE [00:53:56] checking if build run needed ...
AIXnode01:REL_16_STABLE [00:53:56] copying source to pgsql.build ...
AIXnode01:REL_16_STABLE [00:54:08] running configure ...
AIXnode01:REL_16_STABLE [00:55:01] running build ...
AIXnode01:REL_16_STABLE [01:08:09] running basic regression tests ...
AIXnode01:REL_16_STABLE [01:09:51] running make contrib ...
AIXnode01:REL_16_STABLE [01:11:08] running make testmodules ...
AIXnode01:REL_16_STABLE [01:11:19] running install ...
AIXnode01:REL_16_STABLE [01:11:48] running make contrib install ...
AIXnode01:REL_16_STABLE [01:12:01] running testmodules install ...
AIXnode01:REL_16_STABLE [01:12:06] checking test-decoding
gmake: gcc: A file or directory in the path name does not exist.
AIXnode01:REL_16_STABLE [01:12:28] running make check miscellaneous modules ...
gmake: gcc: A file or directory in the path name does not exist.
AIXnode01:REL_16_STABLE [01:13:50] setting up db cluster (C)...
AIXnode01:REL_16_STABLE [01:13:53] starting db (C)...
AIXnode01:REL_16_STABLE [01:13:53] running installcheck (C)...
AIXnode01:REL_16_STABLE [01:15:05] restarting db (C)...
AIXnode01:REL_16_STABLE [01:15:07] running make isolation check ...
AIXnode01:REL_16_STABLE [01:15:51] restarting db (C)...
AIXnode01:REL_16_STABLE [01:15:56] running make PL installcheck (C)...
Branch: REL_16_STABLE
Stage PLCheck-C failed with status 2

#34Sriram RK
sriram.rk@outlook.com
In reply to: Sriram RK (#33)
Re: AIX support

Hi Team,

There are couple of updates, firstly we got an AIX node on the OSU lab.
Please feel free to reach me, so that we can provide access to the node.
We have started working on setting up the buildfarm on that node.

Secondly, as part of the buildfarm setup on our local nodes, we are hitting
an issue with the plperl extension. In the logs we noticed that when the
plperl extension is being created, it is failing to load the perl library.

    - CREATE EXTENSION plperlu;
    + server closed the connection unexpectedly
    +       This probably means the server terminated abnormally
    +       before or while processing the request.
    + connection to server was lost

In the logfile we could see these

2024-05-04 05:05:17.537 CDT [3997786:17] pg_regress/plperl_setup LOG: statement: CREATE EXTENSION plperl;
Util.c: loadable library and perl binaries are mismatched (got first handshake key 9b80080, needed 9a80080)

We tried to resolve some of the suggestions mentioned here, but things couldn’t resolve.

/messages/by-id/CALDaNm15qaRFb3WiPFAdFqoB9pj1E5SCPPUGB+nJ4iF4gXO6Rw@mail.gmail.com

Any inputs here would be greatly appreciated.

Regards,
Sriram.

#35Sriram RK
sriram.rk@outlook.com
In reply to: Sriram RK (#34)
Re: AIX support

Hi Team, on further investigation we were able to resolve the perl issue by setting the right PERL env location. Earlier it was pointing to the 32bit perl, as a result the perl lib mismatch seems to be happening.
Now we have successfully built release 15 and 16 stable branches on the OSU lab node.

p9aix (OSU)
OS: AIX 72Z
RELEASE 16
p9aix:REL_16_STABLE [08:31:26] OK
======== log passed to send_result ===========
Branch: REL_16_STABLE
All stages succeeded

RELEASE 15
p9aix:REL_15_STABLE [08:55:37] OK
======== log passed to send_result ===========
Branch: REL_15_STABLE
All stages succeeded

Also, we had successfully built release 16 branch on our local nodes as well
OS: AIX 71C
pgsql-aix71C:REL_16_STABLE [02:25:32] OK
======== log passed to send_result ===========
Branch: REL_16_STABLE
All stages succeeded

OS: AIX72Z
pgsql-aix72Z:REL_16_STABLE [02:35:03] OK
======== log passed to send_result ===========
Branch: REL_16_STABLE
All stages succeeded

OS: AIX73D
pgsql-aix73D:REL_16_STABLE [05:32:29] OK
======== log passed to send_result ===========
Branch: REL_16_STABLE
All stages succeeded

Regards,
Sriram.

#36Sriram RK
sriram.rk@outlook.com
In reply to: Sriram RK (#35)
Re: AIX support

Hi Team, We have the AIX node ready in OSU lab, and the branches 15 and 16 got build on the node. We had raised a request to register this node as buildfarm member. Yet to receive the approval.

We would like to understand your inputs/plans on reverting the changes for AIX.

Thanks,
Sriram.

#37Peter Eisentraut
peter@eisentraut.org
In reply to: Sriram RK (#36)
Re: AIX support

On 08.05.24 13:39, Sriram RK wrote:

We would like to understand your inputs/plans on reverting the changes
for AIX.

I think the ship has sailed for PG17. The way forward would be that you
submit a patch for new, modernized AIX support for PG18.

#38Bruce Momjian
bruce@momjian.us
In reply to: Peter Eisentraut (#37)
Re: AIX support

On Wed, May 8, 2024 at 03:44:12PM +0200, Peter Eisentraut wrote:

On 08.05.24 13:39, Sriram RK wrote:

We would like to understand your inputs/plans on reverting the changes
for AIX.

I think the ship has sailed for PG17. The way forward would be that you
submit a patch for new, modernized AIX support for PG18.

Yes, I think we were clear that someone needs to review the reverted
patch and figure out which parts are still needed, and why. We have no
"plans" to restore support.

--
Bruce Momjian <bruce@momjian.us> https://momjian.us
EDB https://enterprisedb.com

Only you can decide what is important to you.

#39Sriram RK
sriram.rk@outlook.com
In reply to: Bruce Momjian (#38)
Re: AIX support

Hi Team, we have any updated from the XLC team, the issue specific to the alignment is fixed
and XLC had released it as part of 16.1.0.18. The PTF is available at the below location,

You can also find a link here:
https://www.ibm.com/support/pages/fix-list-xl-cc-aix.

/opt/IBM/xlC/16.1.0/bin/xlC align.c -o align.xl

./align.xl

al4096 4096 @ 0x20008000 (mod 0)
al4096_initialized 4096 @ 0x20004000 (mod 0)
al4096_const 4096 @ 0x2000b000 (mod 0)
al4096_const_initialized 4096 @ 0x10008000 (mod 0)
al4096_static 4096 @ 0x2000e000 (mod 0)
al4096_static_initialized 4096 @ 0x20001000 (mod 0)
al4096_static_const 4096 @ 0x20011000 (mod 0)
al4096_static_const_initialized 4096 @ 0x10001000 (mod 0)

Also would like to know some info related to the request raised for buildfarm access, to register the node in OSU lab. Where can I get the status of the request? Whom can I contact to get the request approved? So that we can add the node to the buildfarm.

Regards,
Sriram.

#40Noah Misch
noah@leadboat.com
In reply to: Sriram RK (#39)
Re: AIX support

On Wed, May 15, 2024 at 03:33:25PM +0000, Sriram RK wrote:

Hi Team, we have any updated from the XLC team, the issue specific to the alignment is fixed
and XLC had released it as part of 16.1.0.18. The PTF is available at the below location,

You can also find a link here:
https://www.ibm.com/support/pages/fix-list-xl-cc-aix.

/opt/IBM/xlC/16.1.0/bin/xlC align.c -o align.xl

./align.xl

al4096 4096 @ 0x20008000 (mod 0)
al4096_initialized 4096 @ 0x20004000 (mod 0)
al4096_const 4096 @ 0x2000b000 (mod 0)
al4096_const_initialized 4096 @ 0x10008000 (mod 0)
al4096_static 4096 @ 0x2000e000 (mod 0)
al4096_static_initialized 4096 @ 0x20001000 (mod 0)
al4096_static_const 4096 @ 0x20011000 (mod 0)
al4096_static_const_initialized 4096 @ 0x10001000 (mod 0)

That is good news. PGIOAlignedBlock is now in the IBM publication,
https://www.ibm.com/support/pages/apar/IJ51032

Also would like to know some info related to the request raised for buildfarm access, to register the node in OSU lab. Where can I get the status of the request? Whom can I contact to get the request approved? So that we can add the node to the buildfarm.

I assume you filled out the form at
https://buildfarm.postgresql.org/cgi-bin/register-form.pl? It can take a few
weeks, so I wouldn't worry yet.

#41Sriram RK
sriram.rk@outlook.com
In reply to: Noah Misch (#40)
Re: AIX support

Also would like to know some info related to the request raised for buildfarm access, to register the
node in OSU lab. Where can I get the status of the request? Whom can I contact to get the request
approved? So that we can add the node to the buildfarm.

I assume you filled out the form at
https://buildfarm.postgresql.org/cgi-bin/register-form.pl? It can take a few
weeks, so I wouldn't worry yet.

Thanks Noha, I had already submitted a form a week back, hope it might take another couple of weeks to get it approved.

#42Sriram RK
sriram.rk@outlook.com
In reply to: Sriram RK (#41)
Re: AIX support

Hi Team,

We have an update wrt to the PG17 AIX port.

We have reverted the changes specific to AIX (that were removed in 0b16bb8776bb8) to the latest PG17 (head).

The Buildfarm succeeded for these changes. All the tests passed.

System config

OS level : AIX-73D

Compiler : gcc-12 & xlc(16.1.0.18)

Wed May 15 21:26:00 2024: buildfarm run for AIXnode01:HEAD starting

AIXnode01:HEAD [21:26:00] running configure ...

AIXnode01:HEAD [21:27:03] running build ...

AIXnode01:HEAD [21:27:27] running basic regression tests ...

AIXnode01:HEAD [21:34:41] running make contrib ...

AIXnode01:HEAD [21:34:43] running make testmodules ...

AIXnode01:HEAD [21:34:44] running install ...

AIXnode01:HEAD [21:34:58] running make contrib install ...

AIXnode01:HEAD [21:35:05] running testmodules install ...

AIXnode01:HEAD [21:35:08] checking pg_upgrade

AIXnode01:HEAD [21:35:08] checking test-decoding

AIXnode01:HEAD [21:35:29] running make check miscellaneous modules ...

AIXnode01:HEAD [21:36:16] setting up db cluster (C)...

AIXnode01:HEAD [21:36:19] starting db (C)...

AIXnode01:HEAD [21:36:19] running installcheck (C)...

AIXnode01:HEAD [21:46:27] restarting db (C)...

AIXnode01:HEAD [21:46:29] running make isolation check ...

AIXnode01:HEAD [21:49:57] restarting db (C)...

AIXnode01:HEAD [21:50:02] running make PL installcheck (C)...

AIXnode01:HEAD [21:50:09] restarting db (C)...

AIXnode01:HEAD [21:50:12] running make contrib installcheck (C)...

AIXnode01:HEAD [21:53:53] restarting db (C)...

AIXnode01:HEAD [21:53:56] running make test-modules installcheck (C)...

AIXnode01:HEAD [21:54:28] stopping db (C)...

AIXnode01:HEAD [21:54:29] running make ecpg check ...

AIXnode01:HEAD [21:54:45] OK

Branch: HEAD

All stages succeeded

The below changes are applied on this commit level

commit 54b69f1bd730a228a666441592a12d2a0cbe2a06 (HEAD -> pgAIX, origin/master, origin/HEAD, master)

On branch pgAIX

Changes to be committed:

(use "git restore --staged <file>..." to unstage)

new file: src/backend/port/aix/mkldexport.sh

new file: src/include/port/aix.h

new file: src/makefiles/Makefile.aix

new file: src/template/aix

Changes not staged for commit:

(use "git add <file>..." to update what will be committed)

(use "git restore <file>..." to discard changes in working directory)

modified: Makefile

modified: config/c-compiler.m4

modified: configure

modified: configure.ac

modified: doc/src/sgml/dfunc.sgml

modified: doc/src/sgml/installation.sgml

modified: doc/src/sgml/runtime.sgml

modified: meson.build

modified: src/Makefile.shlib

modified: src/backend/Makefile

modified: src/backend/meson.build

modified: src/backend/storage/buffer/bufmgr.c

modified: src/backend/utils/error/elog.c

modified: src/backend/utils/misc/ps_status.c

modified: src/bin/pg_basebackup/t/010_pg_basebackup.pl

modified: src/bin/pg_verifybackup/t/008_untar.pl

modified: src/bin/pg_verifybackup/t/010_client_untar.pl

modified: src/include/c.h

modified: src/include/port/atomics.h

modified: src/include/storage/s_lock.h

modified: src/interfaces/libpq/Makefile

modified: src/interfaces/libpq/meson.build

modified: src/port/README

modified: src/port/strerror.c

modified: src/test/regress/Makefile

modified: src/test/regress/expected/sanity_check.out

modified: src/test/regress/expected/test_setup.out

modified: src/test/regress/regress.c

modified: src/test/regress/sql/sanity_check.sql

modified: src/test/regress/sql/test_setup.sql

modified: src/tools/gen_export.pl

modified: src/tools/pginclude/headerscheck

Can you please let us know, the process to post the changes for review?

Regards,
Sriram.

#43Alvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Sriram RK (#42)
Re: AIX support

On 2024-May-16, Sriram RK wrote:

Hi Team,

We have an update wrt to the PG17 AIX port.

We have reverted the changes specific to AIX (that were removed in 0b16bb8776bb8) to the latest PG17 (head).

The Buildfarm succeeded for these changes. All the tests passed.

Excellent.

Can you please let us know, the process to post the changes for review?

Here's some very good advice
/messages/by-id/20240405172649.d1@rfd.leadboat.com

Regards

--
Álvaro Herrera

#44Sriram RK
sriram.rk@outlook.com
In reply to: Alvaro Herrera (#43)
1 attachment(s)
Re: AIX support

Thanks Alvaro, for the info…

Hi Team,
We referred to the below links to build this patch …
https://wiki.postgresql.org/wiki/Submitting_a_Patch
https://peter.eisentraut.org/blog/2023/05/09/how-to-submit-a-patch-by-email-2023-edition

Please find the attached patch.

Apart from the AIX specific changes, there is a minor change in this file wrt to XLC, below is the error for which we removed inline.
Later, the build and tests passed for both XLC(16.1.0.18) and gcc(12) as well.

src/backend/storage/buffer/bufmgr.c

"bufmgr.c", line 811.39: 1506-780 (S) Reference to "RelationGetSmgr" with internal linkage is not allowed within inline definition of "ReadBufferExtended".
"bufmgr.c", line 811.15: 1506-780 (S) Reference to "ReadBuffer_common" with internal linkage is not allowed within inline definition of "ReadBufferExtended".
gmake[4]: *** [<builtin>: bufmgr.o] Error 1

Please let us know your feedback.

Thanks,
Sriram.

Attachments:

0001-AIX-support-revert-the-changes-from-0b16bb8776bb8.patchapplication/octet-stream; name=0001-AIX-support-revert-the-changes-from-0b16bb8776bb8.patchDownload
From 15d0cf54ee49a88c566cb439396b870d5e6c392c Mon Sep 17 00:00:00 2001
From: Sriram RK <sriram.rk@in.ibm.com>
Date: Mon, 20 May 2024 01:38:59 -0500
Subject: [PATCH] AIX support, revert the changes from 0b16bb8776bb8.

---
 Makefile                                      |   2 -
 config/c-compiler.m4                          |   2 +-
 configure                                     | 329 ++++++++++++++++--
 configure.ac                                  |  55 +--
 doc/src/sgml/dfunc.sgml                       |  19 +
 doc/src/sgml/installation.sgml                | 119 ++++++-
 doc/src/sgml/runtime.sgml                     |  23 ++
 meson.build                                   |  57 +--
 src/Makefile.shlib                            |  29 ++
 src/backend/Makefile                          |  20 ++
 src/backend/meson.build                       |  15 +
 src/backend/port/aix/mkldexport.sh            |  61 ++++
 src/backend/storage/buffer/bufmgr.c           |   2 +-
 src/backend/utils/error/elog.c                |   2 +
 src/backend/utils/misc/ps_status.c            |   4 +-
 src/bin/pg_basebackup/t/010_pg_basebackup.pl  |   3 +-
 src/bin/pg_verifybackup/t/008_untar.pl        |   3 +-
 src/bin/pg_verifybackup/t/010_client_untar.pl |   3 +-
 src/include/c.h                               |  18 +-
 src/include/port/aix.h                        |  14 +
 src/include/port/atomics.h                    |   6 +-
 src/include/storage/s_lock.h                  |  31 +-
 src/interfaces/libpq/Makefile                 |   2 +-
 src/interfaces/libpq/meson.build              |   5 +-
 src/makefiles/Makefile.aix                    |  39 +++
 src/port/README                               |   2 +-
 src/port/strerror.c                           |   2 +
 src/template/aix                              |  25 ++
 src/test/regress/Makefile                     |   5 +
 src/test/regress/expected/sanity_check.out    |  29 ++
 src/test/regress/expected/test_setup.out      |   4 +
 src/test/regress/regress.c                    |  40 +++
 src/test/regress/sql/sanity_check.sql         |  26 ++
 src/test/regress/sql/test_setup.sql           |   5 +
 src/tools/gen_export.pl                       |  11 +-
 src/tools/pginclude/headerscheck              |   1 +
 36 files changed, 908 insertions(+), 105 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 create mode 100644 src/include/port/aix.h
 create mode 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index 8a2ec9396b..9bc1a4ec17 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/config/c-compiler.m4 b/config/c-compiler.m4
index 10f8c7bd0a..ad99b91032 100644
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -137,7 +137,7 @@ if test x"$pgac_cv__128bit_int" = xyes ; then
   AC_CACHE_CHECK([for __int128 alignment bug], [pgac_cv__128bit_int_bug],
   [AC_RUN_IFELSE([AC_LANG_PROGRAM([
 /* This must match the corresponding code in c.h: */
-#if defined(__GNUC__) || defined(__SUNPRO_C)
+#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
 #elif defined(_MSC_VER)
 #define pg_attribute_aligned(a) __declspec(align(a))
diff --git a/configure b/configure
index 89644f2249..8ca7ec5cfe 100755
--- a/configure
+++ b/configure
@@ -2988,6 +2988,7 @@ else
 # --with-template not given
 
 case $host_os in
+     aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -3894,8 +3895,10 @@ _ACEOF
 
 # If you don't specify a list of compilers to test, the AC_PROG_CC and
 # AC_PROG_CXX macros test for a long list of unsupported compilers.
-pgac_cc_list="gcc cc"
-pgac_cxx_list="g++ c++"
+case $template in
+  aix) pgac_cc_list="gcc xlc"; pgac_cxx_list="g++ xlC";;
+    *) pgac_cc_list="gcc cc"; pgac_cxx_list="g++ c++";;
+esac
 
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -6849,6 +6852,190 @@ if test x"$pgac_cv_prog_CXX_cxxflags__fno_strict_aliasing" = x"yes"; then
 fi
 
 
+elif test "$PORTNAME" = "aix"; then
+  # AIX's xlc has to have strict aliasing turned off too
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -qnoansialias, for CFLAGS" >&5
+$as_echo_n "checking whether ${CC} supports -qnoansialias, for CFLAGS... " >&6; }
+if ${pgac_cv_prog_CC_cflags__qnoansialias+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CFLAGS=$CFLAGS
+pgac_save_CC=$CC
+CC=${CC}
+CFLAGS="${CFLAGS} -qnoansialias"
+ac_save_c_werror_flag=$ac_c_werror_flag
+ac_c_werror_flag=yes
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  pgac_cv_prog_CC_cflags__qnoansialias=yes
+else
+  pgac_cv_prog_CC_cflags__qnoansialias=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_c_werror_flag=$ac_save_c_werror_flag
+CFLAGS="$pgac_save_CFLAGS"
+CC="$pgac_save_CC"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CC_cflags__qnoansialias" >&5
+$as_echo "$pgac_cv_prog_CC_cflags__qnoansialias" >&6; }
+if test x"$pgac_cv_prog_CC_cflags__qnoansialias" = x"yes"; then
+  CFLAGS="${CFLAGS} -qnoansialias"
+fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CXX} supports -qnoansialias, for CXXFLAGS" >&5
+$as_echo_n "checking whether ${CXX} supports -qnoansialias, for CXXFLAGS... " >&6; }
+if ${pgac_cv_prog_CXX_cxxflags__qnoansialias+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CXXFLAGS=$CXXFLAGS
+pgac_save_CXX=$CXX
+CXX=${CXX}
+CXXFLAGS="${CXXFLAGS} -qnoansialias"
+ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ac_cxx_werror_flag=yes
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  pgac_cv_prog_CXX_cxxflags__qnoansialias=yes
+else
+  pgac_cv_prog_CXX_cxxflags__qnoansialias=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+CXXFLAGS="$pgac_save_CXXFLAGS"
+CXX="$pgac_save_CXX"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CXX_cxxflags__qnoansialias" >&5
+$as_echo "$pgac_cv_prog_CXX_cxxflags__qnoansialias" >&6; }
+if test x"$pgac_cv_prog_CXX_cxxflags__qnoansialias" = x"yes"; then
+  CXXFLAGS="${CXXFLAGS} -qnoansialias"
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -qlonglong, for CFLAGS" >&5
+$as_echo_n "checking whether ${CC} supports -qlonglong, for CFLAGS... " >&6; }
+if ${pgac_cv_prog_CC_cflags__qlonglong+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CFLAGS=$CFLAGS
+pgac_save_CC=$CC
+CC=${CC}
+CFLAGS="${CFLAGS} -qlonglong"
+ac_save_c_werror_flag=$ac_c_werror_flag
+ac_c_werror_flag=yes
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  pgac_cv_prog_CC_cflags__qlonglong=yes
+else
+  pgac_cv_prog_CC_cflags__qlonglong=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_c_werror_flag=$ac_save_c_werror_flag
+CFLAGS="$pgac_save_CFLAGS"
+CC="$pgac_save_CC"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CC_cflags__qlonglong" >&5
+$as_echo "$pgac_cv_prog_CC_cflags__qlonglong" >&6; }
+if test x"$pgac_cv_prog_CC_cflags__qlonglong" = x"yes"; then
+  CFLAGS="${CFLAGS} -qlonglong"
+fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CXX} supports -qlonglong, for CXXFLAGS" >&5
+$as_echo_n "checking whether ${CXX} supports -qlonglong, for CXXFLAGS... " >&6; }
+if ${pgac_cv_prog_CXX_cxxflags__qlonglong+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CXXFLAGS=$CXXFLAGS
+pgac_save_CXX=$CXX
+CXX=${CXX}
+CXXFLAGS="${CXXFLAGS} -qlonglong"
+ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ac_cxx_werror_flag=yes
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  pgac_cv_prog_CXX_cxxflags__qlonglong=yes
+else
+  pgac_cv_prog_CXX_cxxflags__qlonglong=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+CXXFLAGS="$pgac_save_CXXFLAGS"
+CXX="$pgac_save_CXX"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CXX_cxxflags__qlonglong" >&5
+$as_echo "$pgac_cv_prog_CXX_cxxflags__qlonglong" >&6; }
+if test x"$pgac_cv_prog_CXX_cxxflags__qlonglong" = x"yes"; then
+  CXXFLAGS="${CXXFLAGS} -qlonglong"
+fi
+
+
 fi
 
 # If the compiler knows how to hide symbols, add the switch needed for that to
@@ -7003,6 +7190,103 @@ if test x"$pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden" = x"yes"; then
 fi
 
   have_visibility_attribute=$pgac_cv_prog_CC_cflags__fvisibility_hidden
+elif test "$PORTNAME" = "aix"; then
+  # Note that xlc accepts -fvisibility=hidden as a file.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -qvisibility=hidden, for CFLAGS_SL_MODULE" >&5
+$as_echo_n "checking whether ${CC} supports -qvisibility=hidden, for CFLAGS_SL_MODULE... " >&6; }
+if ${pgac_cv_prog_CC_cflags__qvisibility_hidden+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CFLAGS=$CFLAGS
+pgac_save_CC=$CC
+CC=${CC}
+CFLAGS="${CFLAGS_SL_MODULE} -qvisibility=hidden"
+ac_save_c_werror_flag=$ac_c_werror_flag
+ac_c_werror_flag=yes
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  pgac_cv_prog_CC_cflags__qvisibility_hidden=yes
+else
+  pgac_cv_prog_CC_cflags__qvisibility_hidden=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_c_werror_flag=$ac_save_c_werror_flag
+CFLAGS="$pgac_save_CFLAGS"
+CC="$pgac_save_CC"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CC_cflags__qvisibility_hidden" >&5
+$as_echo "$pgac_cv_prog_CC_cflags__qvisibility_hidden" >&6; }
+if test x"$pgac_cv_prog_CC_cflags__qvisibility_hidden" = x"yes"; then
+  CFLAGS_SL_MODULE="${CFLAGS_SL_MODULE} -qvisibility=hidden"
+fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CXX} supports -qvisibility=hidden, for CXXFLAGS_SL_MODULE" >&5
+$as_echo_n "checking whether ${CXX} supports -qvisibility=hidden, for CXXFLAGS_SL_MODULE... " >&6; }
+if ${pgac_cv_prog_CXX_cxxflags__qvisibility_hidden+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CXXFLAGS=$CXXFLAGS
+pgac_save_CXX=$CXX
+CXX=${CXX}
+CXXFLAGS="${CXXFLAGS_SL_MODULE} -qvisibility=hidden"
+ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ac_cxx_werror_flag=yes
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  pgac_cv_prog_CXX_cxxflags__qvisibility_hidden=yes
+else
+  pgac_cv_prog_CXX_cxxflags__qvisibility_hidden=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+CXXFLAGS="$pgac_save_CXXFLAGS"
+CXX="$pgac_save_CXX"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CXX_cxxflags__qvisibility_hidden" >&5
+$as_echo "$pgac_cv_prog_CXX_cxxflags__qvisibility_hidden" >&6; }
+if test x"$pgac_cv_prog_CXX_cxxflags__qvisibility_hidden" = x"yes"; then
+  CXXFLAGS_SL_MODULE="${CXXFLAGS_SL_MODULE} -qvisibility=hidden"
+fi
+
+  have_visibility_attribute=$pgac_cv_prog_CC_cflags__qvisibility_hidden
+  # Old xlc versions (<13.1) don't have support for -qvisibility. Use expfull to force
+  # all extension module symbols to be exported.
+  if test "$pgac_cv_prog_CC_cflags__qvisibility_hidden" != "yes"; then
+    CFLAGS_SL_MODULE="$CFLAGS_SL_MODULE -Wl,-b,expfull"
+  fi
 fi
 
 if test "$have_visibility_attribute" = "yes"; then
@@ -12860,7 +13144,8 @@ fi
 
 fi
 
-# Note: We can test for libldap_r only after we know PTHREAD_LIBS
+# Note: We can test for libldap_r only after we know PTHREAD_LIBS;
+# also, on AIX, we may need to have openssl in LIBS for this step.
 if test "$with_ldap" = yes ; then
   _LIBS="$LIBS"
   if test "$PORTNAME" != "win32"; then
@@ -14718,6 +15003,10 @@ fi
 # spelling it understands, because it conflicts with
 # __declspec(restrict). Therefore we define pg_restrict to the
 # appropriate definition, which presumably won't conflict.
+#
+# Allow platforms with buggy compilers to force restrict to not be
+# used by setting $FORCE_DISABLE_RESTRICT=yes in the relevant
+# template.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
 $as_echo_n "checking for C/C++ restrict keyword... " >&6; }
 if ${ac_cv_c_restrict+:} false; then :
@@ -14764,7 +15053,7 @@ _ACEOF
  ;;
  esac
 
-if test "$ac_cv_c_restrict" = "no"; then
+if test "$ac_cv_c_restrict" = "no" -o "x$FORCE_DISABLE_RESTRICT" = "xyes"; then
   pg_restrict=""
 else
   pg_restrict="$ac_cv_c_restrict"
@@ -16951,28 +17240,18 @@ _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
+# We assume long's alignment is at least as strong as char, short, or int;
+# but we must check long long (if it is being used for int64) and double.
+# 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
-  as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
+MAX_ALIGNOF=$ac_cv_alignof_long
+if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+  MAX_ALIGNOF=$ac_cv_alignof_double
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $MAX_ALIGNOF -lt $ac_cv_alignof_long_long_int ; then
+  MAX_ALIGNOF="$ac_cv_alignof_long_long_int"
 fi
 
 cat >>confdefs.h <<_ACEOF
@@ -17090,7 +17369,7 @@ else
 /* end confdefs.h.  */
 
 /* This must match the corresponding code in c.h: */
-#if defined(__GNUC__) || defined(__SUNPRO_C)
+#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
 #elif defined(_MSC_VER)
 #define pg_attribute_aligned(a) __declspec(align(a))
diff --git a/configure.ac b/configure.ac
index c7322e292c..b2e19cf822 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ PGAC_ARG_REQ(with, template, [NAME], [override operating system template],
 # --with-template not given
 
 case $host_os in
+     aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -368,10 +369,10 @@ AC_DEFINE_UNQUOTED([XLOG_BLCKSZ], ${XLOG_BLCKSZ}, [
 # C compiler
 #
 
-# If you don't specify a list of compilers to test, the AC_PROG_CC and
-# AC_PROG_CXX macros test for a long list of unsupported compilers.
-pgac_cc_list="gcc cc"
-pgac_cxx_list="g++ c++"
+case $template in
+  aix) pgac_cc_list="gcc xlc"; pgac_cxx_list="g++ xlC";;
+    *) pgac_cc_list="gcc cc"; pgac_cxx_list="g++ c++";;
+esac
 
 AC_PROG_CC([$pgac_cc_list])
 AC_PROG_CC_C99()
@@ -588,6 +589,12 @@ elif test "$ICC" = yes; then
   # Make sure strict aliasing is off (though this is said to be the default)
   PGAC_PROG_CC_CFLAGS_OPT([-fno-strict-aliasing])
   PGAC_PROG_CXX_CFLAGS_OPT([-fno-strict-aliasing])
+elif test "$PORTNAME" = "aix"; then
+  # AIX's xlc has to have strict aliasing turned off too
+  PGAC_PROG_CC_CFLAGS_OPT([-qnoansialias])
+  PGAC_PROG_CXX_CFLAGS_OPT([-qnoansialias])
+  PGAC_PROG_CC_CFLAGS_OPT([-qlonglong])
+  PGAC_PROG_CXX_CFLAGS_OPT([-qlonglong])
 fi
 
 # If the compiler knows how to hide symbols, add the switch needed for that to
@@ -606,6 +613,16 @@ if test "$GCC" = yes -o "$SUN_STUDIO_CC" = yes ; then
   PGAC_PROG_VARCXX_VARFLAGS_OPT(CXX, CXXFLAGS_SL_MODULE, [-fvisibility=hidden])
   PGAC_PROG_VARCXX_VARFLAGS_OPT(CXX, CXXFLAGS_SL_MODULE, [-fvisibility-inlines-hidden])
   have_visibility_attribute=$pgac_cv_prog_CC_cflags__fvisibility_hidden
+elif test "$PORTNAME" = "aix"; then
+  # Note that xlc accepts -fvisibility=hidden as a file.
+  PGAC_PROG_CC_VAR_OPT(CFLAGS_SL_MODULE, [-qvisibility=hidden])
+  PGAC_PROG_VARCXX_VARFLAGS_OPT(CXX, CXXFLAGS_SL_MODULE, [-qvisibility=hidden])
+  have_visibility_attribute=$pgac_cv_prog_CC_cflags__qvisibility_hidden
+  # Old xlc versions (<13.1) don't have support for -qvisibility. Use expfull to force
+  # all extension module symbols to be exported.
+  if test "$pgac_cv_prog_CC_cflags__qvisibility_hidden" != "yes"; then
+    CFLAGS_SL_MODULE="$CFLAGS_SL_MODULE -Wl,-b,expfull"
+  fi
 fi
 
 if test "$have_visibility_attribute" = "yes"; then
@@ -1385,7 +1402,8 @@ if test "$with_zstd" = yes ; then
   AC_CHECK_LIB(zstd, ZSTD_compress, [], [AC_MSG_ERROR([library 'zstd' is required for ZSTD support])])
 fi
 
-# Note: We can test for libldap_r only after we know PTHREAD_LIBS
+# Note: We can test for libldap_r only after we know PTHREAD_LIBS;
+# also, on AIX, we may need to have openssl in LIBS for this step.
 if test "$with_ldap" = yes ; then
   _LIBS="$LIBS"
   if test "$PORTNAME" != "win32"; then
@@ -1643,8 +1661,12 @@ PGAC_TYPE_LOCALE_T
 # spelling it understands, because it conflicts with
 # __declspec(restrict). Therefore we define pg_restrict to the
 # appropriate definition, which presumably won't conflict.
+#
+# Allow platforms with buggy compilers to force restrict to not be
+# used by setting $FORCE_DISABLE_RESTRICT=yes in the relevant
+# template.
 AC_C_RESTRICT
-if test "$ac_cv_c_restrict" = "no"; then
+if test "$ac_cv_c_restrict" = "no" -o "x$FORCE_DISABLE_RESTRICT" = "xyes"; then
   pg_restrict=""
 else
   pg_restrict="$ac_cv_c_restrict"
@@ -1996,22 +2018,11 @@ fi
 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 long's alignment is at least as strong as char, short, or int;
+# but we must check long long (if it is being used for int64) and double.
+# 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'])
diff --git a/doc/src/sgml/dfunc.sgml b/doc/src/sgml/dfunc.sgml
index b94aefcd0c..554f9fac4c 100644
--- a/doc/src/sgml/dfunc.sgml
+++ b/doc/src/sgml/dfunc.sgml
@@ -202,4 +202,23 @@ gcc -G -o foo.so foo.o
   server expects to find the shared library files.
  </para>
 
+<!--
+Under AIX, object files are compiled normally but building the shared
+library requires a couple of steps.  First, create the object file:
+.nf
+cc <other flags> -c foo.c
+.fi
+You must then create a symbol \*(lqexports\*(rq file for the object
+file:
+.nf
+mkldexport foo.o `pwd` &gt; foo.exp
+.fi
+Finally, you can create the shared library:
+.nf
+ld <other flags> -H512 -T512 -o foo.so -e _nostart \e
+   -bI:.../lib/postgres.exp -bE:foo.exp foo.o \e
+   -lm -lc 2>/dev/null
+.fi
+  -->
+
 </sect2>
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 1b32d5ca62..6b27a1250b 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -3401,7 +3401,7 @@ export MANPATH
   <para>
    <productname>PostgreSQL</productname> can be expected to work on current
    versions of these operating systems: Linux, Windows,
-   FreeBSD, OpenBSD, NetBSD, DragonFlyBSD, macOS, Solaris, and illumos.
+   FreeBSD, OpenBSD, NetBSD, DragonFlyBSD, macOS, AIX, Solaris, and illumos.
    Other Unix-like systems may also work but are not currently
    being tested.  In most cases, all CPU architectures supported by
    a given operating system will work.  Look in
@@ -3445,6 +3445,123 @@ export MANPATH
    installation issues.
   </para>
 
+  <sect2 id="installation-notes-aix">
+   <title>AIX</title>
+
+   <indexterm zone="installation-notes-aix">
+    <primary>AIX</primary>
+    <secondary>installation on</secondary>
+   </indexterm>
+
+   <para>
+    You can use GCC or the native IBM compiler <command>xlc</command>
+    to build <productname>PostgreSQL</productname>
+    on <productname>AIX</productname>.
+   </para>
+
+   <para>
+    <productname>AIX</productname> versions before 7.1 are no longer
+    tested nor supported by the <productname>PostgreSQL</productname>
+    community.
+   </para>
+
+   <sect3 id="installation-notes-aix-mem-management">
+    <title>Memory Management</title>
+    <!-- https://archives.postgresql.org/message-id/603bgqmpl9.fsf@dba2.int.libertyrms.com -->
+
+    <para>
+     AIX can be somewhat peculiar with regards to the way it does
+     memory management.  You can have a server with many multiples of
+     gigabytes of RAM free, but still get out of memory or address
+     space errors when running applications.  One example
+     is loading of extensions failing with unusual errors.
+     For example, running as the owner of the PostgreSQL installation:
+<screen>
+=# CREATE EXTENSION plperl;
+ERROR:  could not load library "/opt/dbs/pgsql/lib/plperl.so": A memory address is not in the address space for the process.
+</screen>
+    Running as a non-owner in the group possessing the PostgreSQL
+    installation:
+<screen>
+=# CREATE EXTENSION plperl;
+ERROR:  could not load library "/opt/dbs/pgsql/lib/plperl.so": Bad address
+</screen>
+     Another example is out of memory errors in the PostgreSQL server
+     logs, with every memory allocation near or greater than 256 MB
+     failing.
+    </para>
+
+    <para>
+     The overall cause of all these problems is the default bittedness
+     and memory model used by the server process.  By default, all
+     binaries built on AIX are 32-bit.  This does not depend upon
+     hardware type or kernel in use.  These 32-bit processes are
+     limited to 4 GB of memory laid out in 256 MB segments using one
+     of a few models.  The default allows for less than 256 MB in the
+     heap as it shares a single segment with the stack.
+    </para>
+
+    <para>
+     In the case of the <literal>plperl</literal> example, above,
+     check your umask and the permissions of the binaries in your
+     PostgreSQL installation.  The binaries involved in that example
+     were 32-bit and installed as mode 750 instead of 755.  Due to the
+     permissions being set in this fashion, only the owner or a member
+     of the possessing group can load the library.  Since it isn't
+     world-readable, the loader places the object into the process'
+     heap instead of the shared library segments where it would
+     otherwise be placed.
+    </para>
+
+    <para>
+     The <quote>ideal</quote> solution for this is to use a 64-bit
+     build of PostgreSQL, but that is not always practical, because
+     systems with 32-bit processors can build, but not run, 64-bit
+     binaries.
+    </para>
+
+    <para>
+     If a 32-bit binary is desired, set <symbol>LDR_CNTRL</symbol> to
+     <literal>MAXDATA=0x<replaceable>n</replaceable>0000000</literal>,
+     where 1 &lt;= n &lt;= 8, before starting the PostgreSQL server,
+     and try different values and <filename>postgresql.conf</filename>
+     settings to find a configuration that works satisfactorily.  This
+     use of <symbol>LDR_CNTRL</symbol> tells AIX that you want the
+     server to have <symbol>MAXDATA</symbol> bytes set aside for the
+     heap, allocated in 256 MB segments.  When you find a workable
+     configuration,
+     <command>ldedit</command> can be used to modify the binaries so
+     that they default to using the desired heap size.  PostgreSQL can
+     also be rebuilt, passing <literal>configure
+     LDFLAGS="-Wl,-bmaxdata:0x<replaceable>n</replaceable>0000000"</literal>
+     to achieve the same effect.
+    </para>
+
+    <para>
+     For a 64-bit build, set <envar>OBJECT_MODE</envar> to 64 and
+     pass <literal>CC="gcc -maix64"</literal>
+     and <literal>LDFLAGS="-Wl,-bbigtoc"</literal>
+     to <command>configure</command>.  (Options for
+    <command>xlc</command> might differ.)  If you omit the export of
+    <envar>OBJECT_MODE</envar>, your build may fail with linker errors.  When
+    <envar>OBJECT_MODE</envar> is set, it tells AIX's build utilities
+    such as <command>ar</command>, <command>as</command>, and <command>ld</command> what
+    type of objects to default to handling.
+    </para>
+
+    <para>
+     By default, overcommit of paging space can happen.  While we have
+     not seen this occur, AIX will kill processes when it runs out of
+     memory and the overcommit is accessed.  The closest to this that
+     we have seen is fork failing because the system decided that
+     there was not enough memory for another process.  Like many other
+     parts of AIX, the paging space allocation method and
+     out-of-memory kill is configurable on a system- or process-wide
+     basis if this becomes a problem.
+    </para>
+   </sect3>
+  </sect2>
+
   <sect2 id="installation-notes-cygwin">
    <title>Cygwin</title>
 
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 6047b8171d..64753d9c01 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -891,6 +891,29 @@ psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: No such
 
 
     <variablelist>
+     <varlistentry>
+      <term><systemitem class="osname">AIX</systemitem>
+      <indexterm><primary>AIX</primary><secondary>IPC configuration</secondary></indexterm>
+      </term>
+      <listitem>
+       <para>
+        It should not be necessary to do
+        any special configuration for such parameters as
+        <varname>SHMMAX</varname>, as it appears this is configured to
+        allow all memory to be used as shared memory.  That is the
+        sort of configuration commonly used for other databases such
+        as <application>DB/2</application>.</para>
+
+       <para> It might, however, be necessary to modify the global
+       <command>ulimit</command> information in
+       <filename>/etc/security/limits</filename>, as the default hard
+       limits for file sizes (<varname>fsize</varname>) and numbers of
+       files (<varname>nofiles</varname>) might be too low.
+       </para>
+      </listitem>
+     </varlistentry>
+
+
      <varlistentry>
       <term><systemitem class="osname">FreeBSD</systemitem>
       <indexterm><primary>FreeBSD</primary><secondary>IPC configuration</secondary></indexterm>
diff --git a/meson.build b/meson.build
index 1c0579d5a6..f1ac154cdc 100644
--- a/meson.build
+++ b/meson.build
@@ -196,7 +196,26 @@ endif
 # that purpose.
 portname = host_system
 
-if host_system == 'cygwin'
+if host_system == 'aix'
+  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'
+
+  # M:SRE sets a flag indicating that an object is a shared library. Seems to
+  # work in some circumstances without, but required in others.
+  ldflags_sl += '-Wl,-bM:SRE'
+  ldflags_be += '-Wl,-brtllib'
+
+  # Native memset() is faster, tested on:
+  # - AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
+  # - AIX 5.3 ML3, gcc 4.0.1
+  memset_loop_limit = 0
+
+elif host_system == 'cygwin'
   sema_kind = 'unnamed_posix'
   cppflags += '-D_GNU_SOURCE'
   dlsuffix = '.dll'
@@ -1490,11 +1509,11 @@ sizeof_long = cc.sizeof('long', args: test_c_args)
 cdata.set('SIZEOF_LONG', sizeof_long)
 if sizeof_long == 8
   cdata.set('HAVE_LONG_INT_64', 1)
-  pg_int64_type = 'long int'
+  cdata.set('PG_INT64_TYPE', 'long int')
   cdata.set_quoted('INT64_MODIFIER', 'l')
 elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
   cdata.set('HAVE_LONG_LONG_INT_64', 1)
-  pg_int64_type = 'long long int'
+  cdata.set('PG_INT64_TYPE', 'long long int')
   cdata.set_quoted('INT64_MODIFIER', 'll')
 else
   error('do not know how to get a 64bit int')
@@ -1508,31 +1527,15 @@ endif
 # Determine memory alignment requirements for the basic C data types.
 
 alignof_types = ['short', 'int', 'long', 'double']
+maxalign = 0
 foreach t : alignof_types
   align = cc.alignment(t, args: test_c_args)
+  if maxalign < align
+    maxalign = align
+  endif
   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'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(pg_int64_type, args: test_c_args) > alignof_double
-  error('alignment of int64 is greater than the alignment of double')
-endif
-cdata.set('MAXIMUM_ALIGNOF', alignof_double)
+cdata.set('MAXIMUM_ALIGNOF', maxalign)
 
 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
@@ -1581,7 +1584,7 @@ if cc.links('''
   if not meson.is_cross_build()
     r = cc.run('''
     /* This must match the corresponding code in c.h: */
-    #if defined(__GNUC__) || defined(__SUNPRO_C)
+    #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
     #define pg_attribute_aligned(a) __attribute__((aligned(a)))
     #elif defined(_MSC_VER)
     #define pg_attribute_aligned(a) __declspec(align(a))
@@ -2476,6 +2479,10 @@ endif
 # conflict.
 #
 # We assume C99 support, so we don't need to make this conditional.
+#
+# XXX: Historically we allowed platforms to disable restrict in template
+# files, but that was only added for AIX when building with XLC, which we
+# don't support yet.
 cdata.set('pg_restrict', '__restrict')
 
 
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index fa81f6ffdd..8ca51ca03f 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,20 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +268,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps shared libraries inside a static library, can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +289,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +401,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +419,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 6700aec039..954b14962f 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -62,12 +62,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -94,6 +96,24 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
diff --git a/src/backend/meson.build b/src/backend/meson.build
index 436c04af08..8767aaba67 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -91,6 +91,21 @@ if cc.get_id() == 'msvc'
   # be restricted to b_pch=true.
   backend_link_with += postgres_lib
 
+elif 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
 
 backend_input = []
diff --git a/src/backend/port/aix/mkldexport.sh b/src/backend/port/aix/mkldexport.sh
new file mode 100755
index 0000000000..adf3793e86
--- /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/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 49637284f9..bade061271 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -788,7 +788,7 @@ ReadBuffer(Relation reln, BlockNumber blockNum)
  * If strategy is not NULL, a nondefault buffer access strategy is used.
  * See buffer/README for details.
  */
-inline Buffer
+Buffer
 ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 				   ReadBufferMode mode, BufferAccessStrategy strategy)
 {
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index d91a85cb2d..7b51e94f4a 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -908,7 +908,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/backend/utils/misc/ps_status.c b/src/backend/utils/misc/ps_status.c
index 9da6377402..532eac31b4 100644
--- a/src/backend/utils/misc/ps_status.c
+++ b/src/backend/utils/misc/ps_status.c
@@ -50,7 +50,7 @@ bool		update_process_title = DEFAULT_UPDATE_PROCESS_TITLE;
 #define PS_USE_SETPROCTITLE_FAST
 #elif defined(HAVE_SETPROCTITLE)
 #define PS_USE_SETPROCTITLE
-#elif defined(__linux__) || defined(__sun) || defined(__darwin__)
+#elif defined(__linux__) || defined(_AIX) || defined(__sun) || defined(__darwin__)
 #define PS_USE_CLOBBER_ARGV
 #elif defined(WIN32)
 #define PS_USE_WIN32
@@ -60,7 +60,7 @@ bool		update_process_title = DEFAULT_UPDATE_PROCESS_TITLE;
 
 
 /* Different systems want the buffer padded differently */
-#if defined(__linux__) || defined(__darwin__)
+#if defined(_AIX) || defined(__linux__) || defined(__darwin__)
 #define PS_PADDING '\0'
 #else
 #define PS_PADDING ' '
diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
index 2d4b75a6fe..ce936959c1 100644
--- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
+++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
@@ -401,7 +401,8 @@ SKIP:
 {
 	my $tar = $ENV{TAR};
 	# don't check for a working tar here, to accommodate various odd
-	# cases. If tar doesn't work the init_from_backup below will fail.
+	# cases such as AIX. If tar doesn't work the init_from_backup below
+	# will fail.
 	skip "no tar program available", 1
 	  if (!defined $tar || $tar eq '');
 
diff --git a/src/bin/pg_verifybackup/t/008_untar.pl b/src/bin/pg_verifybackup/t/008_untar.pl
index 7a09f3b75b..30d9f3f7f0 100644
--- a/src/bin/pg_verifybackup/t/008_untar.pl
+++ b/src/bin/pg_verifybackup/t/008_untar.pl
@@ -104,7 +104,8 @@ for my $tc (@test_configuration)
 		{
 			my $tar = $ENV{TAR};
 			# don't check for a working tar here, to accommodate various odd
-			# cases. If tar doesn't work the init_from_backup below will fail.
+			# cases such as AIX. If tar doesn't work the init_from_backup below
+			# will fail.
 			skip "no tar program available", 1
 			  if (!defined $tar || $tar eq '');
 
diff --git a/src/bin/pg_verifybackup/t/010_client_untar.pl b/src/bin/pg_verifybackup/t/010_client_untar.pl
index 8c076d46de..45010d79ac 100644
--- a/src/bin/pg_verifybackup/t/010_client_untar.pl
+++ b/src/bin/pg_verifybackup/t/010_client_untar.pl
@@ -134,7 +134,8 @@ for my $tc (@test_configuration)
 		{
 			my $tar = $ENV{TAR};
 			# don't check for a working tar here, to accommodate various odd
-			# cases. If tar doesn't work the init_from_backup below will fail.
+			# cases such as AIX. If tar doesn't work the init_from_backup below
+			# will fail.
 			skip "no tar program available", 1
 			  if (!defined $tar || $tar eq '');
 
diff --git a/src/include/c.h b/src/include/c.h
index dc1841346c..b667ac54a0 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -105,6 +105,8 @@
  * GCC: https://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html
  * Clang: https://clang.llvm.org/docs/AttributeReference.html
  * Sunpro: https://docs.oracle.com/cd/E18659_01/html/821-1384/gjzke.html
+ * XLC: https://www.ibm.com/support/knowledgecenter/SSGH2K_13.1.2/com.ibm.xlc131.aix.doc/language_ref/function_attributes.html
+ * XLC: https://www.ibm.com/support/knowledgecenter/SSGH2K_13.1.2/com.ibm.xlc131.aix.doc/language_ref/type_attrib.html
  */
 
 /*
@@ -182,8 +184,8 @@
 #define PG_USED_FOR_ASSERTS_ONLY pg_attribute_unused()
 #endif
 
-/* GCC supports format attributes */
-#if defined(__GNUC__)
+/* GCC and XLC support format attributes */
+#if defined(__GNUC__) || defined(__IBMC__)
 #define pg_attribute_format_arg(a) __attribute__((format_arg(a)))
 #define pg_attribute_printf(f,a) __attribute__((format(PG_PRINTF_ATTRIBUTE, f, a)))
 #else
@@ -191,8 +193,8 @@
 #define pg_attribute_printf(f,a)
 #endif
 
-/* GCC and Sunpro support aligned, packed and noreturn */
-#if defined(__GNUC__) || defined(__SUNPRO_C)
+/* GCC, Sunpro and XLC support aligned, packed and noreturn */
+#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
 #define pg_attribute_noreturn() __attribute__((noreturn))
 #define pg_attribute_packed() __attribute__((packed))
@@ -223,8 +225,8 @@
  * choose not to.  But, if possible, don't force inlining in unoptimized
  * debug builds.
  */
-#if (defined(__GNUC__) && __GNUC__ > 3 && defined(__OPTIMIZE__)) || defined(__SUNPRO_C)
-/* GCC > 3 and Sunpro support always_inline via __attribute__ */
+#if (defined(__GNUC__) && __GNUC__ > 3 && defined(__OPTIMIZE__)) || defined(__SUNPRO_C) || defined(__IBMC__)
+/* GCC > 3, Sunpro and XLC support always_inline via __attribute__ */
 #define pg_attribute_always_inline __attribute__((always_inline)) inline
 #elif defined(_MSC_VER)
 /* MSVC has a special keyword for this */
@@ -240,8 +242,8 @@
  * for proper cost attribution.  Note that unlike the pg_attribute_XXX macros
  * above, this should be placed before the function's return type and name.
  */
-/* GCC and Sunpro support noinline via __attribute__ */
-#if (defined(__GNUC__) && __GNUC__ > 2) || defined(__SUNPRO_C)
+/* GCC, Sunpro and XLC support noinline via __attribute__ */
+#if (defined(__GNUC__) && __GNUC__ > 2) || defined(__SUNPRO_C) || defined(__IBMC__)
 #define pg_noinline __attribute__((noinline))
 /* msvc via declspec */
 #elif defined(_MSC_VER)
diff --git a/src/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 0000000000..5b1159c578
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,14 @@
+/*
+ * src/include/port/aix.h
+ */
+#define CLASS_CONFLICT
+#define DISABLE_XOPEN_NLS
+
+/*
+ * "IBM XL C/C++ for AIX, V12.1" miscompiles, for 32-bit, some inline
+ * expansions of ginCompareItemPointers() "long long" arithmetic.  To take
+ * advantage of inlining, build a 64-bit PostgreSQL.
+ */
+#if defined(__ILP32__) && defined(__IBMC__)
+#define PG_FORCE_DISABLE_INLINE
+#endif
diff --git a/src/include/port/atomics.h b/src/include/port/atomics.h
index 78987f3154..5b2b70fe5f 100644
--- a/src/include/port/atomics.h
+++ b/src/include/port/atomics.h
@@ -84,9 +84,11 @@
  * using compiler intrinsics are a good idea.
  */
 /*
- * gcc or compatible, including clang and icc.
+ * gcc or compatible, including clang and icc.  Exclude xlc.  The ppc64le "IBM
+ * XL C/C++ for Linux, V13.1.2" emulates gcc, but __sync_lock_test_and_set()
+ * of one-byte types elicits SIGSEGV.  That bug was gone by V13.1.5 (2016-12).
  */
-#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+#if (defined(__GNUC__) || defined(__INTEL_COMPILER)) && !(defined(__IBMC__) || defined(__IBMCPP__))
 #include "port/atomics/generic-gcc.h"
 #elif defined(_MSC_VER)
 #include "port/atomics/generic-msvc.h"
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 29ac6cdcd9..69582f4ae7 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -414,6 +414,12 @@ typedef unsigned int slock_t;
  * 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.
+ *
+ * Ordinarily, we'd code the branches here using GNU-style local symbols, that
+ * is "1f" referencing "1:" and so on.  But some people run gcc on AIX with
+ * IBM's assembler as backend, and IBM's assembler doesn't do local symbols.
+ * So hand-code the branch offsets; fortunately, all PPC instructions are
+ * exactly 4 bytes each, so it's not too hard to count.
  */
 static __inline__ int
 tas(volatile slock_t *lock)
@@ -424,17 +430,15 @@ tas(volatile slock_t *lock)
 	__asm__ __volatile__(
 "	lwarx   %0,0,%3,1	\n"
 "	cmpwi   %0,0		\n"
-"	bne     1f			\n"
+"	bne     $+16		\n"		/* branch to li %1,1 */
 "	addi    %0,%0,1		\n"
 "	stwcx.  %0,0,%3		\n"
-"	beq     2f			\n"
-"1: \n"
+"	beq     $+12		\n"		/* branch to lwsync */
 "	li      %1,1		\n"
-"	b       3f			\n"
-"2: \n"
+"	b       $+12		\n"		/* branch to end of asm sequence */
 "	lwsync				\n"
 "	li      %1,0		\n"
-"3: \n"
+
 :	"=&b"(_t), "=r"(_res), "+m"(*lock)
 :	"r"(lock)
 :	"memory", "cc");
@@ -662,6 +666,21 @@ tas(volatile slock_t *lock)
 
 #if !defined(HAS_TEST_AND_SET)	/* We didn't trigger above, let's try here */
 
+#if defined(_AIX)	/* AIX */
+/*
+ * AIX (POWER)
+ */
+#define HAS_TEST_AND_SET
+
+#include <sys/atomic_op.h>
+
+typedef int slock_t;
+
+#define TAS(lock)			_check_lock((slock_t *) (lock), 0, 1)
+#define S_UNLOCK(lock)		_clear_lock((slock_t *) (lock), 0)
+#endif	 /* _AIX */
+
+
 /* These are in sunstudio_(sparc|x86).s */
 
 #if defined(__SUNPRO_C) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index b36a765764..154429d4d1 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -114,7 +114,7 @@ backend_src = $(top_srcdir)/src/backend
 # coding rule.
 libpq-refs-stamp: $(shlib)
 ifneq ($(enable_coverage), yes)
-ifeq (,$(filter solaris,$(PORTNAME)))
+ifeq (,$(filter aix solaris,$(PORTNAME)))
 	@if nm -A -u $< 2>/dev/null | grep -v -e __cxa_atexit -e __tsan_func_exit | grep exit; then \
 		echo 'libpq must not be calling any function which invokes exit'; exit 1; \
 	fi
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index ed2a4048d1..7e2017daf0 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -54,8 +54,9 @@ libpq_c_args = ['-DSO_MAJOR_VERSION=5']
 #    libpq_st, and {pgport,common}_shlib for libpq_sh
 #
 # We could try to avoid building the source files twice, but it probably adds
-# more complexity than its worth (reusing object files requires also linking
-# to the library on windows or breaks precompiled headers).
+# more complexity than its worth (AIX doesn't support link_whole yet, reusing
+# object files requires also linking to the library on windows or breaks
+# precompiled headers).
 libpq_st = static_library('libpq',
   libpq_sources,
   include_directories: [libpq_inc],
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 0000000000..dd16a7a037
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,39 @@
+# MAKE_EXPORTS is required for svr4 loaders that want a file of
+# symbol names to tell them what to export/import.
+MAKE_EXPORTS= true
+
+# -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
+
+rpath = -Wl,-blibpath:'$(rpathdir)$(libpath)'
+
+LDFLAGS_SL += -Wl,-bnoentry -Wl,-H512 -Wl,-bM:SRE
+
+# 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/port/README b/src/port/README
index ed5c54a72f..97f18a6233 100644
--- a/src/port/README
+++ b/src/port/README
@@ -28,5 +28,5 @@ applications.
 from libpgport are linked first.  This avoids having applications
 dependent on symbols that are _used_ by libpq, but not intended to be
 exported by libpq.  libpq's libpgport usage changes over time, so such a
-dependency is a problem.  Windows, Linux, and macOS use an export
+dependency is a problem.  Windows, Linux, AIX, and macOS use an export
 list to control the symbols exported by libpq.
diff --git a/src/port/strerror.c b/src/port/strerror.c
index 4918ba821c..1070a49802 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,8 +214,10 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
 			return "ENOTEMPTY";
+#endif
 		case ENOTSOCK:
 			return "ENOTSOCK";
 #ifdef ENOTSUP
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 0000000000..47fa8990a7
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,25 @@
+# src/template/aix
+
+# Set default options if using xlc.  This formerly included -qsrcmsg, but that
+# option elicits internal compiler errors from xlc v16.1.0.  Note: configure
+# will add -qnoansialias if the compiler accepts it, even if user specifies a
+# non-default CFLAGS setting.
+if test "$GCC" != yes ; then
+  case $host_os in
+    *)
+      CFLAGS="-O2 -qmaxmem=16384"
+      ;;
+  esac
+
+  # Due to a compiler bug, see 20171013023536.GA492146@rfd.leadboat.com for details,
+  # force restrict not to be used when compiling with xlc.
+  FORCE_DISABLE_RESTRICT=yes
+fi
+
+# Extra CFLAGS for code that will go into a shared library
+CFLAGS_SL=""
+
+# Native memset() is faster, tested on:
+# 	AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
+# 	AIX 5.3 ML3, gcc 4.0.1
+MEMSET_LOOP_LIMIT=0
diff --git a/src/test/regress/Makefile b/src/test/regress/Makefile
index 6409a485e8..7c665ff892 100644
--- a/src/test/regress/Makefile
+++ b/src/test/regress/Makefile
@@ -7,6 +7,11 @@
 # GNU make uses a make file named "GNUmakefile" in preference to "Makefile"
 # if it exists.  Postgres is shipped with a "GNUmakefile".
 
+
+# AIX make defaults to building *every* target of the first rule.  Start with
+# a single-target, empty rule to make the other targets non-default.
+all:
+
 all install clean check installcheck:
 	@echo "You must use GNU make to use Postgres.  It may be installed"
 	@echo "on your system with the name 'gmake'."
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 8370c1561c..c5c675b750 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -25,3 +25,32 @@ SELECT relname, relkind
 ---------+---------
 (0 rows)
 
+--
+-- When ALIGNOF_DOUBLE==4 (e.g. AIX), the C ABI may impose 8-byte alignment on
+-- some of the C types that correspond to TYPALIGN_DOUBLE SQL types.  To ensure
+-- catalog C struct layout matches catalog tuple layout, arrange for the tuple
+-- offset of each fixed-width, attalign='d' catalog column to be divisible by 8
+-- unconditionally.  Keep such columns before the first NameData column of the
+-- catalog, since packagers can override NAMEDATALEN to an odd number.
+--
+WITH check_columns AS (
+ SELECT relname, attname,
+  array(
+   SELECT t.oid
+    FROM pg_type t JOIN pg_attribute pa ON t.oid = pa.atttypid
+    WHERE pa.attrelid = a.attrelid AND
+          pa.attnum > 0 AND pa.attnum < a.attnum
+    ORDER BY pa.attnum) AS coltypes
+ FROM pg_attribute a JOIN pg_class c ON c.oid = attrelid
+  JOIN pg_namespace n ON c.relnamespace = n.oid
+ WHERE attalign = 'd' AND relkind = 'r' AND
+  attnotnull AND attlen <> -1 AND n.nspname = 'pg_catalog'
+)
+SELECT relname, attname, coltypes, get_columns_length(coltypes)
+ FROM check_columns
+ WHERE get_columns_length(coltypes) % 8 != 0 OR
+       'name'::regtype::oid = ANY(coltypes);
+ relname | attname | coltypes | get_columns_length 
+---------+---------+----------+--------------------
+(0 rows)
+
diff --git a/src/test/regress/expected/test_setup.out b/src/test/regress/expected/test_setup.out
index 3d0eeec996..5d9e6bf12b 100644
--- a/src/test/regress/expected/test_setup.out
+++ b/src/test/regress/expected/test_setup.out
@@ -209,6 +209,10 @@ CREATE FUNCTION ttdummy ()
     RETURNS trigger
     AS :'regresslib'
     LANGUAGE C;
+CREATE FUNCTION get_columns_length(oid[])
+    RETURNS int
+    AS :'regresslib'
+    LANGUAGE C STRICT STABLE PARALLEL SAFE;
 -- Use hand-rolled hash functions and operator classes to get predictable
 -- result on different machines.  The hash function for int4 simply returns
 -- the sum of the values passed to it and the one for text returns the length
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index deffaea578..cc633864d7 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -1221,3 +1221,43 @@ binary_coercible(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(IsBinaryCoercible(srctype, targettype));
 }
+
+/*
+ * Return the length of the portion of a tuple consisting of the given array
+ * of data types.  The input data types must be fixed-length data types.
+ */
+PG_FUNCTION_INFO_V1(get_columns_length);
+Datum
+get_columns_length(PG_FUNCTION_ARGS)
+{
+	ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
+	Oid		   *type_oids;
+	int			ntypes;
+	int			column_offset = 0;
+
+	if (ARR_HASNULL(ta) && array_contains_nulls(ta))
+		elog(ERROR, "argument must not contain nulls");
+
+	if (ARR_NDIM(ta) > 1)
+		elog(ERROR, "argument must be empty or one-dimensional array");
+
+	type_oids = (Oid *) ARR_DATA_PTR(ta);
+	ntypes = ArrayGetNItems(ARR_NDIM(ta), ARR_DIMS(ta));
+	for (int i = 0; i < ntypes; i++)
+	{
+		Oid			typeoid = type_oids[i];
+		int16		typlen;
+		bool		typbyval;
+		char		typalign;
+
+		get_typlenbyvalalign(typeoid, &typlen, &typbyval, &typalign);
+
+		/* the data type must be fixed-length */
+		if (typlen < 0)
+			elog(ERROR, "type %u is not fixed-length data type", typeoid);
+
+		column_offset = att_align_nominal(column_offset + typlen, typalign);
+	}
+
+	PG_RETURN_INT32(column_offset);
+}
diff --git a/src/test/regress/sql/sanity_check.sql b/src/test/regress/sql/sanity_check.sql
index 162e5324b5..7f338d191c 100644
--- a/src/test/regress/sql/sanity_check.sql
+++ b/src/test/regress/sql/sanity_check.sql
@@ -19,3 +19,29 @@ SELECT relname, relkind
   FROM pg_class
  WHERE relkind IN ('v', 'c', 'f', 'p', 'I')
        AND relfilenode <> 0;
+
+--
+-- When ALIGNOF_DOUBLE==4 (e.g. AIX), the C ABI may impose 8-byte alignment on
+-- some of the C types that correspond to TYPALIGN_DOUBLE SQL types.  To ensure
+-- catalog C struct layout matches catalog tuple layout, arrange for the tuple
+-- offset of each fixed-width, attalign='d' catalog column to be divisible by 8
+-- unconditionally.  Keep such columns before the first NameData column of the
+-- catalog, since packagers can override NAMEDATALEN to an odd number.
+--
+WITH check_columns AS (
+ SELECT relname, attname,
+  array(
+   SELECT t.oid
+    FROM pg_type t JOIN pg_attribute pa ON t.oid = pa.atttypid
+    WHERE pa.attrelid = a.attrelid AND
+          pa.attnum > 0 AND pa.attnum < a.attnum
+    ORDER BY pa.attnum) AS coltypes
+ FROM pg_attribute a JOIN pg_class c ON c.oid = attrelid
+  JOIN pg_namespace n ON c.relnamespace = n.oid
+ WHERE attalign = 'd' AND relkind = 'r' AND
+  attnotnull AND attlen <> -1 AND n.nspname = 'pg_catalog'
+)
+SELECT relname, attname, coltypes, get_columns_length(coltypes)
+ FROM check_columns
+ WHERE get_columns_length(coltypes) % 8 != 0 OR
+       'name'::regtype::oid = ANY(coltypes);
diff --git a/src/test/regress/sql/test_setup.sql b/src/test/regress/sql/test_setup.sql
index 06b0e2121f..1b2d434683 100644
--- a/src/test/regress/sql/test_setup.sql
+++ b/src/test/regress/sql/test_setup.sql
@@ -257,6 +257,11 @@ CREATE FUNCTION ttdummy ()
     AS :'regresslib'
     LANGUAGE C;
 
+CREATE FUNCTION get_columns_length(oid[])
+    RETURNS int
+    AS :'regresslib'
+    LANGUAGE C STRICT STABLE PARALLEL SAFE;
+
 -- Use hand-rolled hash functions and operator classes to get predictable
 -- result on different machines.  The hash function for int4 simply returns
 -- the sum of the values passed to it and the one for text returns the length
diff --git a/src/tools/gen_export.pl b/src/tools/gen_export.pl
index d9fdaaaf6d..888c8a197a 100644
--- a/src/tools/gen_export.pl
+++ b/src/tools/gen_export.pl
@@ -16,11 +16,12 @@ GetOptions(
 	'input:s' => \$input,
 	'output:s' => \$output) or die "wrong arguments";
 
-if (not(   $format eq 'darwin'
+if (not(   $format eq 'aix'
+		or $format eq 'darwin'
 		or $format eq 'gnu'
 		or $format eq 'win'))
 {
-	die "$0: $format is not yet handled (only darwin, gnu, win are)\n";
+	die "$0: $format is not yet handled (only aix, darwin, gnu, win are)\n";
 }
 
 open(my $input_handle, '<', $input)
@@ -55,7 +56,11 @@ while (<$input_handle>)
 	}
 	elsif (/^(\S+)\s+(\S+)/)
 	{
-		if ($format eq 'darwin')
+		if ($format eq 'aix')
+		{
+			print $output_handle "$1\n";
+		}
+		elsif ($format eq 'darwin')
 		{
 			print $output_handle "_$1\n";
 		}
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 4a157d0a5f..cfd8c6896c 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -85,6 +85,7 @@ do
 
 	# These files are platform-specific, and c.h will include the
 	# one that's relevant for our current platform anyway.
+	test "$f" = src/include/port/aix.h && continue
 	test "$f" = src/include/port/cygwin.h && continue
 	test "$f" = src/include/port/darwin.h && continue
 	test "$f" = src/include/port/freebsd.h && continue
-- 
2.41.0

#45Peter Eisentraut
peter@eisentraut.org
In reply to: Sriram RK (#44)
Re: AIX support

On 22.05.24 18:15, Sriram RK wrote:

Please find the attached patch.

Apart from the AIX specific changes, there is a minor change in this
file wrt to XLC, below is the error for which we removed inline.

Later, the build and tests passed for both XLC(16.1.0.18) and gcc(12) as
well.

I think what you should do next is aggressively trim anything that does
not apply to current versions of AIX or the current compiler.

For example,

+ # Old xlc versions (<13.1) don't have support for -qvisibility. Use
expfull to force

+   <para>
+    <productname>AIX</productname> versions before 7.1 are no longer
+    tested nor supported by the <productname>PostgreSQL</productname>
+    community.
+   </para>

(Probably most of that section needs to be retested and rewritten.)

+  # Native memset() is faster, tested on:
+  # - AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
+  # - AIX 5.3 ML3, gcc 4.0.1
+  memset_loop_limit = 0

+ # for the base executable (AIX 4.2 and up)

+ * "IBM XL C/C++ for AIX, V12.1" miscompiles, for 32-bit, some inline

One of the reasons that the AIX port ultimately became unmaintainable
was that so many hacks and caveats were accumulated over the years. A
new port should set a more recent baseline and trim all those hacks.

#46Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Peter Eisentraut (#45)
RE: AIX support

Hi Peter, thanks for your feedback.

We are eager to extend our support in resolving the issues specific to AIX or corresponding
compilers (XLC and cLang).

But as there are no issues with the patch after reverting the changes(with the latest compilers
gcc12 and xlc-16.0.1.18), we were wondering if this patch can be merged with the current release 17??

Having said that, we are committed to resolve all the hacks and caveats that got
accumulated specific to AIX over the period by picking and resolving one after the other,
rather than waiting for all the hacks to be fixed.

One of the reasons that the AIX port ultimately became unmaintainable
was that so many hacks and caveats were accumulated over the years. A
new port should set a more recent baseline and trim all those hacks.

Please help me understand this, with respect to the AIX specific hacks, is it just we can find
all the location where _AIX macros are involved OR can we just look at the patch changes only, as all
the changes that were made were specific to AIX. If not, is there any other location where
we could find all the hacks to be resolved.
Can you provide some more details on the expectations here?

Warm regards,
Sriram.

#47Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Srirama Kucherlapati (#46)
Re: AIX support

On 23/05/2024 18:36, Srirama Kucherlapati wrote:

Hi Peter, thanks for your feedback.

We are eager to extend our support in resolving the issues specific
to AIX or corresponding compilers (XLC and cLang).

But as there are no issues with the patch after reverting the
changes(with the latest compilers gcc12 and xlc-16.0.1.18), we were
wondering if this patch can be merged with the current release 17??

Having said that, we are committed to resolve all the hacks and
caveats that got accumulated specific to AIX over the period by
picking and resolving one after the other, rather than waiting for
all the hacks to be fixed.

I'm not eager to put back those hacks just to have them be removed
again. So I'd like to see a minimal patch, with the *minimal* changes
required for AIX support. And perhaps split that into two patches: First
add back AIX support with GCC, and second patch to add XLC support. I'd
like to to see how much of the changes are because of the different
compiler and how much from the OS.

No promises for v17, but if the patch is small and non-intrusive, I
would consider it at least. But let's see what it looks like first. It's
the same work that needs to be done whether it goes into v17 or v18 anyway.

One of the reasons that the AIX port ultimately became
unmaintainable was that so many hacks and caveats were accumulated
over the years. A new port should set a more recent baseline and
trim all those hacks.

Please help me understand this, with respect to the AIX specific
hacks, is it just we can find all the location where _AIX macros are
involved OR can we just look at the patch changes only, as all the
changes that were made were specific to AIX. If not, is there any
other location where we could find all the hacks to be resolved.

Can you provide some more details on the expectations here?

Smallest possible patch that makes Postgres work on AIX again.

Perhaps start with the patch you posted yesterday, but remove hunks from
it one by one, to see which ones are still needed.

--
Heikki Linnakangas
Neon (https://neon.tech)

#48Bruce Momjian
bruce@momjian.us
In reply to: Heikki Linnakangas (#47)
Re: AIX support

On Thu, May 23, 2024 at 07:03:20PM +0300, Heikki Linnakangas wrote:

Can you provide some more details on the expectations here?

Smallest possible patch that makes Postgres work on AIX again.

Perhaps start with the patch you posted yesterday, but remove hunks from it
one by one, to see which ones are still needed.

Yes, bingo, that is exactly what needs to be done, and for the minimal
compiler, gcc, and the most recently supported versions of AIX.

--
Bruce Momjian <bruce@momjian.us> https://momjian.us
EDB https://enterprisedb.com

Only you can decide what is important to you.

#49Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Bruce Momjian (#48)
RE: AIX support

Hi Team, We are pursuing to trim the changes wrt AIX. As of now we trimmed
the changes with respect to XLC and currently with trimmed changes the
buildfarm script passed (build and all the regression tests)
The XLC changes were trimmed only in the below file
modified: configure
modified: configure.ac
We are looking further into the other file changes as well.

Warm regards,
Sriram.

#50Laurenz Albe
laurenz.albe@cybertec.at
In reply to: Srirama Kucherlapati (#49)
Re: AIX support

On Fri, 2024-06-07 at 16:30 +0000, Srirama Kucherlapati wrote:

Hi Team, We are pursuing to trim the changes wrt AIX. As of now we trimmed
the changes with respect to XLC and currently with trimmed changes the
buildfarm script passed (build and all the regression tests)
The XLC changes were trimmed only in the below file
    modified: configure
    modified: configure.ac

Did you forget an attachment?

Yours,
Laurenz Albe

#51Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Laurenz Albe (#50)
RE: AIX support

Hi Laurenz, we are working on the other file changes, we shall post you the updates soon.
Warm regards,
Sriram.

#52Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#51)
1 attachment(s)
RE: AIX support

Hi Team,
Please find the attached patch, which resumes the AIX support with gcc alone. We have
removed changes wrt to XLC on AIX.

We are also continuing to work on the XLC and IBM-clang(openXLC) specific patch as well.
Once we get an approval for the above patch we can submit a subsequent patch to support
XLC/IBM-clang changes.

Kindly let us know your inputs/feedback.

Warm regards,
Sriram.

Attachments:

0001-AIX-support-revert-the-changes-from-0b16bb8776bb8-v2.patchapplication/octet-stream; name=0001-AIX-support-revert-the-changes-from-0b16bb8776bb8-v2.patchDownload
From b88f2a8cad14c09bd872f303a27a60e93a916fea Mon Sep 17 00:00:00 2001
From: Sriram RK <sriram.rk@in.ibm.com>
Date: Mon, 20 May 2024 01:38:59 -0500
Subject: [PATCH 1/1] AIX support, revert the changes from 0b16bb8776bb8. Trim
 AIX/XLC changes to support gcc only.

---
 Makefile                                      |   2 -
 configure                                     |  52 ++++----
 configure.ac                                  |  31 ++---
 doc/src/sgml/dfunc.sgml                       |  19 +++
 doc/src/sgml/installation.sgml                | 118 +++++++++++++++++-
 doc/src/sgml/runtime.sgml                     |  23 ++++
 meson.build                                   |  57 +++++----
 src/Makefile.shlib                            |  29 +++++
 src/backend/Makefile                          |  20 +++
 src/backend/meson.build                       |  15 +++
 src/backend/port/aix/mkldexport.sh            |  61 +++++++++
 src/backend/utils/error/elog.c                |   2 +
 src/backend/utils/misc/ps_status.c            |   4 +-
 src/bin/pg_basebackup/t/010_pg_basebackup.pl  |   3 +-
 src/bin/pg_verifybackup/t/008_untar.pl        |   3 +-
 src/bin/pg_verifybackup/t/010_client_untar.pl |   3 +-
 src/include/c.h                               |   4 +-
 src/include/port/aix.h                        |  14 +++
 src/include/storage/s_lock.h                  |  31 ++++-
 src/interfaces/libpq/Makefile                 |   2 +-
 src/interfaces/libpq/meson.build              |   5 +-
 src/makefiles/Makefile.aix                    |  39 ++++++
 src/port/README                               |   2 +-
 src/port/strerror.c                           |   2 +
 src/template/aix                              |  26 ++++
 src/test/regress/Makefile                     |   5 +
 src/test/regress/expected/sanity_check.out    |  29 +++++
 src/test/regress/expected/test_setup.out      |   4 +
 src/test/regress/regress.c                    |  40 ++++++
 src/test/regress/sql/sanity_check.sql         |  26 ++++
 src/test/regress/sql/test_setup.sql           |   5 +
 src/tools/gen_export.pl                       |  11 +-
 src/tools/pginclude/headerscheck              |   1 +
 33 files changed, 598 insertions(+), 90 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 create mode 100644 src/include/port/aix.h
 create mode 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index 8a2ec9396b..9bc1a4ec17 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/configure b/configure
index 89644f2249..03271f1861 100755
--- a/configure
+++ b/configure
@@ -2988,6 +2988,7 @@ else
 # --with-template not given
 
 case $host_os in
+     aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -6849,6 +6850,11 @@ if test x"$pgac_cv_prog_CXX_cxxflags__fno_strict_aliasing" = x"yes"; then
 fi
 
 
+elif test "$PORTNAME" = "aix"; then
+  # AIX's xlc has to have strict aliasing turned off too
+  # Igonoring the XLC falgs -qnoansialias, -qlonglong
+{ $as_echo_n "Running AIX gcc for now... " >&6; }
+
 fi
 
 # If the compiler knows how to hide symbols, add the switch needed for that to
@@ -7003,6 +7009,9 @@ if test x"$pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden" = x"yes"; then
 fi
 
   have_visibility_attribute=$pgac_cv_prog_CC_cflags__fvisibility_hidden
+elif test "$PORTNAME" = "aix"; then
+  # Note that xlc accepts -fvisibility=hidden as a file.
+  { $as_echo_n "Running AIX gcc for now... " >&6; }
 fi
 
 if test "$have_visibility_attribute" = "yes"; then
@@ -12860,7 +12869,8 @@ fi
 
 fi
 
-# Note: We can test for libldap_r only after we know PTHREAD_LIBS
+# Note: We can test for libldap_r only after we know PTHREAD_LIBS;
+# also, on AIX, we may need to have openssl in LIBS for this step.
 if test "$with_ldap" = yes ; then
   _LIBS="$LIBS"
   if test "$PORTNAME" != "win32"; then
@@ -14718,6 +14728,10 @@ fi
 # spelling it understands, because it conflicts with
 # __declspec(restrict). Therefore we define pg_restrict to the
 # appropriate definition, which presumably won't conflict.
+#
+# Allow platforms with buggy compilers to force restrict to not be
+# used by setting $FORCE_DISABLE_RESTRICT=yes in the relevant
+# template.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
 $as_echo_n "checking for C/C++ restrict keyword... " >&6; }
 if ${ac_cv_c_restrict+:} false; then :
@@ -14764,7 +14778,7 @@ _ACEOF
  ;;
  esac
 
-if test "$ac_cv_c_restrict" = "no"; then
+if test "$ac_cv_c_restrict" = "no" -o "x$FORCE_DISABLE_RESTRICT" = "xyes"; then
   pg_restrict=""
 else
   pg_restrict="$ac_cv_c_restrict"
@@ -16951,28 +16965,18 @@ _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 x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+# We assume long's alignment is at least as strong as char, short, or int;
+# but we must check long long (if it is being used for int64) and double.
+# 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_long
+if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+  MAX_ALIGNOF=$ac_cv_alignof_double
+fi
+if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $MAX_ALIGNOF -lt $ac_cv_alignof_long_long_int ; then
+  MAX_ALIGNOF="$ac_cv_alignof_long_long_int"
 fi
 
 cat >>confdefs.h <<_ACEOF
diff --git a/configure.ac b/configure.ac
index c7322e292c..22069395a6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ PGAC_ARG_REQ(with, template, [NAME], [override operating system template],
 # --with-template not given
 
 case $host_os in
+     aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -1385,7 +1386,8 @@ if test "$with_zstd" = yes ; then
   AC_CHECK_LIB(zstd, ZSTD_compress, [], [AC_MSG_ERROR([library 'zstd' is required for ZSTD support])])
 fi
 
-# Note: We can test for libldap_r only after we know PTHREAD_LIBS
+# Note: We can test for libldap_r only after we know PTHREAD_LIBS;
+# also, on AIX, we may need to have openssl in LIBS for this step.
 if test "$with_ldap" = yes ; then
   _LIBS="$LIBS"
   if test "$PORTNAME" != "win32"; then
@@ -1643,8 +1645,12 @@ PGAC_TYPE_LOCALE_T
 # spelling it understands, because it conflicts with
 # __declspec(restrict). Therefore we define pg_restrict to the
 # appropriate definition, which presumably won't conflict.
+#
+# Allow platforms with buggy compilers to force restrict to not be
+# used by setting $FORCE_DISABLE_RESTRICT=yes in the relevant
+# template.
 AC_C_RESTRICT
-if test "$ac_cv_c_restrict" = "no"; then
+if test "$ac_cv_c_restrict" = "no" -o "x$FORCE_DISABLE_RESTRICT" = "xyes"; then
   pg_restrict=""
 else
   pg_restrict="$ac_cv_c_restrict"
@@ -1996,22 +2002,11 @@ fi
 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 long's alignment is at least as strong as char, short, or int;
+# but we must check long long (if it is being used for int64) and double.
+# 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'])
diff --git a/doc/src/sgml/dfunc.sgml b/doc/src/sgml/dfunc.sgml
index b94aefcd0c..554f9fac4c 100644
--- a/doc/src/sgml/dfunc.sgml
+++ b/doc/src/sgml/dfunc.sgml
@@ -202,4 +202,23 @@ gcc -G -o foo.so foo.o
   server expects to find the shared library files.
  </para>
 
+<!--
+Under AIX, object files are compiled normally but building the shared
+library requires a couple of steps.  First, create the object file:
+.nf
+cc <other flags> -c foo.c
+.fi
+You must then create a symbol \*(lqexports\*(rq file for the object
+file:
+.nf
+mkldexport foo.o `pwd` &gt; foo.exp
+.fi
+Finally, you can create the shared library:
+.nf
+ld <other flags> -H512 -T512 -o foo.so -e _nostart \e
+   -bI:.../lib/postgres.exp -bE:foo.exp foo.o \e
+   -lm -lc 2>/dev/null
+.fi
+  -->
+
 </sect2>
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 1b32d5ca62..60e9a34a03 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -3401,7 +3401,7 @@ export MANPATH
   <para>
    <productname>PostgreSQL</productname> can be expected to work on current
    versions of these operating systems: Linux, Windows,
-   FreeBSD, OpenBSD, NetBSD, DragonFlyBSD, macOS, Solaris, and illumos.
+   FreeBSD, OpenBSD, NetBSD, DragonFlyBSD, macOS, AIX, Solaris, and illumos.
    Other Unix-like systems may also work but are not currently
    being tested.  In most cases, all CPU architectures supported by
    a given operating system will work.  Look in
@@ -3445,6 +3445,122 @@ export MANPATH
    installation issues.
   </para>
 
+  <sect2 id="installation-notes-aix">
+   <title>AIX</title>
+
+   <indexterm zone="installation-notes-aix">
+    <primary>AIX</primary>
+    <secondary>installation on</secondary>
+   </indexterm>
+
+   <para>
+    You can use GCC to build <productname>PostgreSQL</productname>
+    on <productname>AIX</productname>.
+   </para>
+
+   <para>
+    <productname>AIX</productname> versions before 7.1 are no longer
+    tested nor supported by the <productname>PostgreSQL</productname>
+    community.
+   </para>
+
+   <sect3 id="installation-notes-aix-mem-management">
+    <title>Memory Management</title>
+    <!-- https://archives.postgresql.org/message-id/603bgqmpl9.fsf@dba2.int.libertyrms.com -->
+
+    <para>
+     AIX can be somewhat peculiar with regards to the way it does
+     memory management.  You can have a server with many multiples of
+     gigabytes of RAM free, but still get out of memory or address
+     space errors when running applications.  One example
+     is loading of extensions failing with unusual errors.
+     For example, running as the owner of the PostgreSQL installation:
+<screen>
+=# CREATE EXTENSION plperl;
+ERROR:  could not load library "/opt/dbs/pgsql/lib/plperl.so": A memory address is not in the address space for the process.
+</screen>
+    Running as a non-owner in the group possessing the PostgreSQL
+    installation:
+<screen>
+=# CREATE EXTENSION plperl;
+ERROR:  could not load library "/opt/dbs/pgsql/lib/plperl.so": Bad address
+</screen>
+     Another example is out of memory errors in the PostgreSQL server
+     logs, with every memory allocation near or greater than 256 MB
+     failing.
+    </para>
+
+    <para>
+     The overall cause of all these problems is the default bittedness
+     and memory model used by the server process.  By default, all
+     binaries built on AIX are 32-bit.  This does not depend upon
+     hardware type or kernel in use.  These 32-bit processes are
+     limited to 4 GB of memory laid out in 256 MB segments using one
+     of a few models.  The default allows for less than 256 MB in the
+     heap as it shares a single segment with the stack.
+    </para>
+
+    <para>
+     In the case of the <literal>plperl</literal> example, above,
+     check your umask and the permissions of the binaries in your
+     PostgreSQL installation.  The binaries involved in that example
+     were 32-bit and installed as mode 750 instead of 755.  Due to the
+     permissions being set in this fashion, only the owner or a member
+     of the possessing group can load the library.  Since it isn't
+     world-readable, the loader places the object into the process'
+     heap instead of the shared library segments where it would
+     otherwise be placed.
+    </para>
+
+    <para>
+     The <quote>ideal</quote> solution for this is to use a 64-bit
+     build of PostgreSQL, but that is not always practical, because
+     systems with 32-bit processors can build, but not run, 64-bit
+     binaries.
+    </para>
+
+    <para>
+     If a 32-bit binary is desired, set <symbol>LDR_CNTRL</symbol> to
+     <literal>MAXDATA=0x<replaceable>n</replaceable>0000000</literal>,
+     where 1 &lt;= n &lt;= 8, before starting the PostgreSQL server,
+     and try different values and <filename>postgresql.conf</filename>
+     settings to find a configuration that works satisfactorily.  This
+     use of <symbol>LDR_CNTRL</symbol> tells AIX that you want the
+     server to have <symbol>MAXDATA</symbol> bytes set aside for the
+     heap, allocated in 256 MB segments.  When you find a workable
+     configuration,
+     <command>ldedit</command> can be used to modify the binaries so
+     that they default to using the desired heap size.  PostgreSQL can
+     also be rebuilt, passing <literal>configure
+     LDFLAGS="-Wl,-bmaxdata:0x<replaceable>n</replaceable>0000000"</literal>
+     to achieve the same effect.
+    </para>
+
+    <para>
+     For a 64-bit build, set <envar>OBJECT_MODE</envar> to 64 and
+     pass <literal>CC="gcc -maix64"</literal>
+     and <literal>LDFLAGS="-Wl,-bbigtoc"</literal>
+     to <command>configure</command>. 
+     If you omit the export of
+    <envar>OBJECT_MODE</envar>, your build may fail with linker errors.  When
+    <envar>OBJECT_MODE</envar> is set, it tells AIX's build utilities
+    such as <command>ar</command>, <command>as</command>, and <command>ld</command> what
+    type of objects to default to handling.
+    </para>
+
+    <para>
+     By default, overcommit of paging space can happen.  While we have
+     not seen this occur, AIX will kill processes when it runs out of
+     memory and the overcommit is accessed.  The closest to this that
+     we have seen is fork failing because the system decided that
+     there was not enough memory for another process.  Like many other
+     parts of AIX, the paging space allocation method and
+     out-of-memory kill is configurable on a system- or process-wide
+     basis if this becomes a problem.
+    </para>
+   </sect3>
+  </sect2>
+
   <sect2 id="installation-notes-cygwin">
    <title>Cygwin</title>
 
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 6047b8171d..64753d9c01 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -891,6 +891,29 @@ psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: No such
 
 
     <variablelist>
+     <varlistentry>
+      <term><systemitem class="osname">AIX</systemitem>
+      <indexterm><primary>AIX</primary><secondary>IPC configuration</secondary></indexterm>
+      </term>
+      <listitem>
+       <para>
+        It should not be necessary to do
+        any special configuration for such parameters as
+        <varname>SHMMAX</varname>, as it appears this is configured to
+        allow all memory to be used as shared memory.  That is the
+        sort of configuration commonly used for other databases such
+        as <application>DB/2</application>.</para>
+
+       <para> It might, however, be necessary to modify the global
+       <command>ulimit</command> information in
+       <filename>/etc/security/limits</filename>, as the default hard
+       limits for file sizes (<varname>fsize</varname>) and numbers of
+       files (<varname>nofiles</varname>) might be too low.
+       </para>
+      </listitem>
+     </varlistentry>
+
+
      <varlistentry>
       <term><systemitem class="osname">FreeBSD</systemitem>
       <indexterm><primary>FreeBSD</primary><secondary>IPC configuration</secondary></indexterm>
diff --git a/meson.build b/meson.build
index 1c0579d5a6..f1ac154cdc 100644
--- a/meson.build
+++ b/meson.build
@@ -196,7 +196,26 @@ endif
 # that purpose.
 portname = host_system
 
-if host_system == 'cygwin'
+if host_system == 'aix'
+  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'
+
+  # M:SRE sets a flag indicating that an object is a shared library. Seems to
+  # work in some circumstances without, but required in others.
+  ldflags_sl += '-Wl,-bM:SRE'
+  ldflags_be += '-Wl,-brtllib'
+
+  # Native memset() is faster, tested on:
+  # - AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
+  # - AIX 5.3 ML3, gcc 4.0.1
+  memset_loop_limit = 0
+
+elif host_system == 'cygwin'
   sema_kind = 'unnamed_posix'
   cppflags += '-D_GNU_SOURCE'
   dlsuffix = '.dll'
@@ -1490,11 +1509,11 @@ sizeof_long = cc.sizeof('long', args: test_c_args)
 cdata.set('SIZEOF_LONG', sizeof_long)
 if sizeof_long == 8
   cdata.set('HAVE_LONG_INT_64', 1)
-  pg_int64_type = 'long int'
+  cdata.set('PG_INT64_TYPE', 'long int')
   cdata.set_quoted('INT64_MODIFIER', 'l')
 elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
   cdata.set('HAVE_LONG_LONG_INT_64', 1)
-  pg_int64_type = 'long long int'
+  cdata.set('PG_INT64_TYPE', 'long long int')
   cdata.set_quoted('INT64_MODIFIER', 'll')
 else
   error('do not know how to get a 64bit int')
@@ -1508,31 +1527,15 @@ endif
 # Determine memory alignment requirements for the basic C data types.
 
 alignof_types = ['short', 'int', 'long', 'double']
+maxalign = 0
 foreach t : alignof_types
   align = cc.alignment(t, args: test_c_args)
+  if maxalign < align
+    maxalign = align
+  endif
   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'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(pg_int64_type, args: test_c_args) > alignof_double
-  error('alignment of int64 is greater than the alignment of double')
-endif
-cdata.set('MAXIMUM_ALIGNOF', alignof_double)
+cdata.set('MAXIMUM_ALIGNOF', maxalign)
 
 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
@@ -1581,7 +1584,7 @@ if cc.links('''
   if not meson.is_cross_build()
     r = cc.run('''
     /* This must match the corresponding code in c.h: */
-    #if defined(__GNUC__) || defined(__SUNPRO_C)
+    #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
     #define pg_attribute_aligned(a) __attribute__((aligned(a)))
     #elif defined(_MSC_VER)
     #define pg_attribute_aligned(a) __declspec(align(a))
@@ -2476,6 +2479,10 @@ endif
 # conflict.
 #
 # We assume C99 support, so we don't need to make this conditional.
+#
+# XXX: Historically we allowed platforms to disable restrict in template
+# files, but that was only added for AIX when building with XLC, which we
+# don't support yet.
 cdata.set('pg_restrict', '__restrict')
 
 
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index fa81f6ffdd..8ca51ca03f 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,20 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +268,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps shared libraries inside a static library, can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +289,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +401,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +419,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 6700aec039..954b14962f 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -62,12 +62,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -94,6 +96,24 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
diff --git a/src/backend/meson.build b/src/backend/meson.build
index 436c04af08..8767aaba67 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -91,6 +91,21 @@ if cc.get_id() == 'msvc'
   # be restricted to b_pch=true.
   backend_link_with += postgres_lib
 
+elif 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
 
 backend_input = []
diff --git a/src/backend/port/aix/mkldexport.sh b/src/backend/port/aix/mkldexport.sh
new file mode 100755
index 0000000000..adf3793e86
--- /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/utils/error/elog.c b/src/backend/utils/error/elog.c
index d91a85cb2d..7b51e94f4a 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -908,7 +908,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/backend/utils/misc/ps_status.c b/src/backend/utils/misc/ps_status.c
index 9da6377402..532eac31b4 100644
--- a/src/backend/utils/misc/ps_status.c
+++ b/src/backend/utils/misc/ps_status.c
@@ -50,7 +50,7 @@ bool		update_process_title = DEFAULT_UPDATE_PROCESS_TITLE;
 #define PS_USE_SETPROCTITLE_FAST
 #elif defined(HAVE_SETPROCTITLE)
 #define PS_USE_SETPROCTITLE
-#elif defined(__linux__) || defined(__sun) || defined(__darwin__)
+#elif defined(__linux__) || defined(_AIX) || defined(__sun) || defined(__darwin__)
 #define PS_USE_CLOBBER_ARGV
 #elif defined(WIN32)
 #define PS_USE_WIN32
@@ -60,7 +60,7 @@ bool		update_process_title = DEFAULT_UPDATE_PROCESS_TITLE;
 
 
 /* Different systems want the buffer padded differently */
-#if defined(__linux__) || defined(__darwin__)
+#if defined(_AIX) || defined(__linux__) || defined(__darwin__)
 #define PS_PADDING '\0'
 #else
 #define PS_PADDING ' '
diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
index 2d4b75a6fe..ce936959c1 100644
--- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
+++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
@@ -401,7 +401,8 @@ SKIP:
 {
 	my $tar = $ENV{TAR};
 	# don't check for a working tar here, to accommodate various odd
-	# cases. If tar doesn't work the init_from_backup below will fail.
+	# cases such as AIX. If tar doesn't work the init_from_backup below
+	# will fail.
 	skip "no tar program available", 1
 	  if (!defined $tar || $tar eq '');
 
diff --git a/src/bin/pg_verifybackup/t/008_untar.pl b/src/bin/pg_verifybackup/t/008_untar.pl
index 7a09f3b75b..30d9f3f7f0 100644
--- a/src/bin/pg_verifybackup/t/008_untar.pl
+++ b/src/bin/pg_verifybackup/t/008_untar.pl
@@ -104,7 +104,8 @@ for my $tc (@test_configuration)
 		{
 			my $tar = $ENV{TAR};
 			# don't check for a working tar here, to accommodate various odd
-			# cases. If tar doesn't work the init_from_backup below will fail.
+			# cases such as AIX. If tar doesn't work the init_from_backup below
+			# will fail.
 			skip "no tar program available", 1
 			  if (!defined $tar || $tar eq '');
 
diff --git a/src/bin/pg_verifybackup/t/010_client_untar.pl b/src/bin/pg_verifybackup/t/010_client_untar.pl
index 8c076d46de..45010d79ac 100644
--- a/src/bin/pg_verifybackup/t/010_client_untar.pl
+++ b/src/bin/pg_verifybackup/t/010_client_untar.pl
@@ -134,7 +134,8 @@ for my $tc (@test_configuration)
 		{
 			my $tar = $ENV{TAR};
 			# don't check for a working tar here, to accommodate various odd
-			# cases. If tar doesn't work the init_from_backup below will fail.
+			# cases such as AIX. If tar doesn't work the init_from_backup below
+			# will fail.
 			skip "no tar program available", 1
 			  if (!defined $tar || $tar eq '');
 
diff --git a/src/include/c.h b/src/include/c.h
index dc1841346c..641cd9bdf1 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -182,7 +182,7 @@
 #define PG_USED_FOR_ASSERTS_ONLY pg_attribute_unused()
 #endif
 
-/* GCC supports format attributes */
+/* GCC support format attributes */
 #if defined(__GNUC__)
 #define pg_attribute_format_arg(a) __attribute__((format_arg(a)))
 #define pg_attribute_printf(f,a) __attribute__((format(PG_PRINTF_ATTRIBUTE, f, a)))
@@ -192,7 +192,7 @@
 #endif
 
 /* GCC and Sunpro support aligned, packed and noreturn */
-#if defined(__GNUC__) || defined(__SUNPRO_C)
+#if defined(__GNUC__) || defined(__SUNPRO_C) 
 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
 #define pg_attribute_noreturn() __attribute__((noreturn))
 #define pg_attribute_packed() __attribute__((packed))
diff --git a/src/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 0000000000..c54c95d4a5
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,14 @@
+/*
+ * src/include/port/aix.h
+ */
+#define CLASS_CONFLICT
+#define DISABLE_XOPEN_NLS
+
+/* Commenting for XLC
+ * "IBM XL C/C++ for AIX, V12.1" miscompiles, for 32-bit, some inline
+ * expansions of ginCompareItemPointers() "long long" arithmetic.  To take
+ * advantage of inlining, build a 64-bit PostgreSQL.
+#if defined(__ILP32__) && defined(__IBMC__)
+#define PG_FORCE_DISABLE_INLINE
+#endif
+ */
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 29ac6cdcd9..69582f4ae7 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -414,6 +414,12 @@ typedef unsigned int slock_t;
  * 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.
+ *
+ * Ordinarily, we'd code the branches here using GNU-style local symbols, that
+ * is "1f" referencing "1:" and so on.  But some people run gcc on AIX with
+ * IBM's assembler as backend, and IBM's assembler doesn't do local symbols.
+ * So hand-code the branch offsets; fortunately, all PPC instructions are
+ * exactly 4 bytes each, so it's not too hard to count.
  */
 static __inline__ int
 tas(volatile slock_t *lock)
@@ -424,17 +430,15 @@ tas(volatile slock_t *lock)
 	__asm__ __volatile__(
 "	lwarx   %0,0,%3,1	\n"
 "	cmpwi   %0,0		\n"
-"	bne     1f			\n"
+"	bne     $+16		\n"		/* branch to li %1,1 */
 "	addi    %0,%0,1		\n"
 "	stwcx.  %0,0,%3		\n"
-"	beq     2f			\n"
-"1: \n"
+"	beq     $+12		\n"		/* branch to lwsync */
 "	li      %1,1		\n"
-"	b       3f			\n"
-"2: \n"
+"	b       $+12		\n"		/* branch to end of asm sequence */
 "	lwsync				\n"
 "	li      %1,0		\n"
-"3: \n"
+
 :	"=&b"(_t), "=r"(_res), "+m"(*lock)
 :	"r"(lock)
 :	"memory", "cc");
@@ -662,6 +666,21 @@ tas(volatile slock_t *lock)
 
 #if !defined(HAS_TEST_AND_SET)	/* We didn't trigger above, let's try here */
 
+#if defined(_AIX)	/* AIX */
+/*
+ * AIX (POWER)
+ */
+#define HAS_TEST_AND_SET
+
+#include <sys/atomic_op.h>
+
+typedef int slock_t;
+
+#define TAS(lock)			_check_lock((slock_t *) (lock), 0, 1)
+#define S_UNLOCK(lock)		_clear_lock((slock_t *) (lock), 0)
+#endif	 /* _AIX */
+
+
 /* These are in sunstudio_(sparc|x86).s */
 
 #if defined(__SUNPRO_C) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index b36a765764..154429d4d1 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -114,7 +114,7 @@ backend_src = $(top_srcdir)/src/backend
 # coding rule.
 libpq-refs-stamp: $(shlib)
 ifneq ($(enable_coverage), yes)
-ifeq (,$(filter solaris,$(PORTNAME)))
+ifeq (,$(filter aix solaris,$(PORTNAME)))
 	@if nm -A -u $< 2>/dev/null | grep -v -e __cxa_atexit -e __tsan_func_exit | grep exit; then \
 		echo 'libpq must not be calling any function which invokes exit'; exit 1; \
 	fi
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index ed2a4048d1..7e2017daf0 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -54,8 +54,9 @@ libpq_c_args = ['-DSO_MAJOR_VERSION=5']
 #    libpq_st, and {pgport,common}_shlib for libpq_sh
 #
 # We could try to avoid building the source files twice, but it probably adds
-# more complexity than its worth (reusing object files requires also linking
-# to the library on windows or breaks precompiled headers).
+# more complexity than its worth (AIX doesn't support link_whole yet, reusing
+# object files requires also linking to the library on windows or breaks
+# precompiled headers).
 libpq_st = static_library('libpq',
   libpq_sources,
   include_directories: [libpq_inc],
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 0000000000..dd16a7a037
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,39 @@
+# MAKE_EXPORTS is required for svr4 loaders that want a file of
+# symbol names to tell them what to export/import.
+MAKE_EXPORTS= true
+
+# -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
+
+rpath = -Wl,-blibpath:'$(rpathdir)$(libpath)'
+
+LDFLAGS_SL += -Wl,-bnoentry -Wl,-H512 -Wl,-bM:SRE
+
+# 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/port/README b/src/port/README
index ed5c54a72f..97f18a6233 100644
--- a/src/port/README
+++ b/src/port/README
@@ -28,5 +28,5 @@ applications.
 from libpgport are linked first.  This avoids having applications
 dependent on symbols that are _used_ by libpq, but not intended to be
 exported by libpq.  libpq's libpgport usage changes over time, so such a
-dependency is a problem.  Windows, Linux, and macOS use an export
+dependency is a problem.  Windows, Linux, AIX, and macOS use an export
 list to control the symbols exported by libpq.
diff --git a/src/port/strerror.c b/src/port/strerror.c
index 4918ba821c..1070a49802 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,8 +214,10 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
 			return "ENOTEMPTY";
+#endif
 		case ENOTSOCK:
 			return "ENOTSOCK";
 #ifdef ENOTSUP
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 0000000000..903f8a8f8a
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,26 @@
+# src/template/aix
+
+# Commenting for XLC
+# Set default options if using xlc.  This formerly included -qsrcmsg, but that
+# option elicits internal compiler errors from xlc v16.1.0.  Note: configure
+# will add -qnoansialias if the compiler accepts it, even if user specifies a
+# non-default CFLAGS setting.
+#if test "$GCC" != yes ; then
+#  case $host_os in
+#    *)
+#      CFLAGS="-O2 -qmaxmem=16384"
+#      ;;
+#  esac
+
+  # Due to a compiler bug, see 20171013023536.GA492146@rfd.leadboat.com for details,
+  # force restrict not to be used when compiling with xlc.
+#  FORCE_DISABLE_RESTRICT=yes
+#fi
+
+# Extra CFLAGS for code that will go into a shared library
+CFLAGS_SL=""
+
+# Native memset() is faster, tested on:
+# 	AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
+# 	AIX 5.3 ML3, gcc 4.0.1
+MEMSET_LOOP_LIMIT=0
diff --git a/src/test/regress/Makefile b/src/test/regress/Makefile
index 6409a485e8..7c665ff892 100644
--- a/src/test/regress/Makefile
+++ b/src/test/regress/Makefile
@@ -7,6 +7,11 @@
 # GNU make uses a make file named "GNUmakefile" in preference to "Makefile"
 # if it exists.  Postgres is shipped with a "GNUmakefile".
 
+
+# AIX make defaults to building *every* target of the first rule.  Start with
+# a single-target, empty rule to make the other targets non-default.
+all:
+
 all install clean check installcheck:
 	@echo "You must use GNU make to use Postgres.  It may be installed"
 	@echo "on your system with the name 'gmake'."
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 8370c1561c..c5c675b750 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -25,3 +25,32 @@ SELECT relname, relkind
 ---------+---------
 (0 rows)
 
+--
+-- When ALIGNOF_DOUBLE==4 (e.g. AIX), the C ABI may impose 8-byte alignment on
+-- some of the C types that correspond to TYPALIGN_DOUBLE SQL types.  To ensure
+-- catalog C struct layout matches catalog tuple layout, arrange for the tuple
+-- offset of each fixed-width, attalign='d' catalog column to be divisible by 8
+-- unconditionally.  Keep such columns before the first NameData column of the
+-- catalog, since packagers can override NAMEDATALEN to an odd number.
+--
+WITH check_columns AS (
+ SELECT relname, attname,
+  array(
+   SELECT t.oid
+    FROM pg_type t JOIN pg_attribute pa ON t.oid = pa.atttypid
+    WHERE pa.attrelid = a.attrelid AND
+          pa.attnum > 0 AND pa.attnum < a.attnum
+    ORDER BY pa.attnum) AS coltypes
+ FROM pg_attribute a JOIN pg_class c ON c.oid = attrelid
+  JOIN pg_namespace n ON c.relnamespace = n.oid
+ WHERE attalign = 'd' AND relkind = 'r' AND
+  attnotnull AND attlen <> -1 AND n.nspname = 'pg_catalog'
+)
+SELECT relname, attname, coltypes, get_columns_length(coltypes)
+ FROM check_columns
+ WHERE get_columns_length(coltypes) % 8 != 0 OR
+       'name'::regtype::oid = ANY(coltypes);
+ relname | attname | coltypes | get_columns_length 
+---------+---------+----------+--------------------
+(0 rows)
+
diff --git a/src/test/regress/expected/test_setup.out b/src/test/regress/expected/test_setup.out
index 3d0eeec996..5d9e6bf12b 100644
--- a/src/test/regress/expected/test_setup.out
+++ b/src/test/regress/expected/test_setup.out
@@ -209,6 +209,10 @@ CREATE FUNCTION ttdummy ()
     RETURNS trigger
     AS :'regresslib'
     LANGUAGE C;
+CREATE FUNCTION get_columns_length(oid[])
+    RETURNS int
+    AS :'regresslib'
+    LANGUAGE C STRICT STABLE PARALLEL SAFE;
 -- Use hand-rolled hash functions and operator classes to get predictable
 -- result on different machines.  The hash function for int4 simply returns
 -- the sum of the values passed to it and the one for text returns the length
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index deffaea578..cc633864d7 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -1221,3 +1221,43 @@ binary_coercible(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(IsBinaryCoercible(srctype, targettype));
 }
+
+/*
+ * Return the length of the portion of a tuple consisting of the given array
+ * of data types.  The input data types must be fixed-length data types.
+ */
+PG_FUNCTION_INFO_V1(get_columns_length);
+Datum
+get_columns_length(PG_FUNCTION_ARGS)
+{
+	ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
+	Oid		   *type_oids;
+	int			ntypes;
+	int			column_offset = 0;
+
+	if (ARR_HASNULL(ta) && array_contains_nulls(ta))
+		elog(ERROR, "argument must not contain nulls");
+
+	if (ARR_NDIM(ta) > 1)
+		elog(ERROR, "argument must be empty or one-dimensional array");
+
+	type_oids = (Oid *) ARR_DATA_PTR(ta);
+	ntypes = ArrayGetNItems(ARR_NDIM(ta), ARR_DIMS(ta));
+	for (int i = 0; i < ntypes; i++)
+	{
+		Oid			typeoid = type_oids[i];
+		int16		typlen;
+		bool		typbyval;
+		char		typalign;
+
+		get_typlenbyvalalign(typeoid, &typlen, &typbyval, &typalign);
+
+		/* the data type must be fixed-length */
+		if (typlen < 0)
+			elog(ERROR, "type %u is not fixed-length data type", typeoid);
+
+		column_offset = att_align_nominal(column_offset + typlen, typalign);
+	}
+
+	PG_RETURN_INT32(column_offset);
+}
diff --git a/src/test/regress/sql/sanity_check.sql b/src/test/regress/sql/sanity_check.sql
index 162e5324b5..7f338d191c 100644
--- a/src/test/regress/sql/sanity_check.sql
+++ b/src/test/regress/sql/sanity_check.sql
@@ -19,3 +19,29 @@ SELECT relname, relkind
   FROM pg_class
  WHERE relkind IN ('v', 'c', 'f', 'p', 'I')
        AND relfilenode <> 0;
+
+--
+-- When ALIGNOF_DOUBLE==4 (e.g. AIX), the C ABI may impose 8-byte alignment on
+-- some of the C types that correspond to TYPALIGN_DOUBLE SQL types.  To ensure
+-- catalog C struct layout matches catalog tuple layout, arrange for the tuple
+-- offset of each fixed-width, attalign='d' catalog column to be divisible by 8
+-- unconditionally.  Keep such columns before the first NameData column of the
+-- catalog, since packagers can override NAMEDATALEN to an odd number.
+--
+WITH check_columns AS (
+ SELECT relname, attname,
+  array(
+   SELECT t.oid
+    FROM pg_type t JOIN pg_attribute pa ON t.oid = pa.atttypid
+    WHERE pa.attrelid = a.attrelid AND
+          pa.attnum > 0 AND pa.attnum < a.attnum
+    ORDER BY pa.attnum) AS coltypes
+ FROM pg_attribute a JOIN pg_class c ON c.oid = attrelid
+  JOIN pg_namespace n ON c.relnamespace = n.oid
+ WHERE attalign = 'd' AND relkind = 'r' AND
+  attnotnull AND attlen <> -1 AND n.nspname = 'pg_catalog'
+)
+SELECT relname, attname, coltypes, get_columns_length(coltypes)
+ FROM check_columns
+ WHERE get_columns_length(coltypes) % 8 != 0 OR
+       'name'::regtype::oid = ANY(coltypes);
diff --git a/src/test/regress/sql/test_setup.sql b/src/test/regress/sql/test_setup.sql
index 06b0e2121f..1b2d434683 100644
--- a/src/test/regress/sql/test_setup.sql
+++ b/src/test/regress/sql/test_setup.sql
@@ -257,6 +257,11 @@ CREATE FUNCTION ttdummy ()
     AS :'regresslib'
     LANGUAGE C;
 
+CREATE FUNCTION get_columns_length(oid[])
+    RETURNS int
+    AS :'regresslib'
+    LANGUAGE C STRICT STABLE PARALLEL SAFE;
+
 -- Use hand-rolled hash functions and operator classes to get predictable
 -- result on different machines.  The hash function for int4 simply returns
 -- the sum of the values passed to it and the one for text returns the length
diff --git a/src/tools/gen_export.pl b/src/tools/gen_export.pl
index d9fdaaaf6d..888c8a197a 100644
--- a/src/tools/gen_export.pl
+++ b/src/tools/gen_export.pl
@@ -16,11 +16,12 @@ GetOptions(
 	'input:s' => \$input,
 	'output:s' => \$output) or die "wrong arguments";
 
-if (not(   $format eq 'darwin'
+if (not(   $format eq 'aix'
+		or $format eq 'darwin'
 		or $format eq 'gnu'
 		or $format eq 'win'))
 {
-	die "$0: $format is not yet handled (only darwin, gnu, win are)\n";
+	die "$0: $format is not yet handled (only aix, darwin, gnu, win are)\n";
 }
 
 open(my $input_handle, '<', $input)
@@ -55,7 +56,11 @@ while (<$input_handle>)
 	}
 	elsif (/^(\S+)\s+(\S+)/)
 	{
-		if ($format eq 'darwin')
+		if ($format eq 'aix')
+		{
+			print $output_handle "$1\n";
+		}
+		elsif ($format eq 'darwin')
 		{
 			print $output_handle "_$1\n";
 		}
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 4a157d0a5f..cfd8c6896c 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -85,6 +85,7 @@ do
 
 	# These files are platform-specific, and c.h will include the
 	# one that's relevant for our current platform anyway.
+	test "$f" = src/include/port/aix.h && continue
 	test "$f" = src/include/port/cygwin.h && continue
 	test "$f" = src/include/port/darwin.h && continue
 	test "$f" = src/include/port/freebsd.h && continue
-- 
2.41.0

#53Heikki Linnakangas
hlinnaka@gmail.com
In reply to: Srirama Kucherlapati (#52)
Re: AIX support

On 19/06/2024 17:55, Srirama Kucherlapati wrote:

+/* Commenting for XLC
+ * "IBM XL C/C++ for AIX, V12.1" miscompiles, for 32-bit, some inline
+ * expansions of ginCompareItemPointers() "long long" arithmetic.  To take
+ * advantage of inlining, build a 64-bit PostgreSQL.
+#if defined(__ILP32__) && defined(__IBMC__)
+#define PG_FORCE_DISABLE_INLINE
+#endif
+ */

This seems irrelevant.

+ * Ordinarily, we'd code the branches here using GNU-style local symbols, that
+ * is "1f" referencing "1:" and so on.  But some people run gcc on AIX with
+ * IBM's assembler as backend, and IBM's assembler doesn't do local symbols.
+ * So hand-code the branch offsets; fortunately, all PPC instructions are
+ * exactly 4 bytes each, so it's not too hard to count.

Could you use GCC assembler to avoid this?

@@ -662,6 +666,21 @@ tas(volatile slock_t *lock)

#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */

+#if defined(_AIX)	/* AIX */
+/*
+ * AIX (POWER)
+ */
+#define HAS_TEST_AND_SET
+
+#include <sys/atomic_op.h>
+
+typedef int slock_t;
+
+#define TAS(lock)			_check_lock((slock_t *) (lock), 0, 1)
+#define S_UNLOCK(lock)		_clear_lock((slock_t *) (lock), 0)
+#endif	 /* _AIX */
+
+
/* These are in sunstudio_(sparc|x86).s */

#if defined(__SUNPRO_C) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))

What CPI/compiler/OS configuration is this for, exactly? Could we rely
on GCC-provided __sync_lock_test_and_set() builtin function instead?

+# Allow platforms with buggy compilers to force restrict to not be
+# used by setting $FORCE_DISABLE_RESTRICT=yes in the relevant
+# template.

Surely we don't need that anymore? Or is the compiler still buggy?

Do you still care about 32-bit binaries on AIX? If not, let's make that
the default in configure or a check for it, and remove the instructions
on building 32-bit binaries from the docs.

Please try hard to remove any changes from the diff that are not
absolutely necessary.

- Heikki

#54Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Heikki Linnakangas (#53)
RE: AIX support

Thanks Hikki, for going through the changes.

+/* Commenting for XLC
+ * "IBM XL C/C++ for AIX, V12.1" miscompiles, for 32-bit, some inline
+ * expansions of ginCompareItemPointers() "long long" arithmetic.  To take
+ * advantage of inlining, build a 64-bit PostgreSQL.
+#if defined(__ILP32__) && defined(__IBMC__)
+#define PG_FORCE_DISABLE_INLINE
+#endif
+ */

I can remove these unwanted comments.

I have to analyze the changes for the rest of your comment and will get back to you.

Warm regards,
Sriram.

From: Heikki Linnakangas <hlinnaka@gmail.com>
Date: Wednesday, 19 June 2024 at 8:45 PM
To: Srirama Kucherlapati <sriram.rk@in.ibm.com>, Laurenz Albe <laurenz.albe@cybertec.at>, Bruce Momjian <bruce@momjian.us>, Heikki Linnakangas <hlinnaka@iki.fi>
Cc: Peter Eisentraut <peter@eisentraut.org>, Alvaro Herrera <alvherre@alvh.no-ip.org>, pgsql-hackers@postgresql.org <pgsql-hackers@postgresql.org>, Noah Misch <noah@leadboat.com>, Michael Paquier <michael@paquier.xyz>, Andres Freund <andres@anarazel.de>, Tom Lane <tgl@sss.pgh.pa.us>, Thomas Munro <thomas.munro@gmail.com>, tvk1271@gmail.com <tvk1271@gmail.com>, postgres-ibm-aix@wwpdl.vnet.ibm.com <postgres-ibm-aix@wwpdl.vnet.ibm.com>
Subject: [EXTERNAL] Re: AIX support
On 19/06/2024 17:55, Srirama Kucherlapati wrote:

+/* Commenting for XLC
+ * "IBM XL C/C++ for AIX, V12.1" miscompiles, for 32-bit, some inline
+ * expansions of ginCompareItemPointers() "long long" arithmetic.  To take
+ * advantage of inlining, build a 64-bit PostgreSQL.
+#if defined(__ILP32__) && defined(__IBMC__)
+#define PG_FORCE_DISABLE_INLINE
+#endif
+ */

This seems irrelevant.

+ * Ordinarily, we'd code the branches here using GNU-style local symbols, that
+ * is "1f" referencing "1:" and so on.  But some people run gcc on AIX with
+ * IBM's assembler as backend, and IBM's assembler doesn't do local symbols.
+ * So hand-code the branch offsets; fortunately, all PPC instructions are
+ * exactly 4 bytes each, so it's not too hard to count.

Could you use GCC assembler to avoid this?

@@ -662,6 +666,21 @@ tas(volatile slock_t *lock)

#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */

+#if defined(_AIX)    /* AIX */
+/*
+ * AIX (POWER)
+ */
+#define HAS_TEST_AND_SET
+
+#include <sys/atomic_op.h>
+
+typedef int slock_t;
+
+#define TAS(lock)                    _check_lock((slock_t *) (lock), 0, 1)
+#define S_UNLOCK(lock)               _clear_lock((slock_t *) (lock), 0)
+#endif        /* _AIX */
+
+
/* These are in sunstudio_(sparc|x86).s */

#if defined(__SUNPRO_C) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))

What CPI/compiler/OS configuration is this for, exactly? Could we rely
on GCC-provided __sync_lock_test_and_set() builtin function instead?

+# Allow platforms with buggy compilers to force restrict to not be
+# used by setting $FORCE_DISABLE_RESTRICT=yes in the relevant
+# template.

Surely we don't need that anymore? Or is the compiler still buggy?

Do you still care about 32-bit binaries on AIX? If not, let's make that
the default in configure or a check for it, and remove the instructions
on building 32-bit binaries from the docs.

Please try hard to remove any changes from the diff that are not
absolutely necessary.

- Heikki

#55Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#54)
RE: AIX support

We are continuing to work on the changes…

Do you still care about 32-bit binaries on AIX? If not, let's make that
the default in configure or a check for it, and remove the instructions
on building 32-bit binaries from the docs.

As most of the products are moving towards 64bit, we will try to remove
this 32bit support.

Warm regards,
Sriram.

#56Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#55)
1 attachment(s)
RE: AIX support

Hi Heikki & Team,

I tried to look at the assembly code changes with our team, in the below file.

diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h

index 29ac6cdcd9..69582f4ae7 100644

--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h

static __inline__ int

tas(volatile slock_t *lock)

@@ -424,17 +430,15 @@ tas(volatile slock_t *lock)

__asm__ __volatile__(

" lwarx %0,0,%3,1 \n"

" cmpwi %0,0 \n"

" bne $+16 \n" /* branch to li %1,1 */

" addi %0,%0,1 \n"

" stwcx. %0,0,%3 \n"

" beq $+12 \n" /* branch to lwsync */

" li %1,1 \n"

" b $+12 \n" /* branch to end of asm sequence */

" lwsync \n"

" li %1,0 \n"

: "=&b"(_t), "=r"(_res), "+m"(*lock)

: "r"(lock)

: "memory", "cc");

For the changes in the above file, this code is very specific to power architecture we need to use the IBM Power specific asm code only, rather than using the GNU assembler. Also, all these asm specific code is under the macro __ppc__, which should not impact any other platforms. I see there is a GCC specific implementation (under this macro #if defined(HAVE_GCC__SYNC_INT32_TAS)) in the same file as well.

+#define TAS(lock) _check_lock((slock_t *) (lock), 0, 1)

+#define S_UNLOCK(lock) _clear_lock((slock_t *) (lock), 0)

The above changes are specific to AIX kernel and it operates on fixed kernel memory. This is more like a compare_and_swap functionality with sync capability. For all the assemble code I think it would be better to use the IBM Power specific asm code to gain additional performance.

I was trying to understand here wrt to both the assemble changes if you are looking for anything specific to the architecture.

Attached is the patch for the previous comments, kindly please let me know your comments.

Warm regards,
Sriram.

Attachments:

0001-AIX-support-revert-changes-from-0b16bb8776bb.v3.patchapplication/octet-stream; name=0001-AIX-support-revert-changes-from-0b16bb8776bb.v3.patchDownload
From 0d69a26fc1b52fb3e274176a83e7772b05bd7025 Mon Sep 17 00:00:00 2001
From: Sriram RK <sriram.rk@in.ibm.com>
Date: Tue, 13 Aug 2024 08:19:25 -0500
Subject: [PATCH] AIX support revert changes from 0b16bb8776bb. Review comments
 from Heikki

---
 configure                    | 17 ++---------------
 configure.ac                 |  5 +----
 src/include/port/aix.h       |  8 --------
 src/include/storage/s_lock.h |  6 ------
 src/template/aix             | 12 ------------
 5 files changed, 3 insertions(+), 45 deletions(-)

diff --git a/configure b/configure
index 03271f1861..f218b2e040 100755
--- a/configure
+++ b/configure
@@ -6849,12 +6849,6 @@ if test x"$pgac_cv_prog_CXX_cxxflags__fno_strict_aliasing" = x"yes"; then
   CXXFLAGS="${CXXFLAGS} -fno-strict-aliasing"
 fi
 
-
-elif test "$PORTNAME" = "aix"; then
-  # AIX's xlc has to have strict aliasing turned off too
-  # Igonoring the XLC falgs -qnoansialias, -qlonglong
-{ $as_echo_n "Running AIX gcc for now... " >&6; }
-
 fi
 
 # If the compiler knows how to hide symbols, add the switch needed for that to
@@ -7009,9 +7003,6 @@ if test x"$pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden" = x"yes"; then
 fi
 
   have_visibility_attribute=$pgac_cv_prog_CC_cflags__fvisibility_hidden
-elif test "$PORTNAME" = "aix"; then
-  # Note that xlc accepts -fvisibility=hidden as a file.
-  { $as_echo_n "Running AIX gcc for now... " >&6; }
 fi
 
 if test "$have_visibility_attribute" = "yes"; then
@@ -14728,10 +14719,6 @@ fi
 # spelling it understands, because it conflicts with
 # __declspec(restrict). Therefore we define pg_restrict to the
 # appropriate definition, which presumably won't conflict.
-#
-# Allow platforms with buggy compilers to force restrict to not be
-# used by setting $FORCE_DISABLE_RESTRICT=yes in the relevant
-# template.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
 $as_echo_n "checking for C/C++ restrict keyword... " >&6; }
 if ${ac_cv_c_restrict+:} false; then :
@@ -14778,7 +14765,7 @@ _ACEOF
  ;;
  esac
 
-if test "$ac_cv_c_restrict" = "no" -o "x$FORCE_DISABLE_RESTRICT" = "xyes"; then
+if test "$ac_cv_c_restrict" = "no"; then
   pg_restrict=""
 else
   pg_restrict="$ac_cv_c_restrict"
@@ -17094,7 +17081,7 @@ else
 /* end confdefs.h.  */
 
 /* This must match the corresponding code in c.h: */
-#if defined(__GNUC__) || defined(__SUNPRO_C)
+#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
 #elif defined(_MSC_VER)
 #define pg_attribute_aligned(a) __declspec(align(a))
diff --git a/configure.ac b/configure.ac
index 22069395a6..a059509cd9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1646,11 +1646,8 @@ PGAC_TYPE_LOCALE_T
 # __declspec(restrict). Therefore we define pg_restrict to the
 # appropriate definition, which presumably won't conflict.
 #
-# Allow platforms with buggy compilers to force restrict to not be
-# used by setting $FORCE_DISABLE_RESTRICT=yes in the relevant
-# template.
 AC_C_RESTRICT
-if test "$ac_cv_c_restrict" = "no" -o "x$FORCE_DISABLE_RESTRICT" = "xyes"; then
+if test "$ac_cv_c_restrict" = "no" ; then
   pg_restrict=""
 else
   pg_restrict="$ac_cv_c_restrict"
diff --git a/src/include/port/aix.h b/src/include/port/aix.h
index c54c95d4a5..1c2d166791 100644
--- a/src/include/port/aix.h
+++ b/src/include/port/aix.h
@@ -4,11 +4,3 @@
 #define CLASS_CONFLICT
 #define DISABLE_XOPEN_NLS
 
-/* Commenting for XLC
- * "IBM XL C/C++ for AIX, V12.1" miscompiles, for 32-bit, some inline
- * expansions of ginCompareItemPointers() "long long" arithmetic.  To take
- * advantage of inlining, build a 64-bit PostgreSQL.
-#if defined(__ILP32__) && defined(__IBMC__)
-#define PG_FORCE_DISABLE_INLINE
-#endif
- */
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 69582f4ae7..2f6eb5df2a 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -414,12 +414,6 @@ typedef unsigned int slock_t;
  * 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.
- *
- * Ordinarily, we'd code the branches here using GNU-style local symbols, that
- * is "1f" referencing "1:" and so on.  But some people run gcc on AIX with
- * IBM's assembler as backend, and IBM's assembler doesn't do local symbols.
- * So hand-code the branch offsets; fortunately, all PPC instructions are
- * exactly 4 bytes each, so it's not too hard to count.
  */
 static __inline__ int
 tas(volatile slock_t *lock)
diff --git a/src/template/aix b/src/template/aix
index 903f8a8f8a..0a788676c0 100644
--- a/src/template/aix
+++ b/src/template/aix
@@ -1,17 +1,5 @@
 # src/template/aix
 
-# Commenting for XLC
-# Set default options if using xlc.  This formerly included -qsrcmsg, but that
-# option elicits internal compiler errors from xlc v16.1.0.  Note: configure
-# will add -qnoansialias if the compiler accepts it, even if user specifies a
-# non-default CFLAGS setting.
-#if test "$GCC" != yes ; then
-#  case $host_os in
-#    *)
-#      CFLAGS="-O2 -qmaxmem=16384"
-#      ;;
-#  esac
-
   # Due to a compiler bug, see 20171013023536.GA492146@rfd.leadboat.com for details,
   # force restrict not to be used when compiling with xlc.
 #  FORCE_DISABLE_RESTRICT=yes
-- 
2.41.0

#57Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Srirama Kucherlapati (#56)
Re: AIX support

On 14/08/2024 06:31, Srirama Kucherlapati wrote:

Hi Heikki & Team,

I tried to look at the assembly code changes with our team, in the below
file.

diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 29ac6cdcd9..69582f4ae7 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
static __inline__ int
tas(volatile slock_t *lock)
@@ -424,17 +430,15 @@ tas(volatile slock_t *lock)
__asm__ __volatile__(
"        lwarx   %0,0,%3,1        \n"
"        cmpwi   %0,0                \n"
"        bne     $+16                \n"                /* branch to li 
%1,1 */
"        addi    %0,%0,1                \n"
"        stwcx.  %0,0,%3                \n"
"        beq     $+12                \n"                /* branch to 
lwsync */
"        li      %1,1                \n"
"        b       $+12                \n"                /* branch to end 
of asm sequence */
"        lwsync                                \n"
"        li      %1,0                \n"
:        "=&b"(_t), "=r"(_res), "+m"(*lock)
:        "r"(lock)
:        "memory", "cc");

For the changes in the above file,  this code is very specific to power
architecture we need to use the IBM Power specific asm code only, rather
than using the GNU assembler. Also, all these asm specific code is under
the macro __ppc__, which should not impact any other platforms. I see
there is a GCC specific implementation (under this macro #if
defined(HAVE_GCC__SYNC_INT32_TAS)) in the same file as well.

I'm sorry, I don't understand what you're saying here. Do you mean that
we don't need to do anything here, and the code we have in s_lock.h in
'master' now will work fine on AIX? Or do we need to (re-)do some
changes to support AIX again? If we only support GCC, can we use the
__sync_lock_test_and_set() builtin instead?

If any changes are required, please include them in the patch. That'll
make it clear what exactly you're proposing.

+#define TAS(lock)                      _check_lock((slock_t *) (lock),
0, 1)

+#define S_UNLOCK(lock)         _clear_lock((slock_t *) (lock), 0)

The above changes are specific to AIX kernel and it operates on fixed
kernel memory. This is more like a compare_and_swap functionality with
sync capability. For all the assemble code I think it would be better to
use the IBM Power specific asm code to gain additional performance.

You mean we don't need the above? Ok, good.

I was trying to understand here wrt to both the assemble changes if you
are looking for anything specific to the architecture.

I don't know. You tell me what makes most sense on AIX / powerpc.

Attached is the patch for the previous comments, kindly please let me
know your comments.

Is this all that's needed to resurrect AIX support?

--
Heikki Linnakangas
Neon (https://neon.tech)

#58Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Heikki Linnakangas (#57)
1 attachment(s)
RE: AIX support

Hi Heikki,
I have attached the merged patch with all the changes, the earlier patch was
just only the changes specific to older review comments.

I'm sorry, I don't understand what you're saying here. Do you mean that
we don't need to do anything here, and the code we have in s_lock.h in
'master' now will work fine on AIX? Or do we need to (re-)do some
changes to support AIX again? If we only support GCC, can we use the
__sync_lock_test_and_set() builtin instead?

Here we need these changes for ppc. These changes are not for enabling
the AIX support, but this is implementing “Enhanced PowerPC Architecture”.
This routine is more of compare_and_increment, which is different from
GCC __sync_lock_test_and_set(). Also I tried to write a sample function to
check the assemble generated by __sync_lock_test_and_set(), which turned out to
be different set of assemble code.

+#define TAS(lock) _check_lock((slock_t *) (lock),
0, 1)

+#define S_UNLOCK(lock) _clear_lock((slock_t *) (lock), 0)

The above changes are specific to AIX kernel and it operates on fixed
kernel memory. This is more like a compare_and_swap functionality with
sync capability. For all the assemble code I think it would be better to
use the IBM Power specific asm code to gain additional performance.

You mean we don't need the above? Ok, good.

I mean this part of the code is needed as this is specific to AIX kernel memory
operation which is different from __sync_lock_test_and_set().

I would like to mention that the changes made in src/include/storage/s_lock.h
are pretty much required and need to be operated in assemble specific to IBM
Power architecture.

Warm regards,
Sriram.

Attachments:

0001-AIX-support-revert-the-changes-from-0b16bb8776bb8.v3.patchapplication/octet-stream; name=0001-AIX-support-revert-the-changes-from-0b16bb8776bb8.v3.patchDownload
From 0ecf87244dea6530abed0d6f5172397e24fda922 Mon Sep 17 00:00:00 2001
From: Sriram RK <sriram.rk@in.ibm.com>
Date: Mon, 20 May 2024 01:38:59 -0500
Subject: [PATCH] AIX support, revert the changes from 0b16bb8776bb8. Trim
 AIX/XLC changes to support gcc only.

Review comments from Heikki.
---
 Makefile                                      |   2 -
 configure                                     |  37 +++---
 configure.ac                                  |  28 ++---
 doc/src/sgml/dfunc.sgml                       |  19 +++
 doc/src/sgml/installation.sgml                | 118 +++++++++++++++++-
 doc/src/sgml/runtime.sgml                     |  23 ++++
 meson.build                                   |  57 +++++----
 src/Makefile.shlib                            |  29 +++++
 src/backend/Makefile                          |  20 +++
 src/backend/meson.build                       |  15 +++
 src/backend/port/aix/mkldexport.sh            |  61 +++++++++
 src/backend/utils/error/elog.c                |   2 +
 src/backend/utils/misc/ps_status.c            |   4 +-
 src/bin/pg_basebackup/t/010_pg_basebackup.pl  |   3 +-
 src/bin/pg_verifybackup/t/008_untar.pl        |   3 +-
 src/bin/pg_verifybackup/t/010_client_untar.pl |   3 +-
 src/include/c.h                               |   4 +-
 src/include/port/aix.h                        |   6 +
 src/include/storage/s_lock.h                  |  25 +++-
 src/interfaces/libpq/Makefile                 |   2 +-
 src/interfaces/libpq/meson.build              |   5 +-
 src/makefiles/Makefile.aix                    |  39 ++++++
 src/port/README                               |   2 +-
 src/port/strerror.c                           |   2 +
 src/template/aix                              |  14 +++
 src/test/regress/Makefile                     |   5 +
 src/test/regress/expected/sanity_check.out    |  29 +++++
 src/test/regress/expected/test_setup.out      |   4 +
 src/test/regress/regress.c                    |  40 ++++++
 src/test/regress/sql/sanity_check.sql         |  26 ++++
 src/test/regress/sql/test_setup.sql           |   5 +
 src/tools/gen_export.pl                       |  11 +-
 src/tools/pginclude/headerscheck              |   1 +
 33 files changed, 555 insertions(+), 89 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 create mode 100644 src/include/port/aix.h
 create mode 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index 8a2ec9396b..9bc1a4ec17 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/configure b/configure
index 89644f2249..f218b2e040 100755
--- a/configure
+++ b/configure
@@ -2988,6 +2988,7 @@ else
 # --with-template not given
 
 case $host_os in
+     aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -6848,7 +6849,6 @@ if test x"$pgac_cv_prog_CXX_cxxflags__fno_strict_aliasing" = x"yes"; then
   CXXFLAGS="${CXXFLAGS} -fno-strict-aliasing"
 fi
 
-
 fi
 
 # If the compiler knows how to hide symbols, add the switch needed for that to
@@ -12860,7 +12860,8 @@ fi
 
 fi
 
-# Note: We can test for libldap_r only after we know PTHREAD_LIBS
+# Note: We can test for libldap_r only after we know PTHREAD_LIBS;
+# also, on AIX, we may need to have openssl in LIBS for this step.
 if test "$with_ldap" = yes ; then
   _LIBS="$LIBS"
   if test "$PORTNAME" != "win32"; then
@@ -16951,28 +16952,18 @@ _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
+# We assume long's alignment is at least as strong as char, short, or int;
+# but we must check long long (if it is being used for int64) and double.
+# 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
-  as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
+MAX_ALIGNOF=$ac_cv_alignof_long
+if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+  MAX_ALIGNOF=$ac_cv_alignof_double
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $MAX_ALIGNOF -lt $ac_cv_alignof_long_long_int ; then
+  MAX_ALIGNOF="$ac_cv_alignof_long_long_int"
 fi
 
 cat >>confdefs.h <<_ACEOF
@@ -17090,7 +17081,7 @@ else
 /* end confdefs.h.  */
 
 /* This must match the corresponding code in c.h: */
-#if defined(__GNUC__) || defined(__SUNPRO_C)
+#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
 #elif defined(_MSC_VER)
 #define pg_attribute_aligned(a) __declspec(align(a))
diff --git a/configure.ac b/configure.ac
index c7322e292c..a059509cd9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ PGAC_ARG_REQ(with, template, [NAME], [override operating system template],
 # --with-template not given
 
 case $host_os in
+     aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -1385,7 +1386,8 @@ if test "$with_zstd" = yes ; then
   AC_CHECK_LIB(zstd, ZSTD_compress, [], [AC_MSG_ERROR([library 'zstd' is required for ZSTD support])])
 fi
 
-# Note: We can test for libldap_r only after we know PTHREAD_LIBS
+# Note: We can test for libldap_r only after we know PTHREAD_LIBS;
+# also, on AIX, we may need to have openssl in LIBS for this step.
 if test "$with_ldap" = yes ; then
   _LIBS="$LIBS"
   if test "$PORTNAME" != "win32"; then
@@ -1643,8 +1645,9 @@ PGAC_TYPE_LOCALE_T
 # spelling it understands, because it conflicts with
 # __declspec(restrict). Therefore we define pg_restrict to the
 # appropriate definition, which presumably won't conflict.
+#
 AC_C_RESTRICT
-if test "$ac_cv_c_restrict" = "no"; then
+if test "$ac_cv_c_restrict" = "no" ; then
   pg_restrict=""
 else
   pg_restrict="$ac_cv_c_restrict"
@@ -1996,22 +1999,11 @@ fi
 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 long's alignment is at least as strong as char, short, or int;
+# but we must check long long (if it is being used for int64) and double.
+# 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'])
diff --git a/doc/src/sgml/dfunc.sgml b/doc/src/sgml/dfunc.sgml
index b94aefcd0c..554f9fac4c 100644
--- a/doc/src/sgml/dfunc.sgml
+++ b/doc/src/sgml/dfunc.sgml
@@ -202,4 +202,23 @@ gcc -G -o foo.so foo.o
   server expects to find the shared library files.
  </para>
 
+<!--
+Under AIX, object files are compiled normally but building the shared
+library requires a couple of steps.  First, create the object file:
+.nf
+cc <other flags> -c foo.c
+.fi
+You must then create a symbol \*(lqexports\*(rq file for the object
+file:
+.nf
+mkldexport foo.o `pwd` &gt; foo.exp
+.fi
+Finally, you can create the shared library:
+.nf
+ld <other flags> -H512 -T512 -o foo.so -e _nostart \e
+   -bI:.../lib/postgres.exp -bE:foo.exp foo.o \e
+   -lm -lc 2>/dev/null
+.fi
+  -->
+
 </sect2>
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 1b32d5ca62..60e9a34a03 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -3401,7 +3401,7 @@ export MANPATH
   <para>
    <productname>PostgreSQL</productname> can be expected to work on current
    versions of these operating systems: Linux, Windows,
-   FreeBSD, OpenBSD, NetBSD, DragonFlyBSD, macOS, Solaris, and illumos.
+   FreeBSD, OpenBSD, NetBSD, DragonFlyBSD, macOS, AIX, Solaris, and illumos.
    Other Unix-like systems may also work but are not currently
    being tested.  In most cases, all CPU architectures supported by
    a given operating system will work.  Look in
@@ -3445,6 +3445,122 @@ export MANPATH
    installation issues.
   </para>
 
+  <sect2 id="installation-notes-aix">
+   <title>AIX</title>
+
+   <indexterm zone="installation-notes-aix">
+    <primary>AIX</primary>
+    <secondary>installation on</secondary>
+   </indexterm>
+
+   <para>
+    You can use GCC to build <productname>PostgreSQL</productname>
+    on <productname>AIX</productname>.
+   </para>
+
+   <para>
+    <productname>AIX</productname> versions before 7.1 are no longer
+    tested nor supported by the <productname>PostgreSQL</productname>
+    community.
+   </para>
+
+   <sect3 id="installation-notes-aix-mem-management">
+    <title>Memory Management</title>
+    <!-- https://archives.postgresql.org/message-id/603bgqmpl9.fsf@dba2.int.libertyrms.com -->
+
+    <para>
+     AIX can be somewhat peculiar with regards to the way it does
+     memory management.  You can have a server with many multiples of
+     gigabytes of RAM free, but still get out of memory or address
+     space errors when running applications.  One example
+     is loading of extensions failing with unusual errors.
+     For example, running as the owner of the PostgreSQL installation:
+<screen>
+=# CREATE EXTENSION plperl;
+ERROR:  could not load library "/opt/dbs/pgsql/lib/plperl.so": A memory address is not in the address space for the process.
+</screen>
+    Running as a non-owner in the group possessing the PostgreSQL
+    installation:
+<screen>
+=# CREATE EXTENSION plperl;
+ERROR:  could not load library "/opt/dbs/pgsql/lib/plperl.so": Bad address
+</screen>
+     Another example is out of memory errors in the PostgreSQL server
+     logs, with every memory allocation near or greater than 256 MB
+     failing.
+    </para>
+
+    <para>
+     The overall cause of all these problems is the default bittedness
+     and memory model used by the server process.  By default, all
+     binaries built on AIX are 32-bit.  This does not depend upon
+     hardware type or kernel in use.  These 32-bit processes are
+     limited to 4 GB of memory laid out in 256 MB segments using one
+     of a few models.  The default allows for less than 256 MB in the
+     heap as it shares a single segment with the stack.
+    </para>
+
+    <para>
+     In the case of the <literal>plperl</literal> example, above,
+     check your umask and the permissions of the binaries in your
+     PostgreSQL installation.  The binaries involved in that example
+     were 32-bit and installed as mode 750 instead of 755.  Due to the
+     permissions being set in this fashion, only the owner or a member
+     of the possessing group can load the library.  Since it isn't
+     world-readable, the loader places the object into the process'
+     heap instead of the shared library segments where it would
+     otherwise be placed.
+    </para>
+
+    <para>
+     The <quote>ideal</quote> solution for this is to use a 64-bit
+     build of PostgreSQL, but that is not always practical, because
+     systems with 32-bit processors can build, but not run, 64-bit
+     binaries.
+    </para>
+
+    <para>
+     If a 32-bit binary is desired, set <symbol>LDR_CNTRL</symbol> to
+     <literal>MAXDATA=0x<replaceable>n</replaceable>0000000</literal>,
+     where 1 &lt;= n &lt;= 8, before starting the PostgreSQL server,
+     and try different values and <filename>postgresql.conf</filename>
+     settings to find a configuration that works satisfactorily.  This
+     use of <symbol>LDR_CNTRL</symbol> tells AIX that you want the
+     server to have <symbol>MAXDATA</symbol> bytes set aside for the
+     heap, allocated in 256 MB segments.  When you find a workable
+     configuration,
+     <command>ldedit</command> can be used to modify the binaries so
+     that they default to using the desired heap size.  PostgreSQL can
+     also be rebuilt, passing <literal>configure
+     LDFLAGS="-Wl,-bmaxdata:0x<replaceable>n</replaceable>0000000"</literal>
+     to achieve the same effect.
+    </para>
+
+    <para>
+     For a 64-bit build, set <envar>OBJECT_MODE</envar> to 64 and
+     pass <literal>CC="gcc -maix64"</literal>
+     and <literal>LDFLAGS="-Wl,-bbigtoc"</literal>
+     to <command>configure</command>. 
+     If you omit the export of
+    <envar>OBJECT_MODE</envar>, your build may fail with linker errors.  When
+    <envar>OBJECT_MODE</envar> is set, it tells AIX's build utilities
+    such as <command>ar</command>, <command>as</command>, and <command>ld</command> what
+    type of objects to default to handling.
+    </para>
+
+    <para>
+     By default, overcommit of paging space can happen.  While we have
+     not seen this occur, AIX will kill processes when it runs out of
+     memory and the overcommit is accessed.  The closest to this that
+     we have seen is fork failing because the system decided that
+     there was not enough memory for another process.  Like many other
+     parts of AIX, the paging space allocation method and
+     out-of-memory kill is configurable on a system- or process-wide
+     basis if this becomes a problem.
+    </para>
+   </sect3>
+  </sect2>
+
   <sect2 id="installation-notes-cygwin">
    <title>Cygwin</title>
 
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 6047b8171d..64753d9c01 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -891,6 +891,29 @@ psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: No such
 
 
     <variablelist>
+     <varlistentry>
+      <term><systemitem class="osname">AIX</systemitem>
+      <indexterm><primary>AIX</primary><secondary>IPC configuration</secondary></indexterm>
+      </term>
+      <listitem>
+       <para>
+        It should not be necessary to do
+        any special configuration for such parameters as
+        <varname>SHMMAX</varname>, as it appears this is configured to
+        allow all memory to be used as shared memory.  That is the
+        sort of configuration commonly used for other databases such
+        as <application>DB/2</application>.</para>
+
+       <para> It might, however, be necessary to modify the global
+       <command>ulimit</command> information in
+       <filename>/etc/security/limits</filename>, as the default hard
+       limits for file sizes (<varname>fsize</varname>) and numbers of
+       files (<varname>nofiles</varname>) might be too low.
+       </para>
+      </listitem>
+     </varlistentry>
+
+
      <varlistentry>
       <term><systemitem class="osname">FreeBSD</systemitem>
       <indexterm><primary>FreeBSD</primary><secondary>IPC configuration</secondary></indexterm>
diff --git a/meson.build b/meson.build
index 1c0579d5a6..f1ac154cdc 100644
--- a/meson.build
+++ b/meson.build
@@ -196,7 +196,26 @@ endif
 # that purpose.
 portname = host_system
 
-if host_system == 'cygwin'
+if host_system == 'aix'
+  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'
+
+  # M:SRE sets a flag indicating that an object is a shared library. Seems to
+  # work in some circumstances without, but required in others.
+  ldflags_sl += '-Wl,-bM:SRE'
+  ldflags_be += '-Wl,-brtllib'
+
+  # Native memset() is faster, tested on:
+  # - AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
+  # - AIX 5.3 ML3, gcc 4.0.1
+  memset_loop_limit = 0
+
+elif host_system == 'cygwin'
   sema_kind = 'unnamed_posix'
   cppflags += '-D_GNU_SOURCE'
   dlsuffix = '.dll'
@@ -1490,11 +1509,11 @@ sizeof_long = cc.sizeof('long', args: test_c_args)
 cdata.set('SIZEOF_LONG', sizeof_long)
 if sizeof_long == 8
   cdata.set('HAVE_LONG_INT_64', 1)
-  pg_int64_type = 'long int'
+  cdata.set('PG_INT64_TYPE', 'long int')
   cdata.set_quoted('INT64_MODIFIER', 'l')
 elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
   cdata.set('HAVE_LONG_LONG_INT_64', 1)
-  pg_int64_type = 'long long int'
+  cdata.set('PG_INT64_TYPE', 'long long int')
   cdata.set_quoted('INT64_MODIFIER', 'll')
 else
   error('do not know how to get a 64bit int')
@@ -1508,31 +1527,15 @@ endif
 # Determine memory alignment requirements for the basic C data types.
 
 alignof_types = ['short', 'int', 'long', 'double']
+maxalign = 0
 foreach t : alignof_types
   align = cc.alignment(t, args: test_c_args)
+  if maxalign < align
+    maxalign = align
+  endif
   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'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(pg_int64_type, args: test_c_args) > alignof_double
-  error('alignment of int64 is greater than the alignment of double')
-endif
-cdata.set('MAXIMUM_ALIGNOF', alignof_double)
+cdata.set('MAXIMUM_ALIGNOF', maxalign)
 
 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
@@ -1581,7 +1584,7 @@ if cc.links('''
   if not meson.is_cross_build()
     r = cc.run('''
     /* This must match the corresponding code in c.h: */
-    #if defined(__GNUC__) || defined(__SUNPRO_C)
+    #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
     #define pg_attribute_aligned(a) __attribute__((aligned(a)))
     #elif defined(_MSC_VER)
     #define pg_attribute_aligned(a) __declspec(align(a))
@@ -2476,6 +2479,10 @@ endif
 # conflict.
 #
 # We assume C99 support, so we don't need to make this conditional.
+#
+# XXX: Historically we allowed platforms to disable restrict in template
+# files, but that was only added for AIX when building with XLC, which we
+# don't support yet.
 cdata.set('pg_restrict', '__restrict')
 
 
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index fa81f6ffdd..8ca51ca03f 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,20 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +268,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps shared libraries inside a static library, can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +289,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +401,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +419,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 6700aec039..954b14962f 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -62,12 +62,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -94,6 +96,24 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
diff --git a/src/backend/meson.build b/src/backend/meson.build
index 436c04af08..8767aaba67 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -91,6 +91,21 @@ if cc.get_id() == 'msvc'
   # be restricted to b_pch=true.
   backend_link_with += postgres_lib
 
+elif 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
 
 backend_input = []
diff --git a/src/backend/port/aix/mkldexport.sh b/src/backend/port/aix/mkldexport.sh
new file mode 100755
index 0000000000..adf3793e86
--- /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/utils/error/elog.c b/src/backend/utils/error/elog.c
index d91a85cb2d..7b51e94f4a 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -908,7 +908,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/backend/utils/misc/ps_status.c b/src/backend/utils/misc/ps_status.c
index 9da6377402..532eac31b4 100644
--- a/src/backend/utils/misc/ps_status.c
+++ b/src/backend/utils/misc/ps_status.c
@@ -50,7 +50,7 @@ bool		update_process_title = DEFAULT_UPDATE_PROCESS_TITLE;
 #define PS_USE_SETPROCTITLE_FAST
 #elif defined(HAVE_SETPROCTITLE)
 #define PS_USE_SETPROCTITLE
-#elif defined(__linux__) || defined(__sun) || defined(__darwin__)
+#elif defined(__linux__) || defined(_AIX) || defined(__sun) || defined(__darwin__)
 #define PS_USE_CLOBBER_ARGV
 #elif defined(WIN32)
 #define PS_USE_WIN32
@@ -60,7 +60,7 @@ bool		update_process_title = DEFAULT_UPDATE_PROCESS_TITLE;
 
 
 /* Different systems want the buffer padded differently */
-#if defined(__linux__) || defined(__darwin__)
+#if defined(_AIX) || defined(__linux__) || defined(__darwin__)
 #define PS_PADDING '\0'
 #else
 #define PS_PADDING ' '
diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
index 2d4b75a6fe..ce936959c1 100644
--- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
+++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
@@ -401,7 +401,8 @@ SKIP:
 {
 	my $tar = $ENV{TAR};
 	# don't check for a working tar here, to accommodate various odd
-	# cases. If tar doesn't work the init_from_backup below will fail.
+	# cases such as AIX. If tar doesn't work the init_from_backup below
+	# will fail.
 	skip "no tar program available", 1
 	  if (!defined $tar || $tar eq '');
 
diff --git a/src/bin/pg_verifybackup/t/008_untar.pl b/src/bin/pg_verifybackup/t/008_untar.pl
index 7a09f3b75b..30d9f3f7f0 100644
--- a/src/bin/pg_verifybackup/t/008_untar.pl
+++ b/src/bin/pg_verifybackup/t/008_untar.pl
@@ -104,7 +104,8 @@ for my $tc (@test_configuration)
 		{
 			my $tar = $ENV{TAR};
 			# don't check for a working tar here, to accommodate various odd
-			# cases. If tar doesn't work the init_from_backup below will fail.
+			# cases such as AIX. If tar doesn't work the init_from_backup below
+			# will fail.
 			skip "no tar program available", 1
 			  if (!defined $tar || $tar eq '');
 
diff --git a/src/bin/pg_verifybackup/t/010_client_untar.pl b/src/bin/pg_verifybackup/t/010_client_untar.pl
index 8c076d46de..45010d79ac 100644
--- a/src/bin/pg_verifybackup/t/010_client_untar.pl
+++ b/src/bin/pg_verifybackup/t/010_client_untar.pl
@@ -134,7 +134,8 @@ for my $tc (@test_configuration)
 		{
 			my $tar = $ENV{TAR};
 			# don't check for a working tar here, to accommodate various odd
-			# cases. If tar doesn't work the init_from_backup below will fail.
+			# cases such as AIX. If tar doesn't work the init_from_backup below
+			# will fail.
 			skip "no tar program available", 1
 			  if (!defined $tar || $tar eq '');
 
diff --git a/src/include/c.h b/src/include/c.h
index dc1841346c..641cd9bdf1 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -182,7 +182,7 @@
 #define PG_USED_FOR_ASSERTS_ONLY pg_attribute_unused()
 #endif
 
-/* GCC supports format attributes */
+/* GCC support format attributes */
 #if defined(__GNUC__)
 #define pg_attribute_format_arg(a) __attribute__((format_arg(a)))
 #define pg_attribute_printf(f,a) __attribute__((format(PG_PRINTF_ATTRIBUTE, f, a)))
@@ -192,7 +192,7 @@
 #endif
 
 /* GCC and Sunpro support aligned, packed and noreturn */
-#if defined(__GNUC__) || defined(__SUNPRO_C)
+#if defined(__GNUC__) || defined(__SUNPRO_C) 
 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
 #define pg_attribute_noreturn() __attribute__((noreturn))
 #define pg_attribute_packed() __attribute__((packed))
diff --git a/src/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 0000000000..1c2d166791
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,6 @@
+/*
+ * src/include/port/aix.h
+ */
+#define CLASS_CONFLICT
+#define DISABLE_XOPEN_NLS
+
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 29ac6cdcd9..2f6eb5df2a 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -424,17 +424,15 @@ tas(volatile slock_t *lock)
 	__asm__ __volatile__(
 "	lwarx   %0,0,%3,1	\n"
 "	cmpwi   %0,0		\n"
-"	bne     1f			\n"
+"	bne     $+16		\n"		/* branch to li %1,1 */
 "	addi    %0,%0,1		\n"
 "	stwcx.  %0,0,%3		\n"
-"	beq     2f			\n"
-"1: \n"
+"	beq     $+12		\n"		/* branch to lwsync */
 "	li      %1,1		\n"
-"	b       3f			\n"
-"2: \n"
+"	b       $+12		\n"		/* branch to end of asm sequence */
 "	lwsync				\n"
 "	li      %1,0		\n"
-"3: \n"
+
 :	"=&b"(_t), "=r"(_res), "+m"(*lock)
 :	"r"(lock)
 :	"memory", "cc");
@@ -662,6 +660,21 @@ tas(volatile slock_t *lock)
 
 #if !defined(HAS_TEST_AND_SET)	/* We didn't trigger above, let's try here */
 
+#if defined(_AIX)	/* AIX */
+/*
+ * AIX (POWER)
+ */
+#define HAS_TEST_AND_SET
+
+#include <sys/atomic_op.h>
+
+typedef int slock_t;
+
+#define TAS(lock)			_check_lock((slock_t *) (lock), 0, 1)
+#define S_UNLOCK(lock)		_clear_lock((slock_t *) (lock), 0)
+#endif	 /* _AIX */
+
+
 /* These are in sunstudio_(sparc|x86).s */
 
 #if defined(__SUNPRO_C) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index b36a765764..154429d4d1 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -114,7 +114,7 @@ backend_src = $(top_srcdir)/src/backend
 # coding rule.
 libpq-refs-stamp: $(shlib)
 ifneq ($(enable_coverage), yes)
-ifeq (,$(filter solaris,$(PORTNAME)))
+ifeq (,$(filter aix solaris,$(PORTNAME)))
 	@if nm -A -u $< 2>/dev/null | grep -v -e __cxa_atexit -e __tsan_func_exit | grep exit; then \
 		echo 'libpq must not be calling any function which invokes exit'; exit 1; \
 	fi
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index ed2a4048d1..7e2017daf0 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -54,8 +54,9 @@ libpq_c_args = ['-DSO_MAJOR_VERSION=5']
 #    libpq_st, and {pgport,common}_shlib for libpq_sh
 #
 # We could try to avoid building the source files twice, but it probably adds
-# more complexity than its worth (reusing object files requires also linking
-# to the library on windows or breaks precompiled headers).
+# more complexity than its worth (AIX doesn't support link_whole yet, reusing
+# object files requires also linking to the library on windows or breaks
+# precompiled headers).
 libpq_st = static_library('libpq',
   libpq_sources,
   include_directories: [libpq_inc],
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 0000000000..dd16a7a037
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,39 @@
+# MAKE_EXPORTS is required for svr4 loaders that want a file of
+# symbol names to tell them what to export/import.
+MAKE_EXPORTS= true
+
+# -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
+
+rpath = -Wl,-blibpath:'$(rpathdir)$(libpath)'
+
+LDFLAGS_SL += -Wl,-bnoentry -Wl,-H512 -Wl,-bM:SRE
+
+# 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/port/README b/src/port/README
index ed5c54a72f..97f18a6233 100644
--- a/src/port/README
+++ b/src/port/README
@@ -28,5 +28,5 @@ applications.
 from libpgport are linked first.  This avoids having applications
 dependent on symbols that are _used_ by libpq, but not intended to be
 exported by libpq.  libpq's libpgport usage changes over time, so such a
-dependency is a problem.  Windows, Linux, and macOS use an export
+dependency is a problem.  Windows, Linux, AIX, and macOS use an export
 list to control the symbols exported by libpq.
diff --git a/src/port/strerror.c b/src/port/strerror.c
index 4918ba821c..1070a49802 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,8 +214,10 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
 			return "ENOTEMPTY";
+#endif
 		case ENOTSOCK:
 			return "ENOTSOCK";
 #ifdef ENOTSUP
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 0000000000..0a788676c0
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,14 @@
+# src/template/aix
+
+  # Due to a compiler bug, see 20171013023536.GA492146@rfd.leadboat.com for details,
+  # force restrict not to be used when compiling with xlc.
+#  FORCE_DISABLE_RESTRICT=yes
+#fi
+
+# Extra CFLAGS for code that will go into a shared library
+CFLAGS_SL=""
+
+# Native memset() is faster, tested on:
+# 	AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
+# 	AIX 5.3 ML3, gcc 4.0.1
+MEMSET_LOOP_LIMIT=0
diff --git a/src/test/regress/Makefile b/src/test/regress/Makefile
index 6409a485e8..7c665ff892 100644
--- a/src/test/regress/Makefile
+++ b/src/test/regress/Makefile
@@ -7,6 +7,11 @@
 # GNU make uses a make file named "GNUmakefile" in preference to "Makefile"
 # if it exists.  Postgres is shipped with a "GNUmakefile".
 
+
+# AIX make defaults to building *every* target of the first rule.  Start with
+# a single-target, empty rule to make the other targets non-default.
+all:
+
 all install clean check installcheck:
 	@echo "You must use GNU make to use Postgres.  It may be installed"
 	@echo "on your system with the name 'gmake'."
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 8370c1561c..c5c675b750 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -25,3 +25,32 @@ SELECT relname, relkind
 ---------+---------
 (0 rows)
 
+--
+-- When ALIGNOF_DOUBLE==4 (e.g. AIX), the C ABI may impose 8-byte alignment on
+-- some of the C types that correspond to TYPALIGN_DOUBLE SQL types.  To ensure
+-- catalog C struct layout matches catalog tuple layout, arrange for the tuple
+-- offset of each fixed-width, attalign='d' catalog column to be divisible by 8
+-- unconditionally.  Keep such columns before the first NameData column of the
+-- catalog, since packagers can override NAMEDATALEN to an odd number.
+--
+WITH check_columns AS (
+ SELECT relname, attname,
+  array(
+   SELECT t.oid
+    FROM pg_type t JOIN pg_attribute pa ON t.oid = pa.atttypid
+    WHERE pa.attrelid = a.attrelid AND
+          pa.attnum > 0 AND pa.attnum < a.attnum
+    ORDER BY pa.attnum) AS coltypes
+ FROM pg_attribute a JOIN pg_class c ON c.oid = attrelid
+  JOIN pg_namespace n ON c.relnamespace = n.oid
+ WHERE attalign = 'd' AND relkind = 'r' AND
+  attnotnull AND attlen <> -1 AND n.nspname = 'pg_catalog'
+)
+SELECT relname, attname, coltypes, get_columns_length(coltypes)
+ FROM check_columns
+ WHERE get_columns_length(coltypes) % 8 != 0 OR
+       'name'::regtype::oid = ANY(coltypes);
+ relname | attname | coltypes | get_columns_length 
+---------+---------+----------+--------------------
+(0 rows)
+
diff --git a/src/test/regress/expected/test_setup.out b/src/test/regress/expected/test_setup.out
index 3d0eeec996..5d9e6bf12b 100644
--- a/src/test/regress/expected/test_setup.out
+++ b/src/test/regress/expected/test_setup.out
@@ -209,6 +209,10 @@ CREATE FUNCTION ttdummy ()
     RETURNS trigger
     AS :'regresslib'
     LANGUAGE C;
+CREATE FUNCTION get_columns_length(oid[])
+    RETURNS int
+    AS :'regresslib'
+    LANGUAGE C STRICT STABLE PARALLEL SAFE;
 -- Use hand-rolled hash functions and operator classes to get predictable
 -- result on different machines.  The hash function for int4 simply returns
 -- the sum of the values passed to it and the one for text returns the length
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index deffaea578..cc633864d7 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -1221,3 +1221,43 @@ binary_coercible(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(IsBinaryCoercible(srctype, targettype));
 }
+
+/*
+ * Return the length of the portion of a tuple consisting of the given array
+ * of data types.  The input data types must be fixed-length data types.
+ */
+PG_FUNCTION_INFO_V1(get_columns_length);
+Datum
+get_columns_length(PG_FUNCTION_ARGS)
+{
+	ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
+	Oid		   *type_oids;
+	int			ntypes;
+	int			column_offset = 0;
+
+	if (ARR_HASNULL(ta) && array_contains_nulls(ta))
+		elog(ERROR, "argument must not contain nulls");
+
+	if (ARR_NDIM(ta) > 1)
+		elog(ERROR, "argument must be empty or one-dimensional array");
+
+	type_oids = (Oid *) ARR_DATA_PTR(ta);
+	ntypes = ArrayGetNItems(ARR_NDIM(ta), ARR_DIMS(ta));
+	for (int i = 0; i < ntypes; i++)
+	{
+		Oid			typeoid = type_oids[i];
+		int16		typlen;
+		bool		typbyval;
+		char		typalign;
+
+		get_typlenbyvalalign(typeoid, &typlen, &typbyval, &typalign);
+
+		/* the data type must be fixed-length */
+		if (typlen < 0)
+			elog(ERROR, "type %u is not fixed-length data type", typeoid);
+
+		column_offset = att_align_nominal(column_offset + typlen, typalign);
+	}
+
+	PG_RETURN_INT32(column_offset);
+}
diff --git a/src/test/regress/sql/sanity_check.sql b/src/test/regress/sql/sanity_check.sql
index 162e5324b5..7f338d191c 100644
--- a/src/test/regress/sql/sanity_check.sql
+++ b/src/test/regress/sql/sanity_check.sql
@@ -19,3 +19,29 @@ SELECT relname, relkind
   FROM pg_class
  WHERE relkind IN ('v', 'c', 'f', 'p', 'I')
        AND relfilenode <> 0;
+
+--
+-- When ALIGNOF_DOUBLE==4 (e.g. AIX), the C ABI may impose 8-byte alignment on
+-- some of the C types that correspond to TYPALIGN_DOUBLE SQL types.  To ensure
+-- catalog C struct layout matches catalog tuple layout, arrange for the tuple
+-- offset of each fixed-width, attalign='d' catalog column to be divisible by 8
+-- unconditionally.  Keep such columns before the first NameData column of the
+-- catalog, since packagers can override NAMEDATALEN to an odd number.
+--
+WITH check_columns AS (
+ SELECT relname, attname,
+  array(
+   SELECT t.oid
+    FROM pg_type t JOIN pg_attribute pa ON t.oid = pa.atttypid
+    WHERE pa.attrelid = a.attrelid AND
+          pa.attnum > 0 AND pa.attnum < a.attnum
+    ORDER BY pa.attnum) AS coltypes
+ FROM pg_attribute a JOIN pg_class c ON c.oid = attrelid
+  JOIN pg_namespace n ON c.relnamespace = n.oid
+ WHERE attalign = 'd' AND relkind = 'r' AND
+  attnotnull AND attlen <> -1 AND n.nspname = 'pg_catalog'
+)
+SELECT relname, attname, coltypes, get_columns_length(coltypes)
+ FROM check_columns
+ WHERE get_columns_length(coltypes) % 8 != 0 OR
+       'name'::regtype::oid = ANY(coltypes);
diff --git a/src/test/regress/sql/test_setup.sql b/src/test/regress/sql/test_setup.sql
index 06b0e2121f..1b2d434683 100644
--- a/src/test/regress/sql/test_setup.sql
+++ b/src/test/regress/sql/test_setup.sql
@@ -257,6 +257,11 @@ CREATE FUNCTION ttdummy ()
     AS :'regresslib'
     LANGUAGE C;
 
+CREATE FUNCTION get_columns_length(oid[])
+    RETURNS int
+    AS :'regresslib'
+    LANGUAGE C STRICT STABLE PARALLEL SAFE;
+
 -- Use hand-rolled hash functions and operator classes to get predictable
 -- result on different machines.  The hash function for int4 simply returns
 -- the sum of the values passed to it and the one for text returns the length
diff --git a/src/tools/gen_export.pl b/src/tools/gen_export.pl
index d9fdaaaf6d..888c8a197a 100644
--- a/src/tools/gen_export.pl
+++ b/src/tools/gen_export.pl
@@ -16,11 +16,12 @@ GetOptions(
 	'input:s' => \$input,
 	'output:s' => \$output) or die "wrong arguments";
 
-if (not(   $format eq 'darwin'
+if (not(   $format eq 'aix'
+		or $format eq 'darwin'
 		or $format eq 'gnu'
 		or $format eq 'win'))
 {
-	die "$0: $format is not yet handled (only darwin, gnu, win are)\n";
+	die "$0: $format is not yet handled (only aix, darwin, gnu, win are)\n";
 }
 
 open(my $input_handle, '<', $input)
@@ -55,7 +56,11 @@ while (<$input_handle>)
 	}
 	elsif (/^(\S+)\s+(\S+)/)
 	{
-		if ($format eq 'darwin')
+		if ($format eq 'aix')
+		{
+			print $output_handle "$1\n";
+		}
+		elsif ($format eq 'darwin')
 		{
 			print $output_handle "_$1\n";
 		}
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 4a157d0a5f..cfd8c6896c 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -85,6 +85,7 @@ do
 
 	# These files are platform-specific, and c.h will include the
 	# one that's relevant for our current platform anyway.
+	test "$f" = src/include/port/aix.h && continue
 	test "$f" = src/include/port/cygwin.h && continue
 	test "$f" = src/include/port/darwin.h && continue
 	test "$f" = src/include/port/freebsd.h && continue
-- 
2.41.0

#59Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Srirama Kucherlapati (#58)
Re: AIX support

On 14/08/2024 18:22, Srirama Kucherlapati wrote:

Hi Heikki,

I have attached the merged patch with all the changes, the earlier patch was

just only the changes specific to older review comments.

    > I'm sorry, I don't understand what you're saying here. Do you
mean that
    > we don't need to do anything here, and the code we have in
s_lock.h in
    > 'master' now will work fine on AIX? Or do we need to (re-)do some
    > changes to support AIX again? If we only support GCC, can we use the
    > __sync_lock_test_and_set() builtin instead?

Here we need these changes for ppc. These changes are not for
enabling the AIX support, but this is implementing “Enhanced PowerPC
Architecture”. This routine is more of compare_and_increment, which
is different from GCC __sync_lock_test_and_set(). Also I tried to
write a sample function to check the assemble generated by
__sync_lock_test_and_set(), which turned out to be different set of
assemble code.

I still don't understand. We have Linux powerpc systems running happily
in the buildfarm. They are happy with the current spinlock
implementation. Why is this needed? What happens without it?

How is this different from __sync_lock_test_and_set()? Is the
__sync_lock_test_and_set() on that platform broken, less efficient, or
just different but equally good?

    > > +#define TAS(lock)                      _check_lock((slock_t *)
(lock),
    > > 0, 1)
    > >
    >>  +#define S_UNLOCK(lock)         _clear_lock((slock_t *) (lock), 0)
    >>
    > > The above changes are specific to AIX kernel and it operates on
fixed
    > > kernel memory. This is more like a compare_and_swap
functionality with
    > > sync capability. For all the assemble code I think it would be
better to
    > > use the IBM Power specific asm code to gain additional performance.

    > You mean we don't need the above? Ok, good.

I mean this part of the code is needed as this is specific to AIX
kernel memory operation which is different from
__sync_lock_test_and_set().

How is it different from __sync_lock_test_and_set()? Why is it needed?
What is AIX kernel memory operation?

I would like to mention that the changes made in
src/include/storage/s_lock.h

are pretty much required and need to be operated in assemble specific to IBM
Power architecture.

Note that your patch both modifies the existing powerpc implementation,
and introduces a new AIX-specific one. They cannot *both* be required,
because only one of them will ever be compiled on a given platform.
Which is it? Or are you trying to make this work on multiple different
CPUs on AIX, so that different implementation gets chosen on different CPUs?

Is the mkldexport stuff still needed on modern AIX? Or was it specific
to XLC and never needed on GCC? How do other products do that?

On a general note: it's your responsibility to explain all the changes
in a way that others will understand and can verify. It is especially
important for something critical and platform-specific like spinlocks,
because others don't have easy access to the hardware to test these
things independently. I also want to remind you that from the Postgres
community point of view, you are introducing support for a new platform,
AIX, not merely resurrecting the old stuff. Every change needs to be
justified anew.

--
Heikki Linnakangas
Neon (https://neon.tech)

#60Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Heikki Linnakangas (#59)
3 attachment(s)
RE: AIX support

Hi Heikki and Team,

Thanks for your comments.

Here are some more details

I still don't understand. We have Linux powerpc systems
running happily in the buildfarm. They are happy with the
current spinlock implementation. Why is this needed?
What happens without it?

Not sure, by the time the below commits were made if there was a consideration
to use the gcc routines. My guess is that by using this PPC assembler code
would make the code independent of the compilers. Even the Linux ppc would use the
same asm. Since gcc is available on AIX, I have replaced the asm changes with
the gcc routine __sync_lock_test_and_set() to set the lock.

We have the gcc(package) build on the AIX platform and as part of the testsuite
there are no issues wrt this routine. We tried to test with the sample test
program extracted from gcc testsuite. Also we discussed the same with our
compiler teams internally and they see no issues using this routine.

<attached sample test> gcc-12.4.0/libgomp/testsuite/libgomp.c/sections-1.c

--------

+#define TAS(lock) _check_lock((slock_t *) (lock), 0, 1)

+#define S_UNLOCK(lock) _clear_lock((slock_t *) (lock), 0)

How is it different from __sync_lock_test_and_set()? Why is it needed?
What is AIX kernel memory operation?

More Info: _check_lock routine description
https://www.ibm.com/docs/en/aix/7.1?topic=c-check-lock-subroutine
The _check_lock subroutine performs an atomic (uninterruptible) sequence of
operations. The compare_and_swap subroutine is similar, but does not issue
synchronization instructions and therefore is inappropriate for updating lock
words.

This change need not be replaced with gcc routine as, these changes will be
compiled for the non-gcc platforms only. This piece of code would never be
compiled, as we are using only gcc to build.

I tried to replace the AIX asm (under__ppc__ macro) with the gcc routine
__sync_lock_test_and_set(), and all the buildfarm tests passed. Attached patch
and the buildfarm output. Please let me know your feedback.

----

On a general note: it's your responsibility to explain all the changes
in a way that others will understand and can verify. It is especially
important for something critical and platform-specific like spinlocks,
because others don't have easy access to the hardware to test these
things independently. I also want to remind you that from the Postgres
community point of view, you are introducing support for a new platform,
AIX, not merely resurrecting the old stuff. Every change needs to be
justified anew.

I do agree with you. To have a better understand on the previous changes,
I was going through the history of the file(s_lock.h) and see that multiple
changes that were made wrt the tas()routine specific to ppc/AIX. Below are
the commit levels.
I would kindly request, Tom Lane, to provide some insights on these changes.

commit e3b06a871b63b90d4a08560ce184bb33324410b8
commit 50938576d482cd36e52a60b5bb1b56026e63962a << added tas() for AIX
commit 7233aae50bea503369b0a4ef9a3b6a3864c96812
commit ceb4f5ea9c2c6c2bd44d4799ff4a62c40a038894 << added tas() for PPC
commit f9ba0a7fe56398e89fe349476d9e437c3197ea28
commit eb5e4c58d137c9258eff5e41b09cb5fe4ed6d64c
commit cd35d601b859d3a56632696b8d5293cbe547764b
commit 109867748259d286dd01fce17d5f895ce59c68d5
commit 5cfa8dd3007d7e953c6a03b0fa2215d97c581b0c
commit 631beeac3598a73dee2c2afa38fa2e734148031b
commit bc2a050d40976441cdb963ad829316c23e8df0aa
commit c41a1215f04912108068b909569551f42059db29
commit 50938576d482cd36e52a60b5bb1b56026e63962a

Please let me know if would like to try on the hardware, we have recently
setup a node in the OSU lab to try out.

Thanks,
Sriram.

Attachments:

0001-AIX-support-revert-the-changes-from-0b16bb8776bb8.v4.patchapplication/octet-stream; name=0001-AIX-support-revert-the-changes-from-0b16bb8776bb8.v4.patchDownload
From f162e7d01f34957c906f96cde865937e05f15038 Mon Sep 17 00:00:00 2001
From: Sriram RK <sriram.rk@in.ibm.com>
Date: Mon, 20 May 2024 01:38:59 -0500
Subject: [PATCH 1/1] AIX support, revert the changes from 0b16bb8776bb8. Trim
 AIX/XLC changes to support gcc only.

 - Review comments from Heikki.
 - Replace tas() AIX asm with gcc __sync_lock_test_and_set().
 - Fix tas() for powerPC.
---
 Makefile                                      |   2 -
 configure                                     |  37 +++---
 configure.ac                                  |  28 ++---
 doc/src/sgml/dfunc.sgml                       |  19 +++
 doc/src/sgml/installation.sgml                | 118 +++++++++++++++++-
 doc/src/sgml/runtime.sgml                     |  23 ++++
 meson.build                                   |  57 +++++----
 src/Makefile.shlib                            |  29 +++++
 src/backend/Makefile                          |  20 +++
 src/backend/meson.build                       |  15 +++
 src/backend/port/aix/mkldexport.sh            |  61 +++++++++
 src/backend/utils/error/elog.c                |   2 +
 src/backend/utils/misc/ps_status.c            |   4 +-
 src/bin/pg_basebackup/t/010_pg_basebackup.pl  |   3 +-
 src/bin/pg_verifybackup/t/008_untar.pl        |   3 +-
 src/bin/pg_verifybackup/t/010_client_untar.pl |   3 +-
 src/include/c.h                               |   4 +-
 src/include/port/aix.h                        |   6 +
 src/include/storage/s_lock.h                  |  62 +++------
 src/interfaces/libpq/Makefile                 |   2 +-
 src/interfaces/libpq/meson.build              |   5 +-
 src/makefiles/Makefile.aix                    |  39 ++++++
 src/port/README                               |   2 +-
 src/port/strerror.c                           |   2 +
 src/template/aix                              |  14 +++
 src/test/regress/Makefile                     |   5 +
 src/test/regress/expected/sanity_check.out    |  29 +++++
 src/test/regress/expected/test_setup.out      |   4 +
 src/test/regress/regress.c                    |  40 ++++++
 src/test/regress/sql/sanity_check.sql         |  26 ++++
 src/test/regress/sql/test_setup.sql           |   5 +
 src/tools/gen_export.pl                       |  11 +-
 src/tools/pginclude/headerscheck              |   1 +
 33 files changed, 554 insertions(+), 127 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 create mode 100644 src/include/port/aix.h
 create mode 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index 8a2ec9396b..9bc1a4ec17 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/configure b/configure
index 89644f2249..f218b2e040 100755
--- a/configure
+++ b/configure
@@ -2988,6 +2988,7 @@ else
 # --with-template not given
 
 case $host_os in
+     aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -6848,7 +6849,6 @@ if test x"$pgac_cv_prog_CXX_cxxflags__fno_strict_aliasing" = x"yes"; then
   CXXFLAGS="${CXXFLAGS} -fno-strict-aliasing"
 fi
 
-
 fi
 
 # If the compiler knows how to hide symbols, add the switch needed for that to
@@ -12860,7 +12860,8 @@ fi
 
 fi
 
-# Note: We can test for libldap_r only after we know PTHREAD_LIBS
+# Note: We can test for libldap_r only after we know PTHREAD_LIBS;
+# also, on AIX, we may need to have openssl in LIBS for this step.
 if test "$with_ldap" = yes ; then
   _LIBS="$LIBS"
   if test "$PORTNAME" != "win32"; then
@@ -16951,28 +16952,18 @@ _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
+# We assume long's alignment is at least as strong as char, short, or int;
+# but we must check long long (if it is being used for int64) and double.
+# 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
-  as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
+MAX_ALIGNOF=$ac_cv_alignof_long
+if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+  MAX_ALIGNOF=$ac_cv_alignof_double
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $MAX_ALIGNOF -lt $ac_cv_alignof_long_long_int ; then
+  MAX_ALIGNOF="$ac_cv_alignof_long_long_int"
 fi
 
 cat >>confdefs.h <<_ACEOF
@@ -17090,7 +17081,7 @@ else
 /* end confdefs.h.  */
 
 /* This must match the corresponding code in c.h: */
-#if defined(__GNUC__) || defined(__SUNPRO_C)
+#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
 #elif defined(_MSC_VER)
 #define pg_attribute_aligned(a) __declspec(align(a))
diff --git a/configure.ac b/configure.ac
index c7322e292c..a059509cd9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ PGAC_ARG_REQ(with, template, [NAME], [override operating system template],
 # --with-template not given
 
 case $host_os in
+     aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -1385,7 +1386,8 @@ if test "$with_zstd" = yes ; then
   AC_CHECK_LIB(zstd, ZSTD_compress, [], [AC_MSG_ERROR([library 'zstd' is required for ZSTD support])])
 fi
 
-# Note: We can test for libldap_r only after we know PTHREAD_LIBS
+# Note: We can test for libldap_r only after we know PTHREAD_LIBS;
+# also, on AIX, we may need to have openssl in LIBS for this step.
 if test "$with_ldap" = yes ; then
   _LIBS="$LIBS"
   if test "$PORTNAME" != "win32"; then
@@ -1643,8 +1645,9 @@ PGAC_TYPE_LOCALE_T
 # spelling it understands, because it conflicts with
 # __declspec(restrict). Therefore we define pg_restrict to the
 # appropriate definition, which presumably won't conflict.
+#
 AC_C_RESTRICT
-if test "$ac_cv_c_restrict" = "no"; then
+if test "$ac_cv_c_restrict" = "no" ; then
   pg_restrict=""
 else
   pg_restrict="$ac_cv_c_restrict"
@@ -1996,22 +1999,11 @@ fi
 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 long's alignment is at least as strong as char, short, or int;
+# but we must check long long (if it is being used for int64) and double.
+# 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'])
diff --git a/doc/src/sgml/dfunc.sgml b/doc/src/sgml/dfunc.sgml
index b94aefcd0c..554f9fac4c 100644
--- a/doc/src/sgml/dfunc.sgml
+++ b/doc/src/sgml/dfunc.sgml
@@ -202,4 +202,23 @@ gcc -G -o foo.so foo.o
   server expects to find the shared library files.
  </para>
 
+<!--
+Under AIX, object files are compiled normally but building the shared
+library requires a couple of steps.  First, create the object file:
+.nf
+cc <other flags> -c foo.c
+.fi
+You must then create a symbol \*(lqexports\*(rq file for the object
+file:
+.nf
+mkldexport foo.o `pwd` &gt; foo.exp
+.fi
+Finally, you can create the shared library:
+.nf
+ld <other flags> -H512 -T512 -o foo.so -e _nostart \e
+   -bI:.../lib/postgres.exp -bE:foo.exp foo.o \e
+   -lm -lc 2>/dev/null
+.fi
+  -->
+
 </sect2>
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 1b32d5ca62..60e9a34a03 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -3401,7 +3401,7 @@ export MANPATH
   <para>
    <productname>PostgreSQL</productname> can be expected to work on current
    versions of these operating systems: Linux, Windows,
-   FreeBSD, OpenBSD, NetBSD, DragonFlyBSD, macOS, Solaris, and illumos.
+   FreeBSD, OpenBSD, NetBSD, DragonFlyBSD, macOS, AIX, Solaris, and illumos.
    Other Unix-like systems may also work but are not currently
    being tested.  In most cases, all CPU architectures supported by
    a given operating system will work.  Look in
@@ -3445,6 +3445,122 @@ export MANPATH
    installation issues.
   </para>
 
+  <sect2 id="installation-notes-aix">
+   <title>AIX</title>
+
+   <indexterm zone="installation-notes-aix">
+    <primary>AIX</primary>
+    <secondary>installation on</secondary>
+   </indexterm>
+
+   <para>
+    You can use GCC to build <productname>PostgreSQL</productname>
+    on <productname>AIX</productname>.
+   </para>
+
+   <para>
+    <productname>AIX</productname> versions before 7.1 are no longer
+    tested nor supported by the <productname>PostgreSQL</productname>
+    community.
+   </para>
+
+   <sect3 id="installation-notes-aix-mem-management">
+    <title>Memory Management</title>
+    <!-- https://archives.postgresql.org/message-id/603bgqmpl9.fsf@dba2.int.libertyrms.com -->
+
+    <para>
+     AIX can be somewhat peculiar with regards to the way it does
+     memory management.  You can have a server with many multiples of
+     gigabytes of RAM free, but still get out of memory or address
+     space errors when running applications.  One example
+     is loading of extensions failing with unusual errors.
+     For example, running as the owner of the PostgreSQL installation:
+<screen>
+=# CREATE EXTENSION plperl;
+ERROR:  could not load library "/opt/dbs/pgsql/lib/plperl.so": A memory address is not in the address space for the process.
+</screen>
+    Running as a non-owner in the group possessing the PostgreSQL
+    installation:
+<screen>
+=# CREATE EXTENSION plperl;
+ERROR:  could not load library "/opt/dbs/pgsql/lib/plperl.so": Bad address
+</screen>
+     Another example is out of memory errors in the PostgreSQL server
+     logs, with every memory allocation near or greater than 256 MB
+     failing.
+    </para>
+
+    <para>
+     The overall cause of all these problems is the default bittedness
+     and memory model used by the server process.  By default, all
+     binaries built on AIX are 32-bit.  This does not depend upon
+     hardware type or kernel in use.  These 32-bit processes are
+     limited to 4 GB of memory laid out in 256 MB segments using one
+     of a few models.  The default allows for less than 256 MB in the
+     heap as it shares a single segment with the stack.
+    </para>
+
+    <para>
+     In the case of the <literal>plperl</literal> example, above,
+     check your umask and the permissions of the binaries in your
+     PostgreSQL installation.  The binaries involved in that example
+     were 32-bit and installed as mode 750 instead of 755.  Due to the
+     permissions being set in this fashion, only the owner or a member
+     of the possessing group can load the library.  Since it isn't
+     world-readable, the loader places the object into the process'
+     heap instead of the shared library segments where it would
+     otherwise be placed.
+    </para>
+
+    <para>
+     The <quote>ideal</quote> solution for this is to use a 64-bit
+     build of PostgreSQL, but that is not always practical, because
+     systems with 32-bit processors can build, but not run, 64-bit
+     binaries.
+    </para>
+
+    <para>
+     If a 32-bit binary is desired, set <symbol>LDR_CNTRL</symbol> to
+     <literal>MAXDATA=0x<replaceable>n</replaceable>0000000</literal>,
+     where 1 &lt;= n &lt;= 8, before starting the PostgreSQL server,
+     and try different values and <filename>postgresql.conf</filename>
+     settings to find a configuration that works satisfactorily.  This
+     use of <symbol>LDR_CNTRL</symbol> tells AIX that you want the
+     server to have <symbol>MAXDATA</symbol> bytes set aside for the
+     heap, allocated in 256 MB segments.  When you find a workable
+     configuration,
+     <command>ldedit</command> can be used to modify the binaries so
+     that they default to using the desired heap size.  PostgreSQL can
+     also be rebuilt, passing <literal>configure
+     LDFLAGS="-Wl,-bmaxdata:0x<replaceable>n</replaceable>0000000"</literal>
+     to achieve the same effect.
+    </para>
+
+    <para>
+     For a 64-bit build, set <envar>OBJECT_MODE</envar> to 64 and
+     pass <literal>CC="gcc -maix64"</literal>
+     and <literal>LDFLAGS="-Wl,-bbigtoc"</literal>
+     to <command>configure</command>. 
+     If you omit the export of
+    <envar>OBJECT_MODE</envar>, your build may fail with linker errors.  When
+    <envar>OBJECT_MODE</envar> is set, it tells AIX's build utilities
+    such as <command>ar</command>, <command>as</command>, and <command>ld</command> what
+    type of objects to default to handling.
+    </para>
+
+    <para>
+     By default, overcommit of paging space can happen.  While we have
+     not seen this occur, AIX will kill processes when it runs out of
+     memory and the overcommit is accessed.  The closest to this that
+     we have seen is fork failing because the system decided that
+     there was not enough memory for another process.  Like many other
+     parts of AIX, the paging space allocation method and
+     out-of-memory kill is configurable on a system- or process-wide
+     basis if this becomes a problem.
+    </para>
+   </sect3>
+  </sect2>
+
   <sect2 id="installation-notes-cygwin">
    <title>Cygwin</title>
 
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 6047b8171d..64753d9c01 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -891,6 +891,29 @@ psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: No such
 
 
     <variablelist>
+     <varlistentry>
+      <term><systemitem class="osname">AIX</systemitem>
+      <indexterm><primary>AIX</primary><secondary>IPC configuration</secondary></indexterm>
+      </term>
+      <listitem>
+       <para>
+        It should not be necessary to do
+        any special configuration for such parameters as
+        <varname>SHMMAX</varname>, as it appears this is configured to
+        allow all memory to be used as shared memory.  That is the
+        sort of configuration commonly used for other databases such
+        as <application>DB/2</application>.</para>
+
+       <para> It might, however, be necessary to modify the global
+       <command>ulimit</command> information in
+       <filename>/etc/security/limits</filename>, as the default hard
+       limits for file sizes (<varname>fsize</varname>) and numbers of
+       files (<varname>nofiles</varname>) might be too low.
+       </para>
+      </listitem>
+     </varlistentry>
+
+
      <varlistentry>
       <term><systemitem class="osname">FreeBSD</systemitem>
       <indexterm><primary>FreeBSD</primary><secondary>IPC configuration</secondary></indexterm>
diff --git a/meson.build b/meson.build
index 1c0579d5a6..f1ac154cdc 100644
--- a/meson.build
+++ b/meson.build
@@ -196,7 +196,26 @@ endif
 # that purpose.
 portname = host_system
 
-if host_system == 'cygwin'
+if host_system == 'aix'
+  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'
+
+  # M:SRE sets a flag indicating that an object is a shared library. Seems to
+  # work in some circumstances without, but required in others.
+  ldflags_sl += '-Wl,-bM:SRE'
+  ldflags_be += '-Wl,-brtllib'
+
+  # Native memset() is faster, tested on:
+  # - AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
+  # - AIX 5.3 ML3, gcc 4.0.1
+  memset_loop_limit = 0
+
+elif host_system == 'cygwin'
   sema_kind = 'unnamed_posix'
   cppflags += '-D_GNU_SOURCE'
   dlsuffix = '.dll'
@@ -1490,11 +1509,11 @@ sizeof_long = cc.sizeof('long', args: test_c_args)
 cdata.set('SIZEOF_LONG', sizeof_long)
 if sizeof_long == 8
   cdata.set('HAVE_LONG_INT_64', 1)
-  pg_int64_type = 'long int'
+  cdata.set('PG_INT64_TYPE', 'long int')
   cdata.set_quoted('INT64_MODIFIER', 'l')
 elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
   cdata.set('HAVE_LONG_LONG_INT_64', 1)
-  pg_int64_type = 'long long int'
+  cdata.set('PG_INT64_TYPE', 'long long int')
   cdata.set_quoted('INT64_MODIFIER', 'll')
 else
   error('do not know how to get a 64bit int')
@@ -1508,31 +1527,15 @@ endif
 # Determine memory alignment requirements for the basic C data types.
 
 alignof_types = ['short', 'int', 'long', 'double']
+maxalign = 0
 foreach t : alignof_types
   align = cc.alignment(t, args: test_c_args)
+  if maxalign < align
+    maxalign = align
+  endif
   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'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(pg_int64_type, args: test_c_args) > alignof_double
-  error('alignment of int64 is greater than the alignment of double')
-endif
-cdata.set('MAXIMUM_ALIGNOF', alignof_double)
+cdata.set('MAXIMUM_ALIGNOF', maxalign)
 
 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
@@ -1581,7 +1584,7 @@ if cc.links('''
   if not meson.is_cross_build()
     r = cc.run('''
     /* This must match the corresponding code in c.h: */
-    #if defined(__GNUC__) || defined(__SUNPRO_C)
+    #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
     #define pg_attribute_aligned(a) __attribute__((aligned(a)))
     #elif defined(_MSC_VER)
     #define pg_attribute_aligned(a) __declspec(align(a))
@@ -2476,6 +2479,10 @@ endif
 # conflict.
 #
 # We assume C99 support, so we don't need to make this conditional.
+#
+# XXX: Historically we allowed platforms to disable restrict in template
+# files, but that was only added for AIX when building with XLC, which we
+# don't support yet.
 cdata.set('pg_restrict', '__restrict')
 
 
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index fa81f6ffdd..8ca51ca03f 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,20 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +268,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps shared libraries inside a static library, can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +289,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +401,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +419,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 6700aec039..954b14962f 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -62,12 +62,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -94,6 +96,24 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
diff --git a/src/backend/meson.build b/src/backend/meson.build
index 436c04af08..8767aaba67 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -91,6 +91,21 @@ if cc.get_id() == 'msvc'
   # be restricted to b_pch=true.
   backend_link_with += postgres_lib
 
+elif 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
 
 backend_input = []
diff --git a/src/backend/port/aix/mkldexport.sh b/src/backend/port/aix/mkldexport.sh
new file mode 100755
index 0000000000..adf3793e86
--- /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/utils/error/elog.c b/src/backend/utils/error/elog.c
index d91a85cb2d..7b51e94f4a 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -908,7 +908,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/backend/utils/misc/ps_status.c b/src/backend/utils/misc/ps_status.c
index 9da6377402..532eac31b4 100644
--- a/src/backend/utils/misc/ps_status.c
+++ b/src/backend/utils/misc/ps_status.c
@@ -50,7 +50,7 @@ bool		update_process_title = DEFAULT_UPDATE_PROCESS_TITLE;
 #define PS_USE_SETPROCTITLE_FAST
 #elif defined(HAVE_SETPROCTITLE)
 #define PS_USE_SETPROCTITLE
-#elif defined(__linux__) || defined(__sun) || defined(__darwin__)
+#elif defined(__linux__) || defined(_AIX) || defined(__sun) || defined(__darwin__)
 #define PS_USE_CLOBBER_ARGV
 #elif defined(WIN32)
 #define PS_USE_WIN32
@@ -60,7 +60,7 @@ bool		update_process_title = DEFAULT_UPDATE_PROCESS_TITLE;
 
 
 /* Different systems want the buffer padded differently */
-#if defined(__linux__) || defined(__darwin__)
+#if defined(_AIX) || defined(__linux__) || defined(__darwin__)
 #define PS_PADDING '\0'
 #else
 #define PS_PADDING ' '
diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
index 2d4b75a6fe..ce936959c1 100644
--- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
+++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
@@ -401,7 +401,8 @@ SKIP:
 {
 	my $tar = $ENV{TAR};
 	# don't check for a working tar here, to accommodate various odd
-	# cases. If tar doesn't work the init_from_backup below will fail.
+	# cases such as AIX. If tar doesn't work the init_from_backup below
+	# will fail.
 	skip "no tar program available", 1
 	  if (!defined $tar || $tar eq '');
 
diff --git a/src/bin/pg_verifybackup/t/008_untar.pl b/src/bin/pg_verifybackup/t/008_untar.pl
index 7a09f3b75b..30d9f3f7f0 100644
--- a/src/bin/pg_verifybackup/t/008_untar.pl
+++ b/src/bin/pg_verifybackup/t/008_untar.pl
@@ -104,7 +104,8 @@ for my $tc (@test_configuration)
 		{
 			my $tar = $ENV{TAR};
 			# don't check for a working tar here, to accommodate various odd
-			# cases. If tar doesn't work the init_from_backup below will fail.
+			# cases such as AIX. If tar doesn't work the init_from_backup below
+			# will fail.
 			skip "no tar program available", 1
 			  if (!defined $tar || $tar eq '');
 
diff --git a/src/bin/pg_verifybackup/t/010_client_untar.pl b/src/bin/pg_verifybackup/t/010_client_untar.pl
index 8c076d46de..45010d79ac 100644
--- a/src/bin/pg_verifybackup/t/010_client_untar.pl
+++ b/src/bin/pg_verifybackup/t/010_client_untar.pl
@@ -134,7 +134,8 @@ for my $tc (@test_configuration)
 		{
 			my $tar = $ENV{TAR};
 			# don't check for a working tar here, to accommodate various odd
-			# cases. If tar doesn't work the init_from_backup below will fail.
+			# cases such as AIX. If tar doesn't work the init_from_backup below
+			# will fail.
 			skip "no tar program available", 1
 			  if (!defined $tar || $tar eq '');
 
diff --git a/src/include/c.h b/src/include/c.h
index dc1841346c..641cd9bdf1 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -182,7 +182,7 @@
 #define PG_USED_FOR_ASSERTS_ONLY pg_attribute_unused()
 #endif
 
-/* GCC supports format attributes */
+/* GCC support format attributes */
 #if defined(__GNUC__)
 #define pg_attribute_format_arg(a) __attribute__((format_arg(a)))
 #define pg_attribute_printf(f,a) __attribute__((format(PG_PRINTF_ATTRIBUTE, f, a)))
@@ -192,7 +192,7 @@
 #endif
 
 /* GCC and Sunpro support aligned, packed and noreturn */
-#if defined(__GNUC__) || defined(__SUNPRO_C)
+#if defined(__GNUC__) || defined(__SUNPRO_C) 
 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
 #define pg_attribute_noreturn() __attribute__((noreturn))
 #define pg_attribute_packed() __attribute__((packed))
diff --git a/src/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 0000000000..1c2d166791
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,6 @@
+/*
+ * src/include/port/aix.h
+ */
+#define CLASS_CONFLICT
+#define DISABLE_XOPEN_NLS
+
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 29ac6cdcd9..768dbbd2e3 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -401,57 +401,16 @@ 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 gcc atomic routines, to set the lock. */
 #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 */
 
 
@@ -662,6 +621,21 @@ tas(volatile slock_t *lock)
 
 #if !defined(HAS_TEST_AND_SET)	/* We didn't trigger above, let's try here */
 
+#if defined(_AIX)	/* AIX */
+/*
+ * AIX (POWER)
+ */
+#define HAS_TEST_AND_SET
+
+#include <sys/atomic_op.h>
+
+typedef int slock_t;
+
+#define TAS(lock)			_check_lock((slock_t *) (lock), 0, 1)
+#define S_UNLOCK(lock)		_clear_lock((slock_t *) (lock), 0)
+#endif	 /* _AIX */
+
+
 /* These are in sunstudio_(sparc|x86).s */
 
 #if defined(__SUNPRO_C) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index b36a765764..154429d4d1 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -114,7 +114,7 @@ backend_src = $(top_srcdir)/src/backend
 # coding rule.
 libpq-refs-stamp: $(shlib)
 ifneq ($(enable_coverage), yes)
-ifeq (,$(filter solaris,$(PORTNAME)))
+ifeq (,$(filter aix solaris,$(PORTNAME)))
 	@if nm -A -u $< 2>/dev/null | grep -v -e __cxa_atexit -e __tsan_func_exit | grep exit; then \
 		echo 'libpq must not be calling any function which invokes exit'; exit 1; \
 	fi
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index ed2a4048d1..7e2017daf0 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -54,8 +54,9 @@ libpq_c_args = ['-DSO_MAJOR_VERSION=5']
 #    libpq_st, and {pgport,common}_shlib for libpq_sh
 #
 # We could try to avoid building the source files twice, but it probably adds
-# more complexity than its worth (reusing object files requires also linking
-# to the library on windows or breaks precompiled headers).
+# more complexity than its worth (AIX doesn't support link_whole yet, reusing
+# object files requires also linking to the library on windows or breaks
+# precompiled headers).
 libpq_st = static_library('libpq',
   libpq_sources,
   include_directories: [libpq_inc],
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 0000000000..dd16a7a037
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,39 @@
+# MAKE_EXPORTS is required for svr4 loaders that want a file of
+# symbol names to tell them what to export/import.
+MAKE_EXPORTS= true
+
+# -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
+
+rpath = -Wl,-blibpath:'$(rpathdir)$(libpath)'
+
+LDFLAGS_SL += -Wl,-bnoentry -Wl,-H512 -Wl,-bM:SRE
+
+# 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/port/README b/src/port/README
index ed5c54a72f..97f18a6233 100644
--- a/src/port/README
+++ b/src/port/README
@@ -28,5 +28,5 @@ applications.
 from libpgport are linked first.  This avoids having applications
 dependent on symbols that are _used_ by libpq, but not intended to be
 exported by libpq.  libpq's libpgport usage changes over time, so such a
-dependency is a problem.  Windows, Linux, and macOS use an export
+dependency is a problem.  Windows, Linux, AIX, and macOS use an export
 list to control the symbols exported by libpq.
diff --git a/src/port/strerror.c b/src/port/strerror.c
index 4918ba821c..1070a49802 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,8 +214,10 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
 			return "ENOTEMPTY";
+#endif
 		case ENOTSOCK:
 			return "ENOTSOCK";
 #ifdef ENOTSUP
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 0000000000..0a788676c0
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,14 @@
+# src/template/aix
+
+  # Due to a compiler bug, see 20171013023536.GA492146@rfd.leadboat.com for details,
+  # force restrict not to be used when compiling with xlc.
+#  FORCE_DISABLE_RESTRICT=yes
+#fi
+
+# Extra CFLAGS for code that will go into a shared library
+CFLAGS_SL=""
+
+# Native memset() is faster, tested on:
+# 	AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
+# 	AIX 5.3 ML3, gcc 4.0.1
+MEMSET_LOOP_LIMIT=0
diff --git a/src/test/regress/Makefile b/src/test/regress/Makefile
index 6409a485e8..7c665ff892 100644
--- a/src/test/regress/Makefile
+++ b/src/test/regress/Makefile
@@ -7,6 +7,11 @@
 # GNU make uses a make file named "GNUmakefile" in preference to "Makefile"
 # if it exists.  Postgres is shipped with a "GNUmakefile".
 
+
+# AIX make defaults to building *every* target of the first rule.  Start with
+# a single-target, empty rule to make the other targets non-default.
+all:
+
 all install clean check installcheck:
 	@echo "You must use GNU make to use Postgres.  It may be installed"
 	@echo "on your system with the name 'gmake'."
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 8370c1561c..c5c675b750 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -25,3 +25,32 @@ SELECT relname, relkind
 ---------+---------
 (0 rows)
 
+--
+-- When ALIGNOF_DOUBLE==4 (e.g. AIX), the C ABI may impose 8-byte alignment on
+-- some of the C types that correspond to TYPALIGN_DOUBLE SQL types.  To ensure
+-- catalog C struct layout matches catalog tuple layout, arrange for the tuple
+-- offset of each fixed-width, attalign='d' catalog column to be divisible by 8
+-- unconditionally.  Keep such columns before the first NameData column of the
+-- catalog, since packagers can override NAMEDATALEN to an odd number.
+--
+WITH check_columns AS (
+ SELECT relname, attname,
+  array(
+   SELECT t.oid
+    FROM pg_type t JOIN pg_attribute pa ON t.oid = pa.atttypid
+    WHERE pa.attrelid = a.attrelid AND
+          pa.attnum > 0 AND pa.attnum < a.attnum
+    ORDER BY pa.attnum) AS coltypes
+ FROM pg_attribute a JOIN pg_class c ON c.oid = attrelid
+  JOIN pg_namespace n ON c.relnamespace = n.oid
+ WHERE attalign = 'd' AND relkind = 'r' AND
+  attnotnull AND attlen <> -1 AND n.nspname = 'pg_catalog'
+)
+SELECT relname, attname, coltypes, get_columns_length(coltypes)
+ FROM check_columns
+ WHERE get_columns_length(coltypes) % 8 != 0 OR
+       'name'::regtype::oid = ANY(coltypes);
+ relname | attname | coltypes | get_columns_length 
+---------+---------+----------+--------------------
+(0 rows)
+
diff --git a/src/test/regress/expected/test_setup.out b/src/test/regress/expected/test_setup.out
index 3d0eeec996..5d9e6bf12b 100644
--- a/src/test/regress/expected/test_setup.out
+++ b/src/test/regress/expected/test_setup.out
@@ -209,6 +209,10 @@ CREATE FUNCTION ttdummy ()
     RETURNS trigger
     AS :'regresslib'
     LANGUAGE C;
+CREATE FUNCTION get_columns_length(oid[])
+    RETURNS int
+    AS :'regresslib'
+    LANGUAGE C STRICT STABLE PARALLEL SAFE;
 -- Use hand-rolled hash functions and operator classes to get predictable
 -- result on different machines.  The hash function for int4 simply returns
 -- the sum of the values passed to it and the one for text returns the length
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index deffaea578..cc633864d7 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -1221,3 +1221,43 @@ binary_coercible(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(IsBinaryCoercible(srctype, targettype));
 }
+
+/*
+ * Return the length of the portion of a tuple consisting of the given array
+ * of data types.  The input data types must be fixed-length data types.
+ */
+PG_FUNCTION_INFO_V1(get_columns_length);
+Datum
+get_columns_length(PG_FUNCTION_ARGS)
+{
+	ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
+	Oid		   *type_oids;
+	int			ntypes;
+	int			column_offset = 0;
+
+	if (ARR_HASNULL(ta) && array_contains_nulls(ta))
+		elog(ERROR, "argument must not contain nulls");
+
+	if (ARR_NDIM(ta) > 1)
+		elog(ERROR, "argument must be empty or one-dimensional array");
+
+	type_oids = (Oid *) ARR_DATA_PTR(ta);
+	ntypes = ArrayGetNItems(ARR_NDIM(ta), ARR_DIMS(ta));
+	for (int i = 0; i < ntypes; i++)
+	{
+		Oid			typeoid = type_oids[i];
+		int16		typlen;
+		bool		typbyval;
+		char		typalign;
+
+		get_typlenbyvalalign(typeoid, &typlen, &typbyval, &typalign);
+
+		/* the data type must be fixed-length */
+		if (typlen < 0)
+			elog(ERROR, "type %u is not fixed-length data type", typeoid);
+
+		column_offset = att_align_nominal(column_offset + typlen, typalign);
+	}
+
+	PG_RETURN_INT32(column_offset);
+}
diff --git a/src/test/regress/sql/sanity_check.sql b/src/test/regress/sql/sanity_check.sql
index 162e5324b5..7f338d191c 100644
--- a/src/test/regress/sql/sanity_check.sql
+++ b/src/test/regress/sql/sanity_check.sql
@@ -19,3 +19,29 @@ SELECT relname, relkind
   FROM pg_class
  WHERE relkind IN ('v', 'c', 'f', 'p', 'I')
        AND relfilenode <> 0;
+
+--
+-- When ALIGNOF_DOUBLE==4 (e.g. AIX), the C ABI may impose 8-byte alignment on
+-- some of the C types that correspond to TYPALIGN_DOUBLE SQL types.  To ensure
+-- catalog C struct layout matches catalog tuple layout, arrange for the tuple
+-- offset of each fixed-width, attalign='d' catalog column to be divisible by 8
+-- unconditionally.  Keep such columns before the first NameData column of the
+-- catalog, since packagers can override NAMEDATALEN to an odd number.
+--
+WITH check_columns AS (
+ SELECT relname, attname,
+  array(
+   SELECT t.oid
+    FROM pg_type t JOIN pg_attribute pa ON t.oid = pa.atttypid
+    WHERE pa.attrelid = a.attrelid AND
+          pa.attnum > 0 AND pa.attnum < a.attnum
+    ORDER BY pa.attnum) AS coltypes
+ FROM pg_attribute a JOIN pg_class c ON c.oid = attrelid
+  JOIN pg_namespace n ON c.relnamespace = n.oid
+ WHERE attalign = 'd' AND relkind = 'r' AND
+  attnotnull AND attlen <> -1 AND n.nspname = 'pg_catalog'
+)
+SELECT relname, attname, coltypes, get_columns_length(coltypes)
+ FROM check_columns
+ WHERE get_columns_length(coltypes) % 8 != 0 OR
+       'name'::regtype::oid = ANY(coltypes);
diff --git a/src/test/regress/sql/test_setup.sql b/src/test/regress/sql/test_setup.sql
index 06b0e2121f..1b2d434683 100644
--- a/src/test/regress/sql/test_setup.sql
+++ b/src/test/regress/sql/test_setup.sql
@@ -257,6 +257,11 @@ CREATE FUNCTION ttdummy ()
     AS :'regresslib'
     LANGUAGE C;
 
+CREATE FUNCTION get_columns_length(oid[])
+    RETURNS int
+    AS :'regresslib'
+    LANGUAGE C STRICT STABLE PARALLEL SAFE;
+
 -- Use hand-rolled hash functions and operator classes to get predictable
 -- result on different machines.  The hash function for int4 simply returns
 -- the sum of the values passed to it and the one for text returns the length
diff --git a/src/tools/gen_export.pl b/src/tools/gen_export.pl
index d9fdaaaf6d..888c8a197a 100644
--- a/src/tools/gen_export.pl
+++ b/src/tools/gen_export.pl
@@ -16,11 +16,12 @@ GetOptions(
 	'input:s' => \$input,
 	'output:s' => \$output) or die "wrong arguments";
 
-if (not(   $format eq 'darwin'
+if (not(   $format eq 'aix'
+		or $format eq 'darwin'
 		or $format eq 'gnu'
 		or $format eq 'win'))
 {
-	die "$0: $format is not yet handled (only darwin, gnu, win are)\n";
+	die "$0: $format is not yet handled (only aix, darwin, gnu, win are)\n";
 }
 
 open(my $input_handle, '<', $input)
@@ -55,7 +56,11 @@ while (<$input_handle>)
 	}
 	elsif (/^(\S+)\s+(\S+)/)
 	{
-		if ($format eq 'darwin')
+		if ($format eq 'aix')
+		{
+			print $output_handle "$1\n";
+		}
+		elsif ($format eq 'darwin')
 		{
 			print $output_handle "_$1\n";
 		}
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 4a157d0a5f..cfd8c6896c 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -85,6 +85,7 @@ do
 
 	# These files are platform-specific, and c.h will include the
 	# one that's relevant for our current platform anyway.
+	test "$f" = src/include/port/aix.h && continue
 	test "$f" = src/include/port/cygwin.h && continue
 	test "$f" = src/include/port/darwin.h && continue
 	test "$f" = src/include/port/freebsd.h && continue
-- 
2.41.0

buildfarm17-summary.logapplication/octet-stream; name=buildfarm17-summary.logDownload
sections-1.ctext/plain; name=sections-1.cDownload
#61Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Srirama Kucherlapati (#60)
Re: AIX support

On 11/09/2024 15:38, Srirama Kucherlapati wrote:

I still don't understand. We have Linux powerpc systems running
happily in the buildfarm. They are happy with the current spinlock
implementation. Why is this needed? What happens without it?

Not sure, by the time the below commits were made if there was a
consideration to use the gcc routines.

The PPC asm code was originally written in 2002, and the first use of
__sync_lock_test_and_set(), for ARM, appeared in 2012. The commit that
made __sync_lock_test_and_set() be chosen automatically for platforms
that don't specify anything else was added in 2022.

I tried to replace the AIX asm (under__ppc__ macro) with the gcc
routine __sync_lock_test_and_set(), and all the buildfarm tests
passed. Attached patch and the buildfarm output. Please let me know
your feedback.

Ok, if we don't need the assembler code at all, that's good. A patch to
introduce AIX support should not change it for non-AIX powerpc systems
though. That might be a good change, but would need to be justified
separately, e.g. by some performance testing, and should be a separate
patch.

If you make no changes to s_lock.h at all, will it work? Why not?

You said earlier:

I mean this part of the code is needed as this is specific to AIX kernel memory
operation which is different from __sync_lock_test_and_set().

I would like to mention that the changes made in src/include/storage/s_lock.h
are pretty much required and need to be operated in assemble specific to IBM
Power architecture.

Was that earlier statement incorrect? Is the manual wrong or outdated or
not applicable to us?

Moving on..

Do you still need mkldexport.sh? Surely there's a better way to do that
in year 2024. Some quick googling says there's a '-bexpall' option to
'ld', which kind of sounds like what we want. Will that work? How do
other programs do this?

--
Heikki Linnakangas
Neon (https://neon.tech)

#62Thomas Munro
thomas.munro@gmail.com
In reply to: Heikki Linnakangas (#61)
Re: AIX support

On Thu, Sep 12, 2024 at 9:57 AM Heikki Linnakangas <hlinnaka@iki.fi> wrote:

If you make no changes to s_lock.h at all, will it work? Why not?

It's good to keep the work independent and I don't want to hold up
anything happening in this thread, but just for information: I have
been poking around at the idea of entirely removing the old spinlock
code and pointing spin.h's function-like-macros to the atomics code.
We couldn't do that before, because atomics were sometimes implemented
with spinlocks, but now that pg_atomic_flag is never implemented with
spinlocks we can flip that around, and then have only one place where
we know how to do this stuff. What is needed for that to progress is,
I guess, to determine though assembler analysis or experimentation
across a bunch of targets that it works out at least as good...

/messages/by-id/CA+hUKGJ+oA+62iUZ-EQb5R2cAOW3Y942ZoOtzOD=1sQ05iNg6Q@mail.gmail.com

#63Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Heikki Linnakangas (#61)
RE: AIX support

The PPC asm code was originally written in 2002, and the first use of
_ sync_lock_test_and_set(), for ARM, appeared in 2012. The commit that
made __sync_lock_test_and_set() be chosen automatically for platforms
that don't specify anything else was added in 2022.

Thanks for the info.

------------------

Ok, if we don't need the assembler code at all, that's good. A patch to
introduce AIX support should not change it for non-AIX powerpc systems
though. That might be a good change, but would need to be justified
separately, e.g. by some performance testing, and should be a separate
patch.

If you make no changes to s_lock.h at all, will it work? Why not?

With the existing asm code I see there are some syntax errors, being hit.
But after reverting the old changes the issues resolved. Below are diffs.

     static __inline__ int
     tas(volatile slock_t *lock)
     {
    @@ -424,17 +413,15 @@ tas(volatile slock_t *lock)
            __asm__ __volatile__(
     "      lwarx   %0,0,%3,1       \n"
     "      cmpwi   %0,0            \n"
    -"      bne     1f                      \n"
    +"      bne     $+16            \n"             /* branch to li %1,1 */
     "      addi    %0,%0,1         \n"
     "      stwcx.  %0,0,%3         \n"
    -"      beq     2f                      \n"
    -"1: \n"
    +"      beq     $+12            \n"             /* branch to lwsync */
     "      li      %1,1            \n"
    -"      b       3f                      \n"
    -"2: \n"
    +"      b       $+12            \n"             /* branch to end of asm sequence */
     "      lwsync                          \n"
     "      li      %1,0            \n"
    -"3: \n"
    +
     :      "=&b"(_t), "=r"(_res), "+m"(*lock)
     :      "r"(lock)
     :      "memory", "cc");

Let me know if I need to run any perf tools to check the performance of
the __sync_lock_test_and_set change.

---------------

I mean this part of the code is needed as this is specific to AIX kernel memory
operation which is different from __sync_lock_test_and_set().

I would like to mention that the changes made in src/include/storage/s_lock.h
are pretty much required and need to be operated in assemble specific to IBM
Power architecture.

Was that earlier statement incorrect? Is the manual wrong or outdated or
not applicable to us?

Here this change is specific to AIX, but since we are compiling with gcc, this
is not applicable. But I will try with __sync* routines and check.

---------------

Do you still need mkldexport.sh? Surely there's a better way to do that
in year 2024. Some quick googling says there's a '-bexpall' option to
'ld', which kind of sounds like what we want. Will that work? How do
other programs do this?

Thanks for looking into this, I’m working on this, I will let you know.

Thanks,
Sriram.

#64Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#63)
RE: AIX support

Do you still need mkldexport.sh? Surely there's a better way to do that
in year 2024. Some quick googling says there's a '-bexpall' option to
'ld', which kind of sounds like what we want. Will that work? How do
other programs do this?

We have noticed couple of caveats with these flags -bexpall/-bexpfull in other
opensource tools on AIX. This option would export too many symbols causing
problems because a shared library may re-export symbols from another library
causing confused dependencies, duplicate symbols.

We have similar discussion wrt to these flag in Cmake

https://gitlab.kitware.com/cmake/cmake/-/issues/19163

Also, I tried some sample program to verify the same as below

cat foo.c

#include <stdio.h>

#include <string.h>

int func1()

{

char str1[] = "Hello ", str2[] = "world! ";

strcat(str1,str2);

puts(str1);

return 0;

}

gcc -c foo.c -o foo.o

gcc -shared -Wl,-bexpall -o foo.so foo.o

dump -Tov foo.so

foo.so:

***Object Module Header***

# Sections Symbol Ptr # Symbols Opt Hdr Len Flags

4 0x00000d88 120 72 0x3002

Flags=( EXEC DYNLOAD SHROBJ DEP_SYSTEM )

Timestamp = "Sep 17 10:17:35 2024"

Magic = 0x1df (32-bit XCOFF)

***Optional Header***

Tsize Dsize Bsize Tstart Dstart

0x00000548 0x0000010c 0x00000004 0x10000128 0x20000670

SNloader SNentry SNtext SNtoc SNdata

0x0004 0x0000 0x0001 0x0002 0x0002

TXTalign DATAalign TOC vstamp entry

0x0005 0x0004 0x20000750 0x0001 0xffffffff

maxSTACK maxDATA SNbss magic modtype

0x00000000 0x00000000 0x0003 0x010b RE

***Loader Section***

***Loader Symbol Table Information***

[Index] Value Scn IMEX Sclass Type IMPid Name

[0]: 0x2000068c .data RW SECdef [noIMid] __rtinit

[1]: 0x00000000 undef IMP DS EXTref libgcc_s.a(shr.o) __cxa_finalize

[2]: 0x00000000 undef IMP DS EXTref libgcc_s.a(shr.o) _GLOBAL__AIXI_shr_o

[3]: 0x00000000 undef IMP DS EXTref libgcc_s.a(shr.o) _GLOBAL__AIXD_shr_o

[4]: 0x00000000 undef IMP DS EXTref libc.a(shr.o) __strtollmax

[5]: 0x00000000 undef IMP DS EXTref libc.a(shr.o) puts

[6]: 0x200006f4 .data EXP DS Ldef [noIMid] __init_aix_libgcc_cxa_atexit

[7]: 0x20000724 .data EXP DS Ldef [noIMid] _GLOBAL__AIXI_foo_so

[8]: 0x20000730 .data EXP DS Ldef [noIMid] _GLOBAL__AIXD_foo_so

[9] 0x2000073c .data EXP DS SECdef [noIMid] strcat

[10]: 0x20000744 .data EXP DS Ldef [noIMid] func1

The code makes use of strcat from libc but re-exports the symbol (because of -bexpall).

As of now due to the limitation with these flags (-bexpall / -bexpfull ? ), the

solution here is to continue to extract the symbols from the object files and

use that export file as part of building the shared library. (Continue to use

the mkldexport.sh script to generate the export symbols).

Thanks,
Sriram.

#65Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#64)
2 attachment(s)
RE: AIX support

Hi Heikki & team,

Could you please let me know your comments on the previous details?

Attached are the individual patches for AIX and gcc(__sync) routines.

Thanks,
Sriram.

Attachments:

0001-AIX-support-revert-the-changes-from-0b16bb8776bb8.v5.patchapplication/octet-stream; name=0001-AIX-support-revert-the-changes-from-0b16bb8776bb8.v5.patchDownload
From f8260d015857d3a65292e55f08ec3a13b60f00b3 Mon Sep 17 00:00:00 2001
From: Sriram RK <sriram.rk@in.ibm.com>
Date: Mon, 20 May 2024 01:38:59 -0500
Subject: [PATCH 1/1] AIX support, revert the changes from 0b16bb8776bb8. Trim
 AIX/XLC changes to support gcc only.

 - Review comments from Heikki.
 - Replace tas() AIX asm with gcc __sync_lock_test_and_set().
 - Fix tas() for powerPC.
 - Include only AIX specific changes in s_lock.h
---
 Makefile                                      |   2 -
 configure                                     |  37 +++---
 configure.ac                                  |  28 ++---
 doc/src/sgml/dfunc.sgml                       |  19 +++
 doc/src/sgml/installation.sgml                | 118 +++++++++++++++++-
 doc/src/sgml/runtime.sgml                     |  23 ++++
 meson.build                                   |  57 +++++----
 src/Makefile.shlib                            |  29 +++++
 src/backend/Makefile                          |  20 +++
 src/backend/meson.build                       |  15 +++
 src/backend/port/aix/mkldexport.sh            |  61 +++++++++
 src/backend/utils/error/elog.c                |   2 +
 src/backend/utils/misc/ps_status.c            |   4 +-
 src/bin/pg_basebackup/t/010_pg_basebackup.pl  |   3 +-
 src/bin/pg_verifybackup/t/008_untar.pl        |   3 +-
 src/bin/pg_verifybackup/t/010_client_untar.pl |   3 +-
 src/include/c.h                               |   4 +-
 src/include/port/aix.h                        |   6 +
 src/include/storage/s_lock.h                  |  25 +++-
 src/interfaces/libpq/Makefile                 |   2 +-
 src/interfaces/libpq/meson.build              |   5 +-
 src/makefiles/Makefile.aix                    |  39 ++++++
 src/port/README                               |   2 +-
 src/port/strerror.c                           |   2 +
 src/template/aix                              |  14 +++
 src/test/regress/Makefile                     |   5 +
 src/test/regress/expected/sanity_check.out    |  29 +++++
 src/test/regress/expected/test_setup.out      |   4 +
 src/test/regress/regress.c                    |  40 ++++++
 src/test/regress/sql/sanity_check.sql         |  26 ++++
 src/test/regress/sql/test_setup.sql           |   5 +
 src/tools/gen_export.pl                       |  11 +-
 src/tools/pginclude/headerscheck              |   1 +
 33 files changed, 555 insertions(+), 89 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 create mode 100644 src/include/port/aix.h
 create mode 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index 8a2ec9396b..9bc1a4ec17 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/configure b/configure
index 89644f2249..f218b2e040 100755
--- a/configure
+++ b/configure
@@ -2988,6 +2988,7 @@ else
 # --with-template not given
 
 case $host_os in
+     aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -6848,7 +6849,6 @@ if test x"$pgac_cv_prog_CXX_cxxflags__fno_strict_aliasing" = x"yes"; then
   CXXFLAGS="${CXXFLAGS} -fno-strict-aliasing"
 fi
 
-
 fi
 
 # If the compiler knows how to hide symbols, add the switch needed for that to
@@ -12860,7 +12860,8 @@ fi
 
 fi
 
-# Note: We can test for libldap_r only after we know PTHREAD_LIBS
+# Note: We can test for libldap_r only after we know PTHREAD_LIBS;
+# also, on AIX, we may need to have openssl in LIBS for this step.
 if test "$with_ldap" = yes ; then
   _LIBS="$LIBS"
   if test "$PORTNAME" != "win32"; then
@@ -16951,28 +16952,18 @@ _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
+# We assume long's alignment is at least as strong as char, short, or int;
+# but we must check long long (if it is being used for int64) and double.
+# 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
-  as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
+MAX_ALIGNOF=$ac_cv_alignof_long
+if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+  MAX_ALIGNOF=$ac_cv_alignof_double
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $MAX_ALIGNOF -lt $ac_cv_alignof_long_long_int ; then
+  MAX_ALIGNOF="$ac_cv_alignof_long_long_int"
 fi
 
 cat >>confdefs.h <<_ACEOF
@@ -17090,7 +17081,7 @@ else
 /* end confdefs.h.  */
 
 /* This must match the corresponding code in c.h: */
-#if defined(__GNUC__) || defined(__SUNPRO_C)
+#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
 #elif defined(_MSC_VER)
 #define pg_attribute_aligned(a) __declspec(align(a))
diff --git a/configure.ac b/configure.ac
index c7322e292c..a059509cd9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ PGAC_ARG_REQ(with, template, [NAME], [override operating system template],
 # --with-template not given
 
 case $host_os in
+     aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -1385,7 +1386,8 @@ if test "$with_zstd" = yes ; then
   AC_CHECK_LIB(zstd, ZSTD_compress, [], [AC_MSG_ERROR([library 'zstd' is required for ZSTD support])])
 fi
 
-# Note: We can test for libldap_r only after we know PTHREAD_LIBS
+# Note: We can test for libldap_r only after we know PTHREAD_LIBS;
+# also, on AIX, we may need to have openssl in LIBS for this step.
 if test "$with_ldap" = yes ; then
   _LIBS="$LIBS"
   if test "$PORTNAME" != "win32"; then
@@ -1643,8 +1645,9 @@ PGAC_TYPE_LOCALE_T
 # spelling it understands, because it conflicts with
 # __declspec(restrict). Therefore we define pg_restrict to the
 # appropriate definition, which presumably won't conflict.
+#
 AC_C_RESTRICT
-if test "$ac_cv_c_restrict" = "no"; then
+if test "$ac_cv_c_restrict" = "no" ; then
   pg_restrict=""
 else
   pg_restrict="$ac_cv_c_restrict"
@@ -1996,22 +1999,11 @@ fi
 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 long's alignment is at least as strong as char, short, or int;
+# but we must check long long (if it is being used for int64) and double.
+# 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'])
diff --git a/doc/src/sgml/dfunc.sgml b/doc/src/sgml/dfunc.sgml
index b94aefcd0c..554f9fac4c 100644
--- a/doc/src/sgml/dfunc.sgml
+++ b/doc/src/sgml/dfunc.sgml
@@ -202,4 +202,23 @@ gcc -G -o foo.so foo.o
   server expects to find the shared library files.
  </para>
 
+<!--
+Under AIX, object files are compiled normally but building the shared
+library requires a couple of steps.  First, create the object file:
+.nf
+cc <other flags> -c foo.c
+.fi
+You must then create a symbol \*(lqexports\*(rq file for the object
+file:
+.nf
+mkldexport foo.o `pwd` &gt; foo.exp
+.fi
+Finally, you can create the shared library:
+.nf
+ld <other flags> -H512 -T512 -o foo.so -e _nostart \e
+   -bI:.../lib/postgres.exp -bE:foo.exp foo.o \e
+   -lm -lc 2>/dev/null
+.fi
+  -->
+
 </sect2>
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 1b32d5ca62..60e9a34a03 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -3401,7 +3401,7 @@ export MANPATH
   <para>
    <productname>PostgreSQL</productname> can be expected to work on current
    versions of these operating systems: Linux, Windows,
-   FreeBSD, OpenBSD, NetBSD, DragonFlyBSD, macOS, Solaris, and illumos.
+   FreeBSD, OpenBSD, NetBSD, DragonFlyBSD, macOS, AIX, Solaris, and illumos.
    Other Unix-like systems may also work but are not currently
    being tested.  In most cases, all CPU architectures supported by
    a given operating system will work.  Look in
@@ -3445,6 +3445,122 @@ export MANPATH
    installation issues.
   </para>
 
+  <sect2 id="installation-notes-aix">
+   <title>AIX</title>
+
+   <indexterm zone="installation-notes-aix">
+    <primary>AIX</primary>
+    <secondary>installation on</secondary>
+   </indexterm>
+
+   <para>
+    You can use GCC to build <productname>PostgreSQL</productname>
+    on <productname>AIX</productname>.
+   </para>
+
+   <para>
+    <productname>AIX</productname> versions before 7.1 are no longer
+    tested nor supported by the <productname>PostgreSQL</productname>
+    community.
+   </para>
+
+   <sect3 id="installation-notes-aix-mem-management">
+    <title>Memory Management</title>
+    <!-- https://archives.postgresql.org/message-id/603bgqmpl9.fsf@dba2.int.libertyrms.com -->
+
+    <para>
+     AIX can be somewhat peculiar with regards to the way it does
+     memory management.  You can have a server with many multiples of
+     gigabytes of RAM free, but still get out of memory or address
+     space errors when running applications.  One example
+     is loading of extensions failing with unusual errors.
+     For example, running as the owner of the PostgreSQL installation:
+<screen>
+=# CREATE EXTENSION plperl;
+ERROR:  could not load library "/opt/dbs/pgsql/lib/plperl.so": A memory address is not in the address space for the process.
+</screen>
+    Running as a non-owner in the group possessing the PostgreSQL
+    installation:
+<screen>
+=# CREATE EXTENSION plperl;
+ERROR:  could not load library "/opt/dbs/pgsql/lib/plperl.so": Bad address
+</screen>
+     Another example is out of memory errors in the PostgreSQL server
+     logs, with every memory allocation near or greater than 256 MB
+     failing.
+    </para>
+
+    <para>
+     The overall cause of all these problems is the default bittedness
+     and memory model used by the server process.  By default, all
+     binaries built on AIX are 32-bit.  This does not depend upon
+     hardware type or kernel in use.  These 32-bit processes are
+     limited to 4 GB of memory laid out in 256 MB segments using one
+     of a few models.  The default allows for less than 256 MB in the
+     heap as it shares a single segment with the stack.
+    </para>
+
+    <para>
+     In the case of the <literal>plperl</literal> example, above,
+     check your umask and the permissions of the binaries in your
+     PostgreSQL installation.  The binaries involved in that example
+     were 32-bit and installed as mode 750 instead of 755.  Due to the
+     permissions being set in this fashion, only the owner or a member
+     of the possessing group can load the library.  Since it isn't
+     world-readable, the loader places the object into the process'
+     heap instead of the shared library segments where it would
+     otherwise be placed.
+    </para>
+
+    <para>
+     The <quote>ideal</quote> solution for this is to use a 64-bit
+     build of PostgreSQL, but that is not always practical, because
+     systems with 32-bit processors can build, but not run, 64-bit
+     binaries.
+    </para>
+
+    <para>
+     If a 32-bit binary is desired, set <symbol>LDR_CNTRL</symbol> to
+     <literal>MAXDATA=0x<replaceable>n</replaceable>0000000</literal>,
+     where 1 &lt;= n &lt;= 8, before starting the PostgreSQL server,
+     and try different values and <filename>postgresql.conf</filename>
+     settings to find a configuration that works satisfactorily.  This
+     use of <symbol>LDR_CNTRL</symbol> tells AIX that you want the
+     server to have <symbol>MAXDATA</symbol> bytes set aside for the
+     heap, allocated in 256 MB segments.  When you find a workable
+     configuration,
+     <command>ldedit</command> can be used to modify the binaries so
+     that they default to using the desired heap size.  PostgreSQL can
+     also be rebuilt, passing <literal>configure
+     LDFLAGS="-Wl,-bmaxdata:0x<replaceable>n</replaceable>0000000"</literal>
+     to achieve the same effect.
+    </para>
+
+    <para>
+     For a 64-bit build, set <envar>OBJECT_MODE</envar> to 64 and
+     pass <literal>CC="gcc -maix64"</literal>
+     and <literal>LDFLAGS="-Wl,-bbigtoc"</literal>
+     to <command>configure</command>. 
+     If you omit the export of
+    <envar>OBJECT_MODE</envar>, your build may fail with linker errors.  When
+    <envar>OBJECT_MODE</envar> is set, it tells AIX's build utilities
+    such as <command>ar</command>, <command>as</command>, and <command>ld</command> what
+    type of objects to default to handling.
+    </para>
+
+    <para>
+     By default, overcommit of paging space can happen.  While we have
+     not seen this occur, AIX will kill processes when it runs out of
+     memory and the overcommit is accessed.  The closest to this that
+     we have seen is fork failing because the system decided that
+     there was not enough memory for another process.  Like many other
+     parts of AIX, the paging space allocation method and
+     out-of-memory kill is configurable on a system- or process-wide
+     basis if this becomes a problem.
+    </para>
+   </sect3>
+  </sect2>
+
   <sect2 id="installation-notes-cygwin">
    <title>Cygwin</title>
 
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 6047b8171d..64753d9c01 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -891,6 +891,29 @@ psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: No such
 
 
     <variablelist>
+     <varlistentry>
+      <term><systemitem class="osname">AIX</systemitem>
+      <indexterm><primary>AIX</primary><secondary>IPC configuration</secondary></indexterm>
+      </term>
+      <listitem>
+       <para>
+        It should not be necessary to do
+        any special configuration for such parameters as
+        <varname>SHMMAX</varname>, as it appears this is configured to
+        allow all memory to be used as shared memory.  That is the
+        sort of configuration commonly used for other databases such
+        as <application>DB/2</application>.</para>
+
+       <para> It might, however, be necessary to modify the global
+       <command>ulimit</command> information in
+       <filename>/etc/security/limits</filename>, as the default hard
+       limits for file sizes (<varname>fsize</varname>) and numbers of
+       files (<varname>nofiles</varname>) might be too low.
+       </para>
+      </listitem>
+     </varlistentry>
+
+
      <varlistentry>
       <term><systemitem class="osname">FreeBSD</systemitem>
       <indexterm><primary>FreeBSD</primary><secondary>IPC configuration</secondary></indexterm>
diff --git a/meson.build b/meson.build
index 1c0579d5a6..f1ac154cdc 100644
--- a/meson.build
+++ b/meson.build
@@ -196,7 +196,26 @@ endif
 # that purpose.
 portname = host_system
 
-if host_system == 'cygwin'
+if host_system == 'aix'
+  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'
+
+  # M:SRE sets a flag indicating that an object is a shared library. Seems to
+  # work in some circumstances without, but required in others.
+  ldflags_sl += '-Wl,-bM:SRE'
+  ldflags_be += '-Wl,-brtllib'
+
+  # Native memset() is faster, tested on:
+  # - AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
+  # - AIX 5.3 ML3, gcc 4.0.1
+  memset_loop_limit = 0
+
+elif host_system == 'cygwin'
   sema_kind = 'unnamed_posix'
   cppflags += '-D_GNU_SOURCE'
   dlsuffix = '.dll'
@@ -1490,11 +1509,11 @@ sizeof_long = cc.sizeof('long', args: test_c_args)
 cdata.set('SIZEOF_LONG', sizeof_long)
 if sizeof_long == 8
   cdata.set('HAVE_LONG_INT_64', 1)
-  pg_int64_type = 'long int'
+  cdata.set('PG_INT64_TYPE', 'long int')
   cdata.set_quoted('INT64_MODIFIER', 'l')
 elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
   cdata.set('HAVE_LONG_LONG_INT_64', 1)
-  pg_int64_type = 'long long int'
+  cdata.set('PG_INT64_TYPE', 'long long int')
   cdata.set_quoted('INT64_MODIFIER', 'll')
 else
   error('do not know how to get a 64bit int')
@@ -1508,31 +1527,15 @@ endif
 # Determine memory alignment requirements for the basic C data types.
 
 alignof_types = ['short', 'int', 'long', 'double']
+maxalign = 0
 foreach t : alignof_types
   align = cc.alignment(t, args: test_c_args)
+  if maxalign < align
+    maxalign = align
+  endif
   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'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(pg_int64_type, args: test_c_args) > alignof_double
-  error('alignment of int64 is greater than the alignment of double')
-endif
-cdata.set('MAXIMUM_ALIGNOF', alignof_double)
+cdata.set('MAXIMUM_ALIGNOF', maxalign)
 
 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
@@ -1581,7 +1584,7 @@ if cc.links('''
   if not meson.is_cross_build()
     r = cc.run('''
     /* This must match the corresponding code in c.h: */
-    #if defined(__GNUC__) || defined(__SUNPRO_C)
+    #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
     #define pg_attribute_aligned(a) __attribute__((aligned(a)))
     #elif defined(_MSC_VER)
     #define pg_attribute_aligned(a) __declspec(align(a))
@@ -2476,6 +2479,10 @@ endif
 # conflict.
 #
 # We assume C99 support, so we don't need to make this conditional.
+#
+# XXX: Historically we allowed platforms to disable restrict in template
+# files, but that was only added for AIX when building with XLC, which we
+# don't support yet.
 cdata.set('pg_restrict', '__restrict')
 
 
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index fa81f6ffdd..8ca51ca03f 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,20 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +268,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps shared libraries inside a static library, can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +289,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +401,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +419,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 6700aec039..954b14962f 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -62,12 +62,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -94,6 +96,24 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
diff --git a/src/backend/meson.build b/src/backend/meson.build
index 436c04af08..8767aaba67 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -91,6 +91,21 @@ if cc.get_id() == 'msvc'
   # be restricted to b_pch=true.
   backend_link_with += postgres_lib
 
+elif 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
 
 backend_input = []
diff --git a/src/backend/port/aix/mkldexport.sh b/src/backend/port/aix/mkldexport.sh
new file mode 100755
index 0000000000..adf3793e86
--- /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/utils/error/elog.c b/src/backend/utils/error/elog.c
index d91a85cb2d..7b51e94f4a 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -908,7 +908,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/backend/utils/misc/ps_status.c b/src/backend/utils/misc/ps_status.c
index 9da6377402..532eac31b4 100644
--- a/src/backend/utils/misc/ps_status.c
+++ b/src/backend/utils/misc/ps_status.c
@@ -50,7 +50,7 @@ bool		update_process_title = DEFAULT_UPDATE_PROCESS_TITLE;
 #define PS_USE_SETPROCTITLE_FAST
 #elif defined(HAVE_SETPROCTITLE)
 #define PS_USE_SETPROCTITLE
-#elif defined(__linux__) || defined(__sun) || defined(__darwin__)
+#elif defined(__linux__) || defined(_AIX) || defined(__sun) || defined(__darwin__)
 #define PS_USE_CLOBBER_ARGV
 #elif defined(WIN32)
 #define PS_USE_WIN32
@@ -60,7 +60,7 @@ bool		update_process_title = DEFAULT_UPDATE_PROCESS_TITLE;
 
 
 /* Different systems want the buffer padded differently */
-#if defined(__linux__) || defined(__darwin__)
+#if defined(_AIX) || defined(__linux__) || defined(__darwin__)
 #define PS_PADDING '\0'
 #else
 #define PS_PADDING ' '
diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
index 2d4b75a6fe..ce936959c1 100644
--- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
+++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
@@ -401,7 +401,8 @@ SKIP:
 {
 	my $tar = $ENV{TAR};
 	# don't check for a working tar here, to accommodate various odd
-	# cases. If tar doesn't work the init_from_backup below will fail.
+	# cases such as AIX. If tar doesn't work the init_from_backup below
+	# will fail.
 	skip "no tar program available", 1
 	  if (!defined $tar || $tar eq '');
 
diff --git a/src/bin/pg_verifybackup/t/008_untar.pl b/src/bin/pg_verifybackup/t/008_untar.pl
index 7a09f3b75b..30d9f3f7f0 100644
--- a/src/bin/pg_verifybackup/t/008_untar.pl
+++ b/src/bin/pg_verifybackup/t/008_untar.pl
@@ -104,7 +104,8 @@ for my $tc (@test_configuration)
 		{
 			my $tar = $ENV{TAR};
 			# don't check for a working tar here, to accommodate various odd
-			# cases. If tar doesn't work the init_from_backup below will fail.
+			# cases such as AIX. If tar doesn't work the init_from_backup below
+			# will fail.
 			skip "no tar program available", 1
 			  if (!defined $tar || $tar eq '');
 
diff --git a/src/bin/pg_verifybackup/t/010_client_untar.pl b/src/bin/pg_verifybackup/t/010_client_untar.pl
index 8c076d46de..45010d79ac 100644
--- a/src/bin/pg_verifybackup/t/010_client_untar.pl
+++ b/src/bin/pg_verifybackup/t/010_client_untar.pl
@@ -134,7 +134,8 @@ for my $tc (@test_configuration)
 		{
 			my $tar = $ENV{TAR};
 			# don't check for a working tar here, to accommodate various odd
-			# cases. If tar doesn't work the init_from_backup below will fail.
+			# cases such as AIX. If tar doesn't work the init_from_backup below
+			# will fail.
 			skip "no tar program available", 1
 			  if (!defined $tar || $tar eq '');
 
diff --git a/src/include/c.h b/src/include/c.h
index dc1841346c..641cd9bdf1 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -182,7 +182,7 @@
 #define PG_USED_FOR_ASSERTS_ONLY pg_attribute_unused()
 #endif
 
-/* GCC supports format attributes */
+/* GCC support format attributes */
 #if defined(__GNUC__)
 #define pg_attribute_format_arg(a) __attribute__((format_arg(a)))
 #define pg_attribute_printf(f,a) __attribute__((format(PG_PRINTF_ATTRIBUTE, f, a)))
@@ -192,7 +192,7 @@
 #endif
 
 /* GCC and Sunpro support aligned, packed and noreturn */
-#if defined(__GNUC__) || defined(__SUNPRO_C)
+#if defined(__GNUC__) || defined(__SUNPRO_C) 
 #define pg_attribute_aligned(a) __attribute__((aligned(a)))
 #define pg_attribute_noreturn() __attribute__((noreturn))
 #define pg_attribute_packed() __attribute__((packed))
diff --git a/src/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 0000000000..1c2d166791
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,6 @@
+/*
+ * src/include/port/aix.h
+ */
+#define CLASS_CONFLICT
+#define DISABLE_XOPEN_NLS
+
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 29ac6cdcd9..2f6eb5df2a 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -424,17 +424,15 @@ tas(volatile slock_t *lock)
 	__asm__ __volatile__(
 "	lwarx   %0,0,%3,1	\n"
 "	cmpwi   %0,0		\n"
-"	bne     1f			\n"
+"	bne     $+16		\n"		/* branch to li %1,1 */
 "	addi    %0,%0,1		\n"
 "	stwcx.  %0,0,%3		\n"
-"	beq     2f			\n"
-"1: \n"
+"	beq     $+12		\n"		/* branch to lwsync */
 "	li      %1,1		\n"
-"	b       3f			\n"
-"2: \n"
+"	b       $+12		\n"		/* branch to end of asm sequence */
 "	lwsync				\n"
 "	li      %1,0		\n"
-"3: \n"
+
 :	"=&b"(_t), "=r"(_res), "+m"(*lock)
 :	"r"(lock)
 :	"memory", "cc");
@@ -662,6 +660,21 @@ tas(volatile slock_t *lock)
 
 #if !defined(HAS_TEST_AND_SET)	/* We didn't trigger above, let's try here */
 
+#if defined(_AIX)	/* AIX */
+/*
+ * AIX (POWER)
+ */
+#define HAS_TEST_AND_SET
+
+#include <sys/atomic_op.h>
+
+typedef int slock_t;
+
+#define TAS(lock)			_check_lock((slock_t *) (lock), 0, 1)
+#define S_UNLOCK(lock)		_clear_lock((slock_t *) (lock), 0)
+#endif	 /* _AIX */
+
+
 /* These are in sunstudio_(sparc|x86).s */
 
 #if defined(__SUNPRO_C) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index b36a765764..154429d4d1 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -114,7 +114,7 @@ backend_src = $(top_srcdir)/src/backend
 # coding rule.
 libpq-refs-stamp: $(shlib)
 ifneq ($(enable_coverage), yes)
-ifeq (,$(filter solaris,$(PORTNAME)))
+ifeq (,$(filter aix solaris,$(PORTNAME)))
 	@if nm -A -u $< 2>/dev/null | grep -v -e __cxa_atexit -e __tsan_func_exit | grep exit; then \
 		echo 'libpq must not be calling any function which invokes exit'; exit 1; \
 	fi
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index ed2a4048d1..7e2017daf0 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -54,8 +54,9 @@ libpq_c_args = ['-DSO_MAJOR_VERSION=5']
 #    libpq_st, and {pgport,common}_shlib for libpq_sh
 #
 # We could try to avoid building the source files twice, but it probably adds
-# more complexity than its worth (reusing object files requires also linking
-# to the library on windows or breaks precompiled headers).
+# more complexity than its worth (AIX doesn't support link_whole yet, reusing
+# object files requires also linking to the library on windows or breaks
+# precompiled headers).
 libpq_st = static_library('libpq',
   libpq_sources,
   include_directories: [libpq_inc],
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 0000000000..dd16a7a037
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,39 @@
+# MAKE_EXPORTS is required for svr4 loaders that want a file of
+# symbol names to tell them what to export/import.
+MAKE_EXPORTS= true
+
+# -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
+
+rpath = -Wl,-blibpath:'$(rpathdir)$(libpath)'
+
+LDFLAGS_SL += -Wl,-bnoentry -Wl,-H512 -Wl,-bM:SRE
+
+# 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/port/README b/src/port/README
index ed5c54a72f..97f18a6233 100644
--- a/src/port/README
+++ b/src/port/README
@@ -28,5 +28,5 @@ applications.
 from libpgport are linked first.  This avoids having applications
 dependent on symbols that are _used_ by libpq, but not intended to be
 exported by libpq.  libpq's libpgport usage changes over time, so such a
-dependency is a problem.  Windows, Linux, and macOS use an export
+dependency is a problem.  Windows, Linux, AIX, and macOS use an export
 list to control the symbols exported by libpq.
diff --git a/src/port/strerror.c b/src/port/strerror.c
index 4918ba821c..1070a49802 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,8 +214,10 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
 			return "ENOTEMPTY";
+#endif
 		case ENOTSOCK:
 			return "ENOTSOCK";
 #ifdef ENOTSUP
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 0000000000..0a788676c0
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,14 @@
+# src/template/aix
+
+  # Due to a compiler bug, see 20171013023536.GA492146@rfd.leadboat.com for details,
+  # force restrict not to be used when compiling with xlc.
+#  FORCE_DISABLE_RESTRICT=yes
+#fi
+
+# Extra CFLAGS for code that will go into a shared library
+CFLAGS_SL=""
+
+# Native memset() is faster, tested on:
+# 	AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
+# 	AIX 5.3 ML3, gcc 4.0.1
+MEMSET_LOOP_LIMIT=0
diff --git a/src/test/regress/Makefile b/src/test/regress/Makefile
index 6409a485e8..7c665ff892 100644
--- a/src/test/regress/Makefile
+++ b/src/test/regress/Makefile
@@ -7,6 +7,11 @@
 # GNU make uses a make file named "GNUmakefile" in preference to "Makefile"
 # if it exists.  Postgres is shipped with a "GNUmakefile".
 
+
+# AIX make defaults to building *every* target of the first rule.  Start with
+# a single-target, empty rule to make the other targets non-default.
+all:
+
 all install clean check installcheck:
 	@echo "You must use GNU make to use Postgres.  It may be installed"
 	@echo "on your system with the name 'gmake'."
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 8370c1561c..c5c675b750 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -25,3 +25,32 @@ SELECT relname, relkind
 ---------+---------
 (0 rows)
 
+--
+-- When ALIGNOF_DOUBLE==4 (e.g. AIX), the C ABI may impose 8-byte alignment on
+-- some of the C types that correspond to TYPALIGN_DOUBLE SQL types.  To ensure
+-- catalog C struct layout matches catalog tuple layout, arrange for the tuple
+-- offset of each fixed-width, attalign='d' catalog column to be divisible by 8
+-- unconditionally.  Keep such columns before the first NameData column of the
+-- catalog, since packagers can override NAMEDATALEN to an odd number.
+--
+WITH check_columns AS (
+ SELECT relname, attname,
+  array(
+   SELECT t.oid
+    FROM pg_type t JOIN pg_attribute pa ON t.oid = pa.atttypid
+    WHERE pa.attrelid = a.attrelid AND
+          pa.attnum > 0 AND pa.attnum < a.attnum
+    ORDER BY pa.attnum) AS coltypes
+ FROM pg_attribute a JOIN pg_class c ON c.oid = attrelid
+  JOIN pg_namespace n ON c.relnamespace = n.oid
+ WHERE attalign = 'd' AND relkind = 'r' AND
+  attnotnull AND attlen <> -1 AND n.nspname = 'pg_catalog'
+)
+SELECT relname, attname, coltypes, get_columns_length(coltypes)
+ FROM check_columns
+ WHERE get_columns_length(coltypes) % 8 != 0 OR
+       'name'::regtype::oid = ANY(coltypes);
+ relname | attname | coltypes | get_columns_length 
+---------+---------+----------+--------------------
+(0 rows)
+
diff --git a/src/test/regress/expected/test_setup.out b/src/test/regress/expected/test_setup.out
index 3d0eeec996..5d9e6bf12b 100644
--- a/src/test/regress/expected/test_setup.out
+++ b/src/test/regress/expected/test_setup.out
@@ -209,6 +209,10 @@ CREATE FUNCTION ttdummy ()
     RETURNS trigger
     AS :'regresslib'
     LANGUAGE C;
+CREATE FUNCTION get_columns_length(oid[])
+    RETURNS int
+    AS :'regresslib'
+    LANGUAGE C STRICT STABLE PARALLEL SAFE;
 -- Use hand-rolled hash functions and operator classes to get predictable
 -- result on different machines.  The hash function for int4 simply returns
 -- the sum of the values passed to it and the one for text returns the length
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index deffaea578..cc633864d7 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -1221,3 +1221,43 @@ binary_coercible(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(IsBinaryCoercible(srctype, targettype));
 }
+
+/*
+ * Return the length of the portion of a tuple consisting of the given array
+ * of data types.  The input data types must be fixed-length data types.
+ */
+PG_FUNCTION_INFO_V1(get_columns_length);
+Datum
+get_columns_length(PG_FUNCTION_ARGS)
+{
+	ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
+	Oid		   *type_oids;
+	int			ntypes;
+	int			column_offset = 0;
+
+	if (ARR_HASNULL(ta) && array_contains_nulls(ta))
+		elog(ERROR, "argument must not contain nulls");
+
+	if (ARR_NDIM(ta) > 1)
+		elog(ERROR, "argument must be empty or one-dimensional array");
+
+	type_oids = (Oid *) ARR_DATA_PTR(ta);
+	ntypes = ArrayGetNItems(ARR_NDIM(ta), ARR_DIMS(ta));
+	for (int i = 0; i < ntypes; i++)
+	{
+		Oid			typeoid = type_oids[i];
+		int16		typlen;
+		bool		typbyval;
+		char		typalign;
+
+		get_typlenbyvalalign(typeoid, &typlen, &typbyval, &typalign);
+
+		/* the data type must be fixed-length */
+		if (typlen < 0)
+			elog(ERROR, "type %u is not fixed-length data type", typeoid);
+
+		column_offset = att_align_nominal(column_offset + typlen, typalign);
+	}
+
+	PG_RETURN_INT32(column_offset);
+}
diff --git a/src/test/regress/sql/sanity_check.sql b/src/test/regress/sql/sanity_check.sql
index 162e5324b5..7f338d191c 100644
--- a/src/test/regress/sql/sanity_check.sql
+++ b/src/test/regress/sql/sanity_check.sql
@@ -19,3 +19,29 @@ SELECT relname, relkind
   FROM pg_class
  WHERE relkind IN ('v', 'c', 'f', 'p', 'I')
        AND relfilenode <> 0;
+
+--
+-- When ALIGNOF_DOUBLE==4 (e.g. AIX), the C ABI may impose 8-byte alignment on
+-- some of the C types that correspond to TYPALIGN_DOUBLE SQL types.  To ensure
+-- catalog C struct layout matches catalog tuple layout, arrange for the tuple
+-- offset of each fixed-width, attalign='d' catalog column to be divisible by 8
+-- unconditionally.  Keep such columns before the first NameData column of the
+-- catalog, since packagers can override NAMEDATALEN to an odd number.
+--
+WITH check_columns AS (
+ SELECT relname, attname,
+  array(
+   SELECT t.oid
+    FROM pg_type t JOIN pg_attribute pa ON t.oid = pa.atttypid
+    WHERE pa.attrelid = a.attrelid AND
+          pa.attnum > 0 AND pa.attnum < a.attnum
+    ORDER BY pa.attnum) AS coltypes
+ FROM pg_attribute a JOIN pg_class c ON c.oid = attrelid
+  JOIN pg_namespace n ON c.relnamespace = n.oid
+ WHERE attalign = 'd' AND relkind = 'r' AND
+  attnotnull AND attlen <> -1 AND n.nspname = 'pg_catalog'
+)
+SELECT relname, attname, coltypes, get_columns_length(coltypes)
+ FROM check_columns
+ WHERE get_columns_length(coltypes) % 8 != 0 OR
+       'name'::regtype::oid = ANY(coltypes);
diff --git a/src/test/regress/sql/test_setup.sql b/src/test/regress/sql/test_setup.sql
index 06b0e2121f..1b2d434683 100644
--- a/src/test/regress/sql/test_setup.sql
+++ b/src/test/regress/sql/test_setup.sql
@@ -257,6 +257,11 @@ CREATE FUNCTION ttdummy ()
     AS :'regresslib'
     LANGUAGE C;
 
+CREATE FUNCTION get_columns_length(oid[])
+    RETURNS int
+    AS :'regresslib'
+    LANGUAGE C STRICT STABLE PARALLEL SAFE;
+
 -- Use hand-rolled hash functions and operator classes to get predictable
 -- result on different machines.  The hash function for int4 simply returns
 -- the sum of the values passed to it and the one for text returns the length
diff --git a/src/tools/gen_export.pl b/src/tools/gen_export.pl
index d9fdaaaf6d..888c8a197a 100644
--- a/src/tools/gen_export.pl
+++ b/src/tools/gen_export.pl
@@ -16,11 +16,12 @@ GetOptions(
 	'input:s' => \$input,
 	'output:s' => \$output) or die "wrong arguments";
 
-if (not(   $format eq 'darwin'
+if (not(   $format eq 'aix'
+		or $format eq 'darwin'
 		or $format eq 'gnu'
 		or $format eq 'win'))
 {
-	die "$0: $format is not yet handled (only darwin, gnu, win are)\n";
+	die "$0: $format is not yet handled (only aix, darwin, gnu, win are)\n";
 }
 
 open(my $input_handle, '<', $input)
@@ -55,7 +56,11 @@ while (<$input_handle>)
 	}
 	elsif (/^(\S+)\s+(\S+)/)
 	{
-		if ($format eq 'darwin')
+		if ($format eq 'aix')
+		{
+			print $output_handle "$1\n";
+		}
+		elsif ($format eq 'darwin')
 		{
 			print $output_handle "_$1\n";
 		}
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 4a157d0a5f..cfd8c6896c 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -85,6 +85,7 @@ do
 
 	# These files are platform-specific, and c.h will include the
 	# one that's relevant for our current platform anyway.
+	test "$f" = src/include/port/aix.h && continue
 	test "$f" = src/include/port/cygwin.h && continue
 	test "$f" = src/include/port/darwin.h && continue
 	test "$f" = src/include/port/freebsd.h && continue
-- 
2.41.0

0001-Replace-tas-asm-with-gcc-routines-for-powerPC-implem.patchapplication/octet-stream; name=0001-Replace-tas-asm-with-gcc-routines-for-powerPC-implem.patchDownload
From a08fbe47316034c458fcfb748efd7caabad9893f Mon Sep 17 00:00:00 2001
From: Sriram RK <sriram.rk@in.ibm.com>
Date: Tue, 24 Sep 2024 05:04:51 -0500
Subject: [PATCH 1/1] Replace tas() asm with gcc routines for powerPC
 implementaion in s_lock.h .

---
 src/include/storage/s_lock.h | 43 ++++--------------------------------
 1 file changed, 4 insertions(+), 39 deletions(-)

diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 2f6eb5df2a..c0cc7bd38b 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -401,54 +401,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 gcc atomic routines, to set the lock. */
 #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     $+16		\n"		/* branch to li %1,1 */
-"	addi    %0,%0,1		\n"
-"	stwcx.  %0,0,%3		\n"
-"	beq     $+12		\n"		/* branch to lwsync */
-"	li      %1,1		\n"
-"	b       $+12		\n"		/* branch to end of asm sequence */
-"	lwsync				\n"
-"	li      %1,0		\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.
+ * PowerPC S_UNLOCK use the gcc atomic routines. 
  */
-#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 */
 
-- 
2.41.0

#66Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Srirama Kucherlapati (#65)
Re: AIX support

On 24/09/2024 14:25, Srirama Kucherlapati wrote:

Hi Heikki & team,

Could you please let me know your comments on the previous details?

Attached are the individual patches for AIX and gcc(__sync) routines.

Repeating what I said earlier:

Ok, if we don't need the assembler code at all, that's good. A patch
to introduce AIX support should not change it for non-AIX powerpc
systems though. That might be a good change, but would need to be
justified separately, e.g. by some performance testing, and should
be a separate patch

--
Heikki Linnakangas
Neon (https://neon.tech)

#67Bruce Momjian
bruce@momjian.us
In reply to: Heikki Linnakangas (#66)
Re: AIX support

On Tue, Sep 24, 2024 at 04:09:39PM +0300, Heikki Linnakangas wrote:

On 24/09/2024 14:25, Srirama Kucherlapati wrote:

Hi Heikki & team,

Could you please let me know your comments on the previous details?

Attached are the individual patches for AIX and gcc(__sync) routines.

Repeating what I said earlier:

Ok, if we don't need the assembler code at all, that's good. A patch
to introduce AIX support should not change it for non-AIX powerpc
systems though. That might be a good change, but would need to be
justified separately, e.g. by some performance testing, and should
be a separate patch

Agreed. Srirama Kucherlapati, you seem to be doing the minimum amount
of work and then repeatedly asking the same questions. I suggest you
start to take this task more seriously. I would go back and read the
entire thread, and take the things we have told you more seriously.

--
Bruce Momjian <bruce@momjian.us> https://momjian.us
EDB https://enterprisedb.com

When a patient asks the doctor, "Am I going to die?", he means
"Am I going to die soon?"

#68Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Heikki Linnakangas (#66)
RE: AIX support

Hi Heikki,

As requested earlier, I need some assistance from the Postgres side to identify any tool or testcase to calibrate the sync routine performance in Postgres.
I see the below tools for benchmarking.

* Pgbench https://www.postgresql.org/docs/current/pgbench.html
* Pg_test_fsync https://www.postgresql.org/docs/current/pgtestfsync.html
* pg_test_timing https://www.postgresql.org/docs/current/pgtesttiming.html

Please let me know, if these tools are fine or else ca you suggest us with any additional tools to run the benchmarking.

Ok, if we don't need the assembler code at all, that's good. A patch to
introduce AIX support should not change it for non-AIX powerpc systems
though. That might be a good change, but would need to be justified
separately, e.g. by some performance testing, and should be a separate
patch.

If you make no changes to s_lock.h at all, will it work? Why not?

With the existing asm code I see there are some syntax errors, being hit.
But after reverting the old changes the issues resolved. Below are diffs.

Let me know if I need to run any perf tools to check the performance of
the __sync_lock_test_and_set change.

Thanks,
Sriram.

#69Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#68)
RE: AIX support

Hi Heikki and team,

A few updates…

Ok, if we don't need the assembler code at all, that's good. A patch to
introduce AIX support should not change it for non-AIX powerpc systems
though. That might be a good change, but would need to be justified
separately, e.g. by some performance testing, and should be a separate
patch.

We ran pgbench for both the patches on powerpc Linux and below are the test
results and both results are close.

PPCLE sync: is the patch with the spin lock using gcc __sync* routines.
PPCLE asm: is the patch with the assemble code.

pgbench -c 100 -p 5432 -d postgres -T 180 -r -P 10 -L 10 -j 20

OS/type : PPCLE sync PPCLE asm
---------------------------------------------------------
latency average : 136.257 138.552
---------------------------------------------------------
latency stddev : 234.74 238.603
---------------------------------------------------------
Initial
connection time : 101.791 88.411
---------------------------------------------------------
TPS(without initial
connection time) : 733.633924 721.440648
---------------------------------------------------------
No. of transactions
actually processed : 132080 129893
---------------------------------------------------------
No of transactions
above the 10.0 ms
latency limit : 124235/132080 122183/129893
(94.060%) (94.064%)
---------------------------------------------------------

Please let us know your comments.
BTW we are working on the other review comments as well.

Warm regards,
Sriram.

#70Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#69)
RE: AIX support

Hi Team, here are few updates.

As of now we have removed all the old changes and made the changes that are
pretty much required by building from scratch. We had few issues with our
hardware as a result it took a while to build the code.

Below are the changes done as of now.

commit d2b4b4c2259e21ceaf05e393769b69728bfbee99 (HEAD -> master, origin/master, origin/HEAD)

git status

On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: src/backend/port/aix/mkldexport.sh
new file: src/include/port/aix.h
new file: src/makefiles/Makefile.aix
new file: src/template/aix

Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: Makefile
modified: configure
modified: doc/src/sgml/dfunc.sgml
modified: src/Makefile.shlib
modified: src/backend/Makefile
modified: src/backend/port/aix/mkldexport.sh
modified: src/backend/utils/error/elog.c
modified: src/include/storage/s_lock.h
modified: src/port/strerror.c
modified: src/test/regress/expected/jsonb_jsonpath.out

We are seeing this one issue as of now with ‘gmake check’…

1 diff -U3 /home /postgres/src/test/regress/expected/jsonb_jsonpath.out /home/ /postgres/src/test/regress/results/jsonb_jsonpath.out
2 --- /home /postgres/src/test/regress/expected/jsonb_jsonpath.out 2024-10-22 02:30:00.545814423 -0500
3 +++ /home/ postgres/src/test/regress/results/jsonb_jsonpath.out 2024-11-12 03:31:52.251125056 -0600
4 @@ -2687,7 +2687,7 @@
5 select jsonb_path_query_tz('"12:34:56"', '$.time_tz().string()');
6 jsonb_path_query_tz
7 ---------------------
8 - "12:34:56-07:00"
9 + "12:34:56-08:00"
10 (1 row)
11
12 select jsonb_path_query('"12:34:56"', '$.time().string()');

After modifying the expected output for this testcase as below, the issue was
resolved and the test case passed. But we are trying to see the root cause of this.
"12:34:56-08:00"

We are working on the buildfarm setup to check the actual tests.

I shall keep you posted.

Warm regards,
Sriram.

#71Robert Haas
robertmhaas@gmail.com
In reply to: Srirama Kucherlapati (#70)
Re: AIX support

On Mon, Nov 25, 2024 at 11:27 AM Srirama Kucherlapati
<sriram.rk@in.ibm.com> wrote:

After modifying the expected output for this testcase as below, the issue was
resolved and the test case passed. But we are trying to see the root cause of this.

"12:34:56-08:00"

This is not an AIX-specific issue. It was fixed in commit
af21152268317323480caa790c4a6347110f8085, committed October 30th.

--
Robert Haas
EDB: http://www.enterprisedb.com

#72Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Robert Haas (#71)
RE: AIX support

This is not an AIX-specific issue. It was fixed in commit
af21152268317323480caa790c4a6347110f8085, committed October 30th.

Thanks Robert, it worked after applying this change.

Warm regards,
Sriram.

#73Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#72)
RE: AIX support

Hi Team, few more updates on the buildfarm, all the tests have passed and below
is the gist of the logs. We are working on the cleaning up the changes and will
post them for review.

Tue Dec 3 04:08:29 2024: buildfarm run for CHANGEME:HEAD starting
CHANGEME:HEAD [04:09:49] running build ...
======== make log ===========
CHANGEME:HEAD [04:09:54] running basic regression tests ...
======== make check logs ===========
CHANGEME:HEAD [04:19:47] running make contrib ...
======== make contrib log ===========
CHANGEME:HEAD [04:19:48] running make testmodules ...
======== make testmodules log ===========
CHANGEME:HEAD [04:19:49] running install ...
======== make install log ===========
CHANGEME:HEAD [04:20:51] running make contrib install ...
======== make contrib install log ===========
CHANGEME:HEAD [04:21:20] running testmodules install ...
======== testmodules install log ===========
CHANGEME:HEAD [04:21:33] checking pg_upgrade
======== pg_upgrade check log ===========
CHANGEME:HEAD [04:21:33] checking test-decoding
======== test-decoding check log ===========
========================== output_iso/log/initdb.log ================
========================== output_iso/log/postmaster.log ================
========================== test_decoding/log/initdb.log ================
========================== test_decoding/log/postmaster.log ================
CHANGEME:HEAD [04:23:40] running make check miscellaneous modules ...
=========== Module commit_ts check =============
=========== Module injection_points check =============
=========== Module test_oat_hooks check =============
=========== Module test_slru check =============
=========== Module unsafe_tests check =============
=========== Module basic_archive check =============
=========== Module pg_freespacemap check =============
=========== Module pg_logicalinspect check =============
=========== Module pg_stat_statements check =============
=========== Module pg_walinspect check =============
=========== Module test_decoding check =============
CHANGEME:HEAD [04:31:54] setting up db cluster (C)...
======== initdb log (C) ===========
CHANGEME:HEAD [04:32:13] starting db (C)...
======== start db (C) : 1 log ========
=========== db log file ==========
CHANGEME:HEAD [04:32:14] running installcheck (C)...
======== make installcheck log ===========
CHANGEME:HEAD [04:44:14] restarting db (C)...
======== stop db (C): 1 log ==========
=========== db log file ==========
======== start db (C) : 2 log ========
=========== db log file ==========
CHANGEME:HEAD [04:44:16] running make isolation check ...
======== make isolation check logs ===========
CHANGEME:HEAD [04:48:22] restarting db (C)...
======== stop db (C): 2 log ==========
=========== db log file ==========
======== start db (C) : 3 log ========
=========== db log file ==========
CHANGEME:HEAD [04:49:24] running make PL installcheck (C)...
======== make pl installcheck log ===========
CHANGEME:HEAD [04:49:44] restarting db (C)...
======== stop db (C): 3 log ==========
=========== db log file ==========
======== start db (C) : 4 log ========
=========== db log file ==========
CHANGEME:HEAD [04:49:47] running make contrib installcheck (C)...
======== make contrib installcheck log ===========
CHANGEME:HEAD [04:55:01] restarting db (C)...
======== stop db (C): 4 log ==========
=========== db log file ==========
======== start db (C) : 5 log ========
=========== db log file ==========
CHANGEME:HEAD [04:55:09] running make test-modules installcheck (C)...
======== make testmodules installcheck log ===========
CHANGEME:HEAD [04:56:54] stopping db (C)...
======== stop db (C): 5 log ==========
=========== db log file ==========
CHANGEME:HEAD [04:56:57] running make ecpg check ...
======== make ecpg check logs ===========
CHANGEME:HEAD [04:58:38] OK
======== log passed to send_result ===========

======== log passed to send_result ===========
All stages succeeded

Generated logs files

aixpg-lpar01:~/build-farm-17/buildroot/HEAD/CHANGEME.fromsource-logs]

ls

build.log pl-install-check-C.log
check-pg_upgrade.log startdb-C-1.log
check.log startdb-C-2.log
configure.log startdb-C-3.log
contrib-install-check-C.log startdb-C-4.log
ecpg-check.log startdb-C-5.log
initdb-C.log stopdb-C-1.log
install-check-C.log stopdb-C-2.log
install-contrib.log stopdb-C-3.log
install-testmodules.log stopdb-C-4.log
isolation-check.log stopdb-C-5.log
make-contrib.log test-decoding-check.log
make-install.log testmodules-install-check-C.log
make-testmodules.log web-txn.data
misc-check.log

Warm regards,
Sriram.

#74Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#73)
1 attachment(s)
RE: AIX support

Hello Team,
In response to our previous discussions, we have refined the code to address
only the necessary adjustments focusing solely on the essential modifications
for AIX compatibility. The codebase was pulled from the GitHub repository
(https://github.com/postgres/postgres.git) and we resolved all issues
encountered during the configure and build processes. The following are the
minimal alterations needed to ensure AIX is supported.

Overview of Changes
We consulted with internal teams (GCC/Linker and Open Source) for each
modification. Details of the changes for the relevant files are as follows:

- configure:
- Addressed AIX-specific alignment issues to support MAXALIGN_ALIGNOF.
- Added comments regarding AIX alignment rules in the file.
- doc/src/sgml/dfunc.sgml:
- Updated related documentation.
- Shared Libraries Build Process:
- Files Affected:
src/Makefile.shlib
src/backend/Makefile
- src/backend/port/aix/mkldexport.sh
- Implemented AIX-specific changes for shared library creation using export
files.
- As per discussions with the linker team, the current design mandates using
the script method to extract symbols and build shared libraries.
- This approach aligns with practices in other open-source projects like
Python, OpenBLAS and other gnu tools(references, link).

https://github.com/python/cpython/blob/main/Modules/ld_so_aix.in

https://github.com/OpenMathLib/OpenBLAS/commit/892f8ff3e55e24fda9af3f6364319cce3f60116b#diff-4011a114c75fe804332139868806cbe23f275963e4e6afa9b57e51b2b9817293R261

- Platform-Specific Updates:
- src/backend/utils/error/elog.c & src/port/strerror.c: Resolved macro
conflict where ENOTEMPTY and EEXIST have the same value.
- src/include/port/aix.h: Added platform-specific header to address
compilation errors.
- src/makefiles/Makefile.aix: Introduced AIX-specific makefile for building.
- src/template/aix: Defined memset flags for AIX.
- Lock Implementation:
- src/include/storage/s_lock.h:
Retained the tas() definition in assembly for now. Testing is ongoing to
replace it with __sync_lock_test_and_set() for benchmarking on both AIX and
PPCle platforms. A separate patch will address this in the future.

- IGNORE: known issue resolved in af21152268317323480
- src/test/regress/expected/jsonb_jsonpath.out
- src/test/regress/sql/jsonb_jsonpath.sql

Testing and Results
We built the code using GCC 12.0, which includes fixes for the memory alignment
issue in AIX. Testing was conducted on the following hardware:
- Hardware: POWER9 machine with 8 CPUs (64-bit registers).
- OS: AIX 7.3 TL3 (7300-03) Latest GA 2024.

Buildfarm Tests: All tests passed.
Performance Benchmark (pgbench):

./bin/pgbench -c 100 -p 5678 -d postgres -T 180 -r -P 10 -L 10 -j 20

scaling factor: 50
query mode: simple
number of clients: 100
number of threads: 20
maximum number of tries: 1
duration: 180 s
number of transactions actually processed: 69978
number of failed transactions: 0 (0.000%)
number of transactions above the 10.0 ms latency limit: 69977/69978 (99.999%)
latency average = 257.223 ms
latency stddev = 3000.532 ms
initial connection time = 366.422 ms
tps = 387.366846 (without initial connection time)
statement latencies in milliseconds and failures:
0.003 0 \set aid random(1, 100000 * :scale)
0.002 0 \set bid random(1, 1 * :scale)
0.002 0 \set tid random(1, 10 * :scale)
0.002 0 \set delta random(-5000, 5000)
1.016 0 BEGIN;
121.947 0 UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
18.406 0 SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
9.764 0 UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
50.664 0 UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
1.044 0 INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
54.844 0 END;

The changes have been carefully reviewed, tested, and aligned with the
requirements for AIX. If you have any additional feedback or concerns,
please let us know.

Warm regards,
Sriram.

Attachments:

0001-AIX-support-v6.patchapplication/octet-stream; name=0001-AIX-support-v6.patchDownload
From 103760b2d065081447efd27f4ecc20c5dbb7abcf Mon Sep 17 00:00:00 2001
From: Sriram RK <sriram.rk@in.ibm.com>
Date: Fri, 6 Dec 2024 10:36:29 -0600
Subject: [PATCH] AIX support

---
 Makefile                                     |  2 -
 configure                                    | 35 +++++++++--
 doc/src/sgml/dfunc.sgml                      | 19 ++++++
 src/Makefile.shlib                           | 29 ++++++++++
 src/backend/Makefile                         | 20 +++++++
 src/backend/port/aix/mkldexport.sh           | 61 ++++++++++++++++++++
 src/backend/utils/error/elog.c               |  2 +
 src/include/port/aix.h                       |  4 ++
 src/include/storage/s_lock.h                 | 10 ++--
 src/makefiles/Makefile.aix                   | 39 +++++++++++++
 src/port/strerror.c                          |  2 +
 src/template/aix                             |  7 +++
 src/test/regress/expected/jsonb_jsonpath.out |  6 +-           << IGNORE: known issue resolved in af21152268317323480
 src/test/regress/sql/jsonb_jsonpath.sql      |  4 ++           << IGNORE: known issue resolved in af21152268317323480
 14 files changed, 225 insertions(+), 15 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 create mode 100644 src/include/port/aix.h
 create mode 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index 8a2ec9396b..9bc1a4ec17 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/configure b/configure
index 3a577e463b..0f400c4e84 100755
--- a/configure
+++ b/configure
@@ -2985,6 +2985,7 @@ else
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -16769,13 +16770,35 @@ _ACEOF
 # 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 "$PORTNAME" != "aix"; then
+    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 x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
+      as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# AIX alignment info: We assume long's alignment is at least as strong as char, short, or
+# int; but we must check long long (if it is being used for int64) and double.
+#
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# 
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+    fi
+    if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $MAX_ALIGNOF -lt $ac_cv_alignof_long_long_int ; then
+      MAX_ALIGNOF="$ac_cv_alignof_long_long_int"
+    fi
 
-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 x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
 fi
 
 cat >>confdefs.h <<_ACEOF
diff --git a/doc/src/sgml/dfunc.sgml b/doc/src/sgml/dfunc.sgml
index b94aefcd0c..554f9fac4c 100644
--- a/doc/src/sgml/dfunc.sgml
+++ b/doc/src/sgml/dfunc.sgml
@@ -202,4 +202,23 @@ gcc -G -o foo.so foo.o
   server expects to find the shared library files.
  </para>
 
+<!--
+Under AIX, object files are compiled normally but building the shared
+library requires a couple of steps.  First, create the object file:
+.nf
+cc <other flags> -c foo.c
+.fi
+You must then create a symbol \*(lqexports\*(rq file for the object
+file:
+.nf
+mkldexport foo.o `pwd` &gt; foo.exp
+.fi
+Finally, you can create the shared library:
+.nf
+ld <other flags> -H512 -T512 -o foo.so -e _nostart \e
+   -bI:.../lib/postgres.exp -bE:foo.exp foo.o \e
+   -lm -lc 2>/dev/null
+.fi
+  -->
+
 </sect2>
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index fa81f6ffdd..13ea84ac18 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,20 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +268,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps both shared libraries and static library, which can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +289,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +401,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +419,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 84302cc6da..a37f6198ed 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -62,12 +62,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -94,6 +96,24 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
diff --git a/src/backend/port/aix/mkldexport.sh b/src/backend/port/aix/mkldexport.sh
new file mode 100755
index 0000000000..adf3793e86
--- /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/utils/error/elog.c b/src/backend/utils/error/elog.c
index 8acca3e0a0..54c3446c66 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -904,7 +904,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/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 0000000000..7d08480c8c
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,4 @@
+/*
+ * src/include/port/aix.h
+ */
+
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index e94ed5f48b..17a2ee0973 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -415,17 +415,15 @@ tas(volatile slock_t *lock)
 	__asm__ __volatile__(
 "	lwarx   %0,0,%3,1	\n"
 "	cmpwi   %0,0		\n"
-"	bne     1f			\n"
+"	bne     $+16		\n"		/* branch to li %1,1 */
 "	addi    %0,%0,1		\n"
 "	stwcx.  %0,0,%3		\n"
-"	beq     2f			\n"
-"1: \n"
+"	beq     $+12		\n"		/* branch to lwsync */
 "	li      %1,1		\n"
-"	b       3f			\n"
-"2: \n"
+"	b       $+12		\n"		/* branch to end of asm sequence */
 "	lwsync				\n"
 "	li      %1,0		\n"
-"3: \n"
+
 :	"=&b"(_t), "=r"(_res), "+m"(*lock)
 :	"r"(lock)
 :	"memory", "cc");
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 0000000000..dd16a7a037
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,39 @@
+# MAKE_EXPORTS is required for svr4 loaders that want a file of
+# symbol names to tell them what to export/import.
+MAKE_EXPORTS= true
+
+# -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
+
+rpath = -Wl,-blibpath:'$(rpathdir)$(libpath)'
+
+LDFLAGS_SL += -Wl,-bnoentry -Wl,-H512 -Wl,-bM:SRE
+
+# 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/port/strerror.c b/src/port/strerror.c
index 4918ba821c..1070a49802 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,8 +214,10 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
 			return "ENOTEMPTY";
+#endif
 		case ENOTSOCK:
 			return "ENOTSOCK";
 #ifdef ENOTSUP
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 0000000000..48a3ce55cf
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,7 @@
+# src/template/aix
+
+# Extra CFLAGS for code that will go into a shared library
+CFLAGS_SL=""
+
+# Native memset() is faster.
+MEMSET_LOOP_LIMIT=0
diff --git a/src/test/regress/expected/jsonb_jsonpath.out b/src/test/regress/expected/jsonb_jsonpath.out
index acdf7e436f..4bcd4e91a2 100644
--- a/src/test/regress/expected/jsonb_jsonpath.out
+++ b/src/test/regress/expected/jsonb_jsonpath.out
@@ -2684,12 +2684,16 @@ select jsonb_path_query('"12:34:56 +5:30"', '$.time_tz().string()');
  "12:34:56+05:30"
 (1 row)
 
+-- this timetz usage will absorb the UTC offset of the current timezone setting
+begin;
+set local timezone = 'UTC-10';
 select jsonb_path_query_tz('"12:34:56"', '$.time_tz().string()');
  jsonb_path_query_tz 
 ---------------------
- "12:34:56-07:00"
+ "12:34:56+10:00"
 (1 row)
 
+rollback;
 select jsonb_path_query('"12:34:56"', '$.time().string()');
  jsonb_path_query 
 ------------------
diff --git a/src/test/regress/sql/jsonb_jsonpath.sql b/src/test/regress/sql/jsonb_jsonpath.sql
index da3f7969ca..3e8929a526 100644
--- a/src/test/regress/sql/jsonb_jsonpath.sql
+++ b/src/test/regress/sql/jsonb_jsonpath.sql
@@ -607,7 +607,11 @@ select jsonb_path_query_tz('"2023-08-15 12:34:56"', '$.timestamp_tz().string()')
 select jsonb_path_query('"2023-08-15 12:34:56 +5:30"', '$.timestamp_tz().string()');
 select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp().string()');
 select jsonb_path_query('"12:34:56 +5:30"', '$.time_tz().string()');
+-- this timetz usage will absorb the UTC offset of the current timezone setting
+begin;
+set local timezone = 'UTC-10';
 select jsonb_path_query_tz('"12:34:56"', '$.time_tz().string()');
+rollback;
 select jsonb_path_query('"12:34:56"', '$.time().string()');
 select jsonb_path_query('"2023-08-15"', '$.date().string()');
 
-- 
2.41.0

#75Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Srirama Kucherlapati (#74)
Re: AIX support

On 23/12/2024 17:55, Srirama Kucherlapati wrote:

Hello Team,

In response to our previous discussions, we have refined the code to address

only the necessary adjustments focusing solely on the essential
modifications

for AIX compatibility. The codebase was pulled from the GitHub repository

(https://github.com/postgres/postgres.git <https://github.com/postgres/
postgres.git>) and we resolved all issues

encountered during the configure and build processes. The following are the

minimal alterations needed to ensure AIX is supported.

Thanks, getting better.

Please generate the patches against 'master', rather than v17. We might
choose to backport this to v17 later, but let's focus on the current
development branch for now.

Overview of Changes

We consulted with internal teams (GCC/Linker and Open Source) for each

modification. Details of the changes for the relevant files are as follows:

- configure:

  - Addressed AIX-specific alignment issues to support MAXALIGN_ALIGNOF.

  - Added comments regarding AIX alignment rules in the file.

The patch modifies 'configure', but that file is generated from
'configure.ac'. Please show the changes to 'configure.ac'

Please also update the meson build system accordingly.

+# AIX alignment info: We assume long's alignment is at least as strong as char, short, or
+# int; but we must check long long (if it is being used for int64) and double.
+#
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# 
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.

I don't quite understand this comment. Maybe some rephrasing or examples
would help.

What is an aggregate in this context? A struct or union?

We use C99 int64_t for the int64 datatype nowadays, not "long long", so
this seems a little outdated. (Since commit 962da900ac)

- doc/src/sgml/dfunc.sgml:

  - Updated related documentation.

diff --git a/doc/src/sgml/dfunc.sgml b/doc/src/sgml/dfunc.sgml
index b94aefcd0c..554f9fac4c 100644
--- a/doc/src/sgml/dfunc.sgml
+++ b/doc/src/sgml/dfunc.sgml
@@ -202,4 +202,23 @@ gcc -G -o foo.so foo.o
server expects to find the shared library files.
</para>
+<!--
+Under AIX, object files are compiled normally but building the shared
+library requires a couple of steps.  First, create the object file:
+.nf
+cc <other flags> -c foo.c
+.fi
+You must then create a symbol \*(lqexports\*(rq file for the object
+file:
+.nf
+mkldexport foo.o `pwd` &gt; foo.exp
+.fi
+Finally, you can create the shared library:
+.nf
+ld <other flags> -H512 -T512 -o foo.so -e _nostart \e
+   -bI:.../lib/postgres.exp -bE:foo.exp foo.o \e
+   -lm -lc 2>/dev/null
+.fi
+  -->
+
</sect2>

Why is this commented out?

You say "updated related documentation", but these instructions were
first added to the tree in year 1999, in commit f2f43efbe1, which
apparently copied them from old man pages. Are they still current and
relevant?

- Shared Libraries Build Process:

  - Files Affected:

    src/Makefile.shlib

    src/backend/Makefile

- src/backend/port/aix/mkldexport.sh

  - Implemented AIX-specific changes for shared library creation using
export

    files.

  - As per discussions with the linker team, the current design
mandates using

    the script method to extract symbols and build shared libraries.

  - This approach aligns with practices in other open-source projects like

    Python, OpenBLAS and other gnu tools(references, link).

https://github.com/python/cpython/blob/main/Modules/ld_so_aix.in
<https://github.com/python/cpython/blob/main/Modules/ld_so_aix.in&gt;

https://github.com/OpenMathLib/OpenBLAS/
commit/892f8ff3e55e24fda9af3f6364319cce3f60116b#diff-4011a114c75fe804332139868806cbe23f275963e4e6afa9b57e51b2b9817293R261 <https://github.com/OpenMathLib/OpenBLAS/commit/892f8ff3e55e24fda9af3f6364319cce3f60116b#diff-4011a114c75fe804332139868806cbe23f275963e4e6afa9b57e51b2b9817293R261&gt;

Thanks for the links. It's disappointing there isn't a standard way to
do this. It's nice to see the comments in cpython's makeexp_aix script
explaining the "hidden tricks". I'd love to see similar comments in
mkldexport.sh explaining what it does. And also why the script is needed
on AIX in the first place.

I wonder if meson's AIX support would have something built-in to do this?

  - src/makefiles/Makefile.aix: Introduced AIX-specific makefile for
building.

+# 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
+
+rpath = -Wl,-blibpath:'$(rpathdir)$(libpath)'

Is this still needed? I have no idea, but it seems surprising if gcc and
ld don't handle this automatically.

+LDFLAGS_SL += -Wl,-bnoentry -Wl,-H512 -Wl,-bM:SRE

What do all these options do? Why are they needed?

  - src/template/aix: Defined memset flags for AIX.

Why? Did you benchmark it? How big is the difference?

I don't know if the default we have for MEMSET_LOOP_LIMIT is any good on
modern compilers and systems in general. Perhaps we should just always
use the system memset(). So for this patch, e key question is whether
there's something AIX specific here. I'd assume no. I'd assume it to
depend on the hardware rather than the OS.

--
Heikki Linnakangas
Neon (https://neon.tech)

#76Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Heikki Linnakangas (#75)
RE: AIX support

Hi Heikki, Thanks for your feedback.

Please generate the patches against 'master', rather than v17. We might
choose to backport this to v17 later, but let's focus on the current
development branch for now.

All the changes were made on top of master(development) branch pulled from github repository. Below is the log info.
I’ll pull the latest master and apply the changes for the next patch.

github repository: https://github.com/postgres/postgres.git

commit 103760b2d065081447efd27f4ecc20c5dbb7abcf (HEAD -> aixSupport)
Author: Sriram RK sriram.rk@in.ibm.com<mailto:sriram.rk@in.ibm.com>
Date: Fri Dec 6 10:36:29 2024 -0600

AIX support

commit d2b4b4c2259e21ceaf05e393769b69728bfbee99 (origin/master, origin/HEAD, gitibm/master, master)
Author: Peter Eisentraut peter@eisentraut.org<mailto:peter@eisentraut.org>
Date: Tue Oct 22 08:12:43 2024 +0200

Fix C23 compiler warning

commit 45e0ba30fc40581f320fac17ad8b4e0676e1b3b5
Author: Michael Paquier michael@paquier.xyz<mailto:michael@paquier.xyz>
Date: Tue Oct 22 13:05:51 2024 +0900

pg_stat_statements: Add tests for nested queries with level tracking

I shall continue to work on the other comments and will keep you posted.

Warm regards,
Sriram.

#77Peter Eisentraut
peter@eisentraut.org
In reply to: Heikki Linnakangas (#75)
Re: AIX support

On 25.12.24 11:22, Heikki Linnakangas wrote:

Thanks for the links. It's disappointing there isn't a standard way to
do this. It's nice to see the comments in cpython's makeexp_aix script
explaining the "hidden tricks". I'd love to see similar comments in
mkldexport.sh explaining what it does. And also why the script is needed
on AIX in the first place.

I wonder if meson's AIX support would have something built-in to do this?

Meson appears to have AIX support, so it's worth trying out. If it's
working, then it would also be worth considering a meson-only AIX port,
which might be much simpler. Conversely, if it doesn't work at all, it
would need to be fixed. I don't think we'd want to accept a new port
that doesn't work with meson.

#78Andres Freund
andres@anarazel.de
In reply to: Peter Eisentraut (#77)
Re: AIX support

Hi,

On December 30, 2024 10:29:53 AM GMT+01:00, Peter Eisentraut <peter@eisentraut.org> wrote:

On 25.12.24 11:22, Heikki Linnakangas wrote:

Thanks for the links. It's disappointing there isn't a standard way to do this. It's nice to see the comments in cpython's makeexp_aix script explaining the "hidden tricks". I'd love to see similar comments in mkldexport.sh explaining what it does. And also why the script is needed on AIX in the first place.

I wonder if meson's AIX support would have something built-in to do this?

Meson appears to have AIX support, so it's worth trying out. If it's working, then it would also be worth considering a meson-only AIX port, which might be much simpler. Conversely, if it doesn't work at all, it would need to be fixed. I don't think we'd want to accept a new port that doesn't work with meson.

Before the removal PG passed tests on AIX, when built with meson. IIRC it shared the annoying symbol handling script with autoconf though.

Andres
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.

#79Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Peter Eisentraut (#77)
RE: AIX support

Meson appears to have AIX support, so it's worth trying out.

Right, meson is supported on AIX, we have meson in our AIX toolbox.
We are trying to build with meson as well. I shall update you.

BTW, I would like to wish the entire Postgres community a Happy new year.

Warm regards,
Sriram.

#80Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Heikki Linnakangas (#75)
RE: AIX support

Hi Team,
A few updates regarding the meson build.

We have successfully resolved issues with the meson build on AIX, allowing the meson configure and build to succeed.
A problem was addressed in the meson script wrt AIX (to build a nested shared libraries), specifically in the symbolextractor.py file. The fix has been implemented and will be submitted to the meson community.

https://github.com/mesonbuild/meson/blob/07f595fa98087352940121c87ba9aca0ebc95996/mesonbuild/scripts/symbolextractor.py#L4

Currently, we are verifying the test results.

Warm regards,
Sriram.

#81Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#80)
RE: AIX support

Hi Team,
Our team has identified couple of issues with the meson build on AIX, primarily focusing on the following areas:

1. Symbol extraction and resolution in object files during binary creation.
2. Dynamic runtime library path resolution in shared libraries.
We have resolved them and we plan to submit these fixes to the meson community shortly.

In addition, we are actively working on resolving other test issues. I will provide you with updates once these problems have been resolved.

92/301 postgresql:regress / regress/regress
# 4 of 223 tests failed.

Warm regards,
Sriram.

#82Robert Haas
robertmhaas@gmail.com
In reply to: Srirama Kucherlapati (#81)
Re: AIX support

On Fri, Mar 7, 2025 at 9:11 AM Srirama Kucherlapati
<sriram.rk@in.ibm.com> wrote:

Our team has identified couple of issues with the meson build on AIX, primarily focusing on the following areas:

Symbol extraction and resolution in object files during binary creation.
Dynamic runtime library path resolution in shared libraries.

We have resolved them and we plan to submit these fixes to the meson community shortly.

Nice!

--
Robert Haas
EDB: http://www.enterprisedb.com

#83Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Robert Haas (#82)
RE: AIX support

Hi Team,
Here are the updates on the meson on AIX. Our team had pushed the fixes meson github here …

https://github.com/mesonbuild/meson/pull/14335

#14335 Enhance AIX shared library build to use an export List.<https://github.com/mesonbuild/meson/pull/14335&gt;

#84wenhui qiu
qiuwenhuifx@gmail.com
In reply to: Srirama Kucherlapati (#83)
Re: AIX support

HI Srirama
It's getting close to code freeze. Any updates from your end?

Thanks

On Tue, Mar 18, 2025 at 12:58 AM Srirama Kucherlapati <sriram.rk@in.ibm.com>
wrote:

Show quoted text

Hi Team,

Here are the updates on the meson on AIX. Our team had pushed the fixes
meson github here …

https://github.com/mesonbuild/meson/pull/14335

#14335 Enhance AIX shared library build to use an export List.
<https://github.com/mesonbuild/meson/pull/14335&gt;

#85Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: wenhui qiu (#84)
RE: AIX support

Hi Wenhui Qiu,

May I know the freeze dates.

We are nearly ready to deliver the patch. Currently, we have compiled the
source using Meson and are investigating one test case issue. Once we pinpoint
the cause, we will send you the patch. Notably, this test case behaves
differently on AIX, opting for a Bitmap Index Scan instead of an Index Scan.
Not sure if this is really specific to AIX?

meson test

396 Ok: 81
397 Expected Fail: 0
398 Fail: 1 (regex)
399 Unexpected Pass: 0
400 Skipped: 219
401 Timeout: 0

7 explain (costs off) select * from pg_proc where proname ~ '^abc';
8 - QUERY PLAN
9 -----------------------------------------------------------------------
10 - Index Scan using pg_proc_proname_args_nsp_index on pg_proc
11 - Index Cond: ((proname >= 'abc'::text) AND (proname < 'abd'::text))
12 + QUERY PLAN
13 +----------------------------------------------------------------------------
14 + Bitmap Heap Scan on pg_proc
15 Filter: (proname ~ '^abc'::text)
16 -(3 rows)
17 + -> Bitmap Index Scan on pg_proc_proname_args_nsp_index
18 + Index Cond: ((proname >= 'abc'::text) AND (proname < 'abd'::text))
19 +(4 rows)

As of now below are the changes wrt to meson.

modified: meson.build
modified: src/backend/meson.build
modified: src/bin/initdb/initdb.c
modified: src/include/c.h
modified: src/include/port/aix.h
modified: src/include/utils/float.h
modified: src/interfaces/ecpg/compatlib/meson.build
modified: src/interfaces/ecpg/ecpglib/meson.build
modified: src/interfaces/ecpg/pgtypeslib/meson.build
modified: src/interfaces/libpq/meson.build
modified: src/test/regress/expected/txid.out
modified: src/test/regress/expected/xid.out
modified: src/test/regress/sql/sanity_check.sql

Warm regards,
Sriram.

#86Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Srirama Kucherlapati (#85)
Re: AIX support

On 03/04/2025 16:45, Srirama Kucherlapati wrote:

Hi Wenhui Qiu,

May I know the freeze dates.

April 8th is the feature freeze. Any new features must be *committed* by
then. We are already very close to that, and given that there's no
concrete patch for committer to review yet, I think it's safe to say
that you missed it already.

--
Heikki Linnakangas
Neon (https://neon.tech)

#87Andres Freund
andres@anarazel.de
In reply to: Srirama Kucherlapati (#85)
Re: AIX support

Hi,

On 2025-04-03 13:45:01 +0000, Srirama Kucherlapati wrote:

We are nearly ready to deliver the patch. Currently, we have compiled the
source using Meson and are investigating one test case issue. Once we pinpoint
the cause, we will send you the patch. Notably, this test case behaves
differently on AIX, opting for a Bitmap Index Scan instead of an Index Scan.
Not sure if this is really specific to AIX?

meson test

396 Ok: 81
397 Expected Fail: 0
398 Fail: 1 (regex)
399 Unexpected Pass: 0
400 Skipped: 219

FWIW, the skipped tests indicate that you are building without tap tests or
such - that means most of the testsuite is not run. That certainly is not good
enough.

Greetings,

Andres Freund

#88Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Heikki Linnakangas (#86)
1 attachment(s)
RE: AIX support

Hi Heikki and team,

Thank you for considering our request. As discussed, we have revised the patch
to incorporate all the review comments provided.
Please find the attached patch, which focuses solely on the gmake changes.
As discussed the meson specific changes would be provided as different patch.

We have taken into account and resolved the earlier comments within this patch.
/messages/by-id/e0dc2bff-300b-4edd-912b-b6c52274bdc5@iki.fi

- Build using latest master. (used commit 898c131b58a0b)
- We have merged our changes to this latest level.
- configure.ac
- Updated the changes aligning to configure file.
- configure
- Updated the comments wrt to the alignment details. Updated with
the gcc specific fix which talks about the alignment.
- updated the int64_t specific changes.
- doc/src/sgml/dfunc.sgml
- This is removed as it is not relevant.
- src/backend/port/aix/mkldexport.sh
- When building shared libraries from various archives on AIX, we encounter a
situation where symbols are not exported. To resolve this, we require an export
file. For instance, the command is used to export symbols.
gcc -shared libtest.so libtest.a -Wl,-bE:test.exp

However, if we directly provide object files in the command line instead of an
archive, the symbols will be exported automatically, as demonstrated by the command
gcc -shared libtest.so test1.o test2.o test3.o.
- We will update the description with additional details in the later point of time. (Considering the time lines)

- src/makefiles/Makefile.aix
- The changes in this file are required
- This change is not required “+LDFLAGS_SL += -Wl,-bnoentry -Wl,-H512 -Wl,-bM:SRE”
- src/template/aix
- WRT to the MEMSET_LOOP_LIMIT flag, this is set to “0”, which would internally use
The system call memset() as mentioned in the below link as well

/messages/by-id/20060203135315.E08B09DC816@postgresql.org

I Kindly request you to review the changes and provide your feedback.

With all the above changes we have built and ran the tests. As of now we see
there is only one test case that is failing, which seems to have been
introduced recently. And this might not be related to the above changes as
earlier there were no test cases failing.

64 not ok 12 + float8 235 ms

297 # 1 of 226 tests failed.

20 +ERROR: value out of range: overflow
21 -- test overflow/underflow handling
22 SELECT gamma(float8 '-infinity');
23 ERROR: value out of range: overflow

Warm regards,
Sriram.

Attachments:

0001-AIX-support.v7.patchapplication/octet-stream; name=0001-AIX-support.v7.patchDownload
From 614cd077da0de9ca92c4e4fb300c39f73ab5ad10 Mon Sep 17 00:00:00 2001
From: Sriram RK <sriram.rk@in.ibm.com>
Date: Fri, 4 Apr 2025 13:16:21 -0500
Subject: [PATCH] AIX support.

---
 Makefile                           |  2 -
 configure                          | 34 ++++++++++++++---
 configure.ac                       | 34 ++++++++++++++---
 src/Makefile.shlib                 | 29 ++++++++++++++
 src/backend/Makefile               | 20 ++++++++++
 src/backend/port/aix/mkldexport.sh | 61 ++++++++++++++++++++++++++++++
 src/backend/utils/error/elog.c     |  2 +
 src/include/port/aix.h             |  4 ++
 src/include/storage/s_lock.h       | 10 ++---
 src/makefiles/Makefile.aix         | 39 +++++++++++++++++++
 src/port/strerror.c                |  2 +
 src/template/aix                   |  7 ++++
 12 files changed, 224 insertions(+), 20 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 create mode 100644 src/include/port/aix.h
 create mode 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index 8a2ec9396b6..9bc1a4ec17b 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/configure b/configure
index 11615d1122d..6088fa26679 100755
--- a/configure
+++ b/configure
@@ -3008,6 +3008,7 @@ else
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -16953,13 +16954,34 @@ _ACEOF
 # 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 "$PORTNAME" != "aix"; then
+    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 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+#
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+    fi
 
-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
diff --git a/configure.ac b/configure.ac
index debdf165044..c21aaa52064 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ PGAC_ARG_REQ(with, template, [NAME], [override operating system template],
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -1987,13 +1988,34 @@ AC_CHECK_ALIGNOF(double)
 # 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 "$PORTNAME" != "aix"; then
+    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 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+# 
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t ; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+    fi
 
-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.])
 
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index fa81f6ffdd6..13ea84ac185 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,20 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +268,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps both shared libraries and static library, which can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +289,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +401,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +419,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 7344c8c7f5c..572f5430a60 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -63,12 +63,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -95,6 +97,24 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
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/utils/error/elog.c b/src/backend/utils/error/elog.c
index 8a6b6905079..3a8e9dc30b0 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -904,7 +904,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/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 00000000000..7d08480c8c0
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,4 @@
+/*
+ * src/include/port/aix.h
+ */
+
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 2f73f9fcf57..5da9b3acda4 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -421,17 +421,15 @@ tas(volatile slock_t *lock)
 	__asm__ __volatile__(
 "	lwarx   %0,0,%3,1	\n"
 "	cmpwi   %0,0		\n"
-"	bne     1f			\n"
+"	bne     $+16		\n"		/* branch to li %1,1 */
 "	addi    %0,%0,1		\n"
 "	stwcx.  %0,0,%3		\n"
-"	beq     2f			\n"
-"1: \n"
+"	beq     $+12		\n"		/* branch to lwsync */
 "	li      %1,1		\n"
-"	b       3f			\n"
-"2: \n"
+"	b       $+12		\n"		/* branch to end of asm sequence */
 "	lwsync				\n"
 "	li      %1,0		\n"
-"3: \n"
+
 :	"=&b"(_t), "=r"(_res), "+m"(*lock)
 :	"r"(lock)
 :	"memory", "cc");
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 00000000000..d33918f91b9
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,39 @@
+# MAKE_EXPORTS is required for svr4 loaders that want a file of
+# symbol names to tell them what to export/import.
+MAKE_EXPORTS= true
+
+# -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
+
+rpath = -Wl,-blibpath:'$(rpathdir)$(libpath)'
+
+#LDFLAGS_SL += -Wl,-bnoentry -Wl,-H512 -Wl,-bM:SRE
+
+# 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/port/strerror.c b/src/port/strerror.c
index f0746517770..c46b9dc91fc 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,8 +214,10 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
 			return "ENOTEMPTY";
+#endif
 		case ENOTSOCK:
 			return "ENOTSOCK";
 #ifdef ENOTSUP
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 00000000000..48a3ce55cf7
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,7 @@
+# src/template/aix
+
+# Extra CFLAGS for code that will go into a shared library
+CFLAGS_SL=""
+
+# Native memset() is faster.
+MEMSET_LOOP_LIMIT=0
-- 
2.41.0

#89Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Srirama Kucherlapati (#88)
Re: AIX support

On 04/04/2025 22:31, Srirama Kucherlapati wrote:

- src/backend/port/aix/mkldexport.sh>
  - When building shared libraries from various archives on AIX, we encounter a
     situation where symbols are not exported. To resolve this, we require an export
     file. For instance, the command is used to export symbols.

     gcc -shared libtest.so libtest.a -Wl,-bE:test.exp

     However, if we directly provide object files in the command line instead of an
     archive, the symbols will be exported automatically, as demonstrated by the command

     gcc -shared libtest.so test1.o test2.o test3.o.

Oh, that's interesting. So if we do that, we don't need mkldepxort.sh
anymore?

   - WRT to the MEMSET_LOOP_LIMIT flag, this is set to “0”, which would
internally use

     The system call memset() as mentioned in the below link as well

https://www.postgresql.org/message-
id/20060203135315.E08B09DC816%40postgresql.org <https://
www.postgresql.org/message-id/20060203135315.E08B09DC816%40postgresql.org>

Yes, I understand what it does. But why? Whatever benchmarking was done
back in 2006 by is no longer relevant.

With all the above changes we have built and ran the tests. As of now we see

there is only one test case that is failing, which seems to have been

introduced recently. And this might not be related to the above changes as

earlier there were no test cases failing.

64 not ok 12    + float8                   235 ms

297 # 1 of 226 tests failed.

20 +ERROR:  value out of range: overflow

21  -- test overflow/underflow handling

22  SELECT gamma(float8 '-infinity');

23  ERROR:  value out of range: overflow

Yeah, that function is new. I don't know if it's a pre-existing problem
or something specific to AIX. Please check the archives for prior
discussion on that; if you can reproduce it, maybe you can help to fix it?

12 files changed, 224 insertions(+), 20 deletions(-)

I'm glad to see this patch shrinking :-)

diff --git a/src/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 00000000000..7d08480c8c0
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,4 @@
+/*
+ * src/include/port/aix.h
+ */
+

Useless.

diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 2f73f9fcf57..5da9b3acda4 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -421,17 +421,15 @@ tas(volatile slock_t *lock)
__asm__ __volatile__(
"	lwarx   %0,0,%3,1	\n"
"	cmpwi   %0,0		\n"
-"	bne     1f			\n"
+"	bne     $+16		\n"		/* branch to li %1,1 */
"	addi    %0,%0,1		\n"
"	stwcx.  %0,0,%3		\n"
-"	beq     2f			\n"
-"1: \n"
+"	beq     $+12		\n"		/* branch to lwsync */
"	li      %1,1		\n"
-"	b       3f			\n"
-"2: \n"
+"	b       $+12		\n"		/* branch to end of asm sequence */
"	lwsync				\n"
"	li      %1,0		\n"
-"3: \n"
+
:	"=&b"(_t), "=r"(_res), "+m"(*lock)
:	"r"(lock)
:	"memory", "cc");

Why is this change needed?

Yes, I know we've been over this many times already. I still don't
understand why it's needed. The onus is on you to explain it adequately,
in comments in the patch, so that I and others understand it. Or even
better, remove it if it's not necessary.

diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 00000000000..d33918f91b9
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,39 @@
+# MAKE_EXPORTS is required for svr4 loaders that want a file of
+# symbol names to tell them what to export/import.
+MAKE_EXPORTS= true

Oh this is interesting. I think MAKE_EXPORTS is actually a leftover that
I failed to remove when I removed the AIX support; it's not used on any
currently-supported platform.

+# -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

Is this still sensible on modern AIX systems? What happens if you leave
it out?

+# 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

Same here. Still relevant? What happens if you leave it out?

+# 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

On other platforms, we have this in LINK.shared, see src/Makefile.shlib.
Should we do the same on AIX; if not, why not?

+# env var name to use in place of LD_LIBRARY_PATH
+ld_library_path_var = LIBPATH

Does AIX have LD_LIBRARY_PATH? This suggests that it does:

https://www.ibm.com/support/pages/aix-libpath-recommendations

What's the difference between LIBPATH and LD_LIBRARY_PATH? Why prefer
LIBPATH?

Separately from the remaining issues with this patch, I still feel
pretty reluctant with accepting this, because if I commit this patch,
I'm on the hook to keep it working. I do regularly commit stuff that I'm
not personally that interested in, but a new port is different:

If something breaks on AIX, I have no means (or interest!) in debugging
it. That means that I need to be pretty confident that there are others
who are interested and invested in keeping working, take ownership, will
help to debug problems in a timely fashion, and can submit high-quality
fixes. I am not seeing that.

I also notice that all the AIX systems we have in the buildfarm are still:

- maintained by Noah, who - correct me if I'm wrong - is not
particularly interested in AIX or keen on maintaining them
- are on AIX 7.1.5, which I believe is already end-of-line
- running on power7 hardware which is 15 years old.

That's not very reassuring.

--
Heikki Linnakangas
Neon (https://neon.tech)

#90Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Heikki Linnakangas (#89)
1 attachment(s)
RE: AIX support

Hi Heikki,
Please find the attached patch addressing the provided comments. Our responses are outlined below.

- src/backend/port/aix/mkldexport.sh>

Oh, that's interesting. So if we do that, we don't need mkldepxort.sh
anymore?

Here the better approach still would be to use the script to extract the
symbols build the corresponding shared libraries. As we see there are
lot of extensions that are getting built using the symbols exported from
"postges" binary, we need to definitely use the script to extract the symbols
and import them while building the library extensions.

- WRT to the MEMSET_LOOP_LIMIT flag, this is set to “0”, which would
internally use

Yes, I understand what it does. But why? Whatever benchmarking was done
back in 2006 by is no longer relevant.

We ran the program , mentioned in the below link and collected the

benchmark stats on our node (POWER_10).

https://postgrespro.com/list/thread-id/1673194

The native AIX memset() seems to performs better. The benchmark seems to be still

relevant, so I think we should continue to use the existing optimization for

AIX. Below are the stats (64bit Object mode).

./memset-aix

sizeof(int) = 4

sizeof(long) = 8

Loop by int (size=8) : 0.238024

memset by int (size=8) : 0.280301

Loop by long (size=8) : 0.202650

Loop by int (size=16) : 0.389846

memset by int (size=16) : 0.280979

Loop by long (size=16) : 0.246879

Loop by int (size=32) : 0.773478

memset by int (size=32) : 0.331691

Loop by long (size=32) : 0.422261

Loop by int (size=64) : 1.945150

memset by int (size=64) : 0.319117

Loop by long (size=64) : 0.769770

Loop by int (size=128) : 4.517186

memset by int (size=128) : 0.398292

Loop by long (size=128) : 1.982307

Loop by int (size=256) : 12.486661

memset by int (size=256) : 0.463115

Loop by long (size=256) : 4.526272

Loop by int (size=512) : 24.433075

memset by int (size=512) : 0.681426

Loop by long (size=512) : 12.564701

Loop by int (size=1024) : 48.060486

memset by int (size=1024) : 0.904048

Loop by long (size=1024) : 24.149871

Loop by int (size=2048) : 96.288018

memset by int (size=2048) : 1.509465

Loop by long (size=2048) : 48.216079

Loop by int (size=4096) : 191.847177

memset by int (size=4096) : 1.435403

Loop by long (size=4096) : 96.433072

12 files changed, 224 insertions(+), 20 deletions(-)

I'm glad to see this patch shrinking :-)

Thanks for your suggestions, yes it further shrinked.

diff --git a/src/include/port/aix.h b/src/include/port/aix.h

Useless.

I too initially felt this was not needed, This file is still required as the below file is

getting auto generated. I attempted to remove it; the below error is hit.

so this is still required.

64 ../../src/include/c.h:59:10: fatal error: pg_config_os.h: No such file or directory

65 59 | #include "pg_config_os.h" /* config from include/port/PORTNAME.h */

66 | ^~~~~~~~~~~~~~~~

diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h

Why is this change needed?

Yes, I know we've been over this many times already. I still don't
understand why it's needed. The onus is on you to explain it adequately,
in comments in the patch, so that I and others understand it. Or even
better, remove it if it's not necessary.

If you recall, we previously considered replacing this assembly code with
__sync_lock_test_and_set(). However, as you mentioned earlier, this should be
handled in a separate patch. For now, I'll make a note and submit a separate
patch for this later, as originally planned. Below is the reference to older
discussion.
/messages/by-id/7751f9c5-e2e6-4252-a9fa-14b3e78ddec9@iki.fi

diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
+MAKE_EXPORTS= true

Oh this is interesting. I think MAKE_EXPORTS is actually a leftover that
I failed to remove when I removed the AIX support; it's not used on any
currently-supported platform.

Removed it and its working fine.

+# -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

Is this still sensible on modern AIX systems? What happens if you leave
it out?

This is required as it is looking for the possible non-default directories for the linker

at the runtime. This is used along with rpath. As suggested, I tested this by removing

the libpath, but at run time the linker is not able to find the dependent libraries path

as a result, the binaries are not getting loaded. After doing some research, AIX uses a stricter,

more explicit approach. The runtime linker expects to tell it exactly where to look using -blibpath.

+# 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

Same here. Still relevant? What happens if you leave it out?

Removed it and it is working fine.

+# 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

On other platforms, we have this in LINK.shared, see src/Makefile.shlib.
Should we do the same on AIX; if not, why not?

I tried your suggestion to move the gcc "LDFLAGS_SL += -shared" flag to Makefile.shlib,

"LINK.shared = $(COMPILER) -shared", but there are some extensions dependent

on this in "contrib" which are not building with “-shared” flag, as a result a testcase

is failing to load this library "contrib/spi/autoinc.so" . Below is the error.

not ok 78 + triggers 2443 ms

31 +ERROR: incompatible library "/home/pgdev/pgdb/postgres/src/test/regress/autoinc.so": missing magic block

32 +HINT: Extension libraries are required to use the PG_MODULE_MAGIC macro.

I noticed that the “-shared” flag was missing while building the contrib/spi/autoinc.so library.

I tried to add the “include $(top_builddir)/src/Makefile.shlib” in the

contrib/spi/Makefile, but still the “-shared” flag is not getting included while building

the library.
So we will continue to use the earlier change.

Does AIX have LD_LIBRARY_PATH? This suggests that it does:
https://www.ibm.com/support/pages/aix-libpath-recommendations
What's the difference between LIBPATH and LD_LIBRARY_PATH? Why prefer

LIBPATH?

AIX uses only LIBPATH and LD_LIBRARY_PATH is specific to Linux.

Separately from the remaining issues with this patch, I still feel
pretty reluctant with accepting this, because if I commit this patch,
I'm on the hook to keep it working. I do regularly commit stuff that I'm
not personally that interested in, but a new port is different:

If something breaks on AIX, I have no means (or interest!) in debugging
it. That means that I need to be pretty confident that there are others
who are interested and invested in keeping working, take ownership, will
help to debug problems in a timely fashion, and can submit high-quality
fixes. I am not seeing that.

I completely understand your concerns about committing to a new port and
ensuring its long-term maintenance.
Our team would like to extend the support to maintain PostgreSQL on AIX.
We would like to assist by timely debugging and resolving any issues on AIX.
We’re also keen to actively contribute to this effort.

I also notice that all the AIX systems we have in the buildfarm are still:

- maintained by Noah, who - correct me if I'm wrong - is not
particularly interested in AIX or keen on maintaining them
- are on AIX 7.1.5, which I believe is already end-of-line
- running on power7 hardware which is 15 years old.

That's not very reassuring.

From a hardware perspective, we believe it should be feasible to provide
new nodes in the OSU lab. We've already set up a Power9 machine with the
supported AIX version for the community usage. Recently, there was a request from
the community (Mark Wong) for additional nodes, and we're happy to offer
any hardware support needed.

Warm regards,
Sriram.

Attachments:

0001-AIX-support.v8.patchapplication/octet-stream; name=0001-AIX-support.v8.patchDownload
From c854025252ca3dfff9f7f1c4d4aed21cf0cf5346 Mon Sep 17 00:00:00 2001
From: Sriram RK <sriram.rk@in.ibm.com>
Date: Fri, 4 Apr 2025 13:16:21 -0500
Subject: [PATCH] AIX support.

---
 Makefile                           |  2 -
 configure                          | 34 ++++++++++++++---
 configure.ac                       | 34 ++++++++++++++---
 src/Makefile.shlib                 | 29 ++++++++++++++
 src/backend/Makefile               | 20 ++++++++++
 src/backend/port/aix/mkldexport.sh | 61 ++++++++++++++++++++++++++++++
 src/backend/utils/error/elog.c     |  2 +
 src/include/port/aix.h             |  4 ++
 src/include/storage/s_lock.h       | 10 ++---
 src/makefiles/Makefile.aix         | 29 ++++++++++++++
 src/port/strerror.c                |  2 +
 src/template/aix                   |  7 ++++
 12 files changed, 214 insertions(+), 20 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 create mode 100644 src/include/port/aix.h
 create mode 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index 8a2ec9396b6..9bc1a4ec17b 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/configure b/configure
index 11615d1122d..6088fa26679 100755
--- a/configure
+++ b/configure
@@ -3008,6 +3008,7 @@ else
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -16953,13 +16954,34 @@ _ACEOF
 # 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 "$PORTNAME" != "aix"; then
+    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 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+#
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+    fi
 
-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
diff --git a/configure.ac b/configure.ac
index debdf165044..c21aaa52064 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ PGAC_ARG_REQ(with, template, [NAME], [override operating system template],
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -1987,13 +1988,34 @@ AC_CHECK_ALIGNOF(double)
 # 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 "$PORTNAME" != "aix"; then
+    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 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+# 
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t ; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+    fi
 
-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.])
 
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index fa81f6ffdd6..13ea84ac185 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,20 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +268,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps both shared libraries and static library, which can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +289,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +401,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +419,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 7344c8c7f5c..572f5430a60 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -63,12 +63,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -95,6 +97,24 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
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/utils/error/elog.c b/src/backend/utils/error/elog.c
index 8a6b6905079..3a8e9dc30b0 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -904,7 +904,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/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 00000000000..7d08480c8c0
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,4 @@
+/*
+ * src/include/port/aix.h
+ */
+
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 2f73f9fcf57..5da9b3acda4 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -421,17 +421,15 @@ tas(volatile slock_t *lock)
 	__asm__ __volatile__(
 "	lwarx   %0,0,%3,1	\n"
 "	cmpwi   %0,0		\n"
-"	bne     1f			\n"
+"	bne     $+16		\n"		/* branch to li %1,1 */
 "	addi    %0,%0,1		\n"
 "	stwcx.  %0,0,%3		\n"
-"	beq     2f			\n"
-"1: \n"
+"	beq     $+12		\n"		/* branch to lwsync */
 "	li      %1,1		\n"
-"	b       3f			\n"
-"2: \n"
+"	b       $+12		\n"		/* branch to end of asm sequence */
 "	lwsync				\n"
 "	li      %1,0		\n"
-"3: \n"
+
 :	"=&b"(_t), "=r"(_res), "+m"(*lock)
 :	"r"(lock)
 :	"memory", "cc");
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 00000000000..ab6581533d8
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,29 @@
+# -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
+
+# 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/port/strerror.c b/src/port/strerror.c
index f0746517770..c46b9dc91fc 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,8 +214,10 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
 			return "ENOTEMPTY";
+#endif
 		case ENOTSOCK:
 			return "ENOTSOCK";
 #ifdef ENOTSUP
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 00000000000..48a3ce55cf7
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,7 @@
+# src/template/aix
+
+# Extra CFLAGS for code that will go into a shared library
+CFLAGS_SL=""
+
+# Native memset() is faster.
+MEMSET_LOOP_LIMIT=0
-- 
2.41.0

#91Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Srirama Kucherlapati (#90)
Re: AIX support

On 05/04/2025 21:29, Srirama Kucherlapati wrote:

 - WRT to the MEMSET_LOOP_LIMIT flag, this is set to “0”, which would
internally use

Yes, I understand what it does. But why? Whatever benchmarking was done
back in 2006 by is no longer relevant.

We ran the program , mentioned in the below link and collected the
benchmark stats on our node (POWER_10).

https://postgrespro.com/list/thread-id/1673194 <https://postgrespro.com/
list/thread-id/1673194>

The native AIX memset() seems to performs better. The benchmark seems to
be still relevant, so I think we should continue to use the existing optimization for
AIX.

At least it needs to be updated to match what MemSet() looks like
nowadays. The changes may be just cosmetic, but better check. Should
also check the effect on MemSetAligned(). That might matter more for
performance in practice.

A third thing to check is the performance of MemSet() when the pointer
is, in fact, aligned.

The other question is what do the results look like on other platforms?
How much difference does the libc implementation make, vs. the compiler
and CPU architecture? If the difference is related to compiler or CPU
architecture, then this doesn't belong in the AIX template, but
somewhere else.

Below are the stats (64bit Object mode).

./memset-aix

        sizeof(int)  = 4
        sizeof(long) = 8

MemSet() uses 'long', so the int tests are not relevant. I have omitted
them below.

        memset by int (size=8) : 0.280301
        Loop by long (size=8) : 0.202650

        memset by int (size=16) : 0.280979
        Loop by long (size=16) : 0.246879

        memset by int (size=32) : 0.331691
        Loop by long (size=32) : 0.422261

Ok, MemSet() is faster with very small sizes, the crossover is somewhere
between 16 and 32 bytes.

I'm actually surprised the compiler doesn't replace the memset() call
with a few store instructions with these sizes.

        memset by int (size=1024) : 0.904048
        Loop by long (size=1024) : 24.149871

So with larger sizes, memset() wins hands down.

I'm surprised how big the difference is, because I actually expected the
compiler to detect the memory-zeroing loop and replace it with some
fancy vector instructions (does powerpc have any?). Or a call to
memset(); I've seen compilers convert loops to memset() and vice versa.

My gut feeling is actually that we should remove the MemSet() macro
altogether and just use memset() everywhere. The compilers are much
better at optimizing it in year 2025 than they were back in 2002. I'd
love to see some rigorous benchmarks across different platforms and
compilers to demonstrate that, and then just get rid of MemSet().

MemSetAligned() might still be worth keeping. Sometimes we know that a
piece of memory is aligned, but the compiler does not. But maybe even
that should just assert and hint the compiler that the input is aligned,
and then call memset().

If you'd like to help the community in general, if you could do some
more rigorous benchmarking along those lines, not just for AIX, and
start a new thread to discuss that, that'd be much appreciated. That
would be the best way to resolve this.

For the more narrow question of what should the AIX template do, that
comes down to whether there's some *AIX-specific* performance
difference. The generated powerpc assembly code is presumably the same
on AIX and other operating systems, so it comes down to whether there's
some big difference in AIX's memset() implementation vs. glibc's.

diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h

Why is this change needed?

Yes, I know we've been over this many times already. I still don't
understand why it's needed. The onus is on you to explain it adequately,
in comments in the patch, so that I and others understand it. Or even
better, remove it if it's not necessary.

If you recall, we previously considered replacing this assembly code
with __sync_lock_test_and_set(). However, as you mentioned earlier,
this should be handled in a separate patch. For now, I'll make a
note and submit a separate patch for this later, as originally
planned. Below is the reference to older discussion.

Yes, I do recall. Please read again my comment above: this all needs to
be explained in comments in the code.

To be precise, I have these questions:

- Does GCC on AIX (still) use the IBM assembler?
- Does the IBM assembler still not understand the label syntax?
- Is there some other label syntax that would work on the IBM assembler?
- Is it possible to use the GNU assembler instead?

+# -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

Is this still sensible on modern AIX systems? What happens if you leave
it out?

This is required as it is looking for the possible non-default
directories for the linker at the runtime. This is used along with
rpath. As suggested, I tested this by removing the libpath, but at
run time the linker is not able to find the dependent libraries path
as a result, the binaries are not getting loaded. After doing some
research, AIX uses a stricter, more*explicit* approach. The runtime
linker expects to tell it exactly where to look using -blibpath.

Ok, some comments would be in order to explain that, maybe with links to
the relevant AIX documentation.

--
Heikki Linnakangas
Neon (https://neon.tech)

#92Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Heikki Linnakangas (#91)
RE: AIX support

Here are some stats wrt to loop and native memset after enabling optimization with the same test tool(tested for long and long align using MemSetAligned). Corresponding glibc is linked on PPcle and AIX libc is linked on AIX.

https://postgrespro.com/list/thread-id/1673194

AIX loop-1 PPCle - loop1 AIX loop-2 PPCle - loop2
Loop by long (size=8) : 0 0 0.000001 0
Loop Align by long (size=8) : 0 0 0 0
memset by long (size=8) : 0.00999 0.010229 0.00994 0.010211
Loop by long (size=16) : 0 0 0 0
Loop Align by long (size=16) : 0 0 0 0
memset by long (size=16) : 0.010082 0.010036 0.010094 0.01003
Loop by long (size=32) : 0.32903 0.227726 0.329027 0.227707
Loop Align by long (size=32) : 0.329486 0.227705 0.328932 0.227712
memset by long (size=32) : 0.021061 0.01064 0.021115 0.01064
Loop by long (size=64) : 0.334761 0.227714 0.34326 0.227688
Loop Align by long (size=64) : 0.329005 0.236937 0.329084 0.236906
memset by long (size=64) : 0.059559 0.025612 0.053004 0.029589
Loop by long (size=128) : 0.420381 0.329634 0.420332 0.329524
Loop Align by long (size=128) : 0.420376 0.337169 0.42022 0.337162
memset by long (size=128) : 0.420153 0.098774 0.420312 0.101888
Loop by long (size=256) : 0.472187 0.428049 0.472774 0.429217
Loop Align by long (size=256) : 0.472586 0.438316 0.472447 0.438325
memset by long (size=256) : 0.473731 0.428013 0.473864 0.42759
Loop by long (size=512) : 0.676089 0.435649 0.632774 0.43574
Loop Align by long (size=512) : 0.66702 0.428013 0.630751 0.427319
memset by long (size=512) : 0.666619 0.427989 0.691485 0.427263
Loop by long (size=1024) : 1.00773 0.45079 0.925212 0.452131
Loop Align by long (size=1024) : 0.92114 0.45084 0.920574 0.452994
memset by long (size=1024) : 0.935062 0.450821 0.917 0.452396
Loop by long (size=2048) : 1.52585 0.702127 1.265107 0.701822
Loop Align by long (size=2048) : 1.57524 0.702158 1.439109 0.702651
memset by long (size=2048) : 1.614771 0.702247 1.384672 0.701857
Loop by long (size=4096) : 1.418133 1.37568 1.325803 1.376005
Loop Align by long (size=4096) : 1.421619 1.375741 1.325743 1.376071
memset by long (size=4096) : 1.423404 1.375716 1.325666 1.376091

After enabling optimization levels, both are performing similar.
As both are performing similar we have removed the MEMSET_LOOP in the AIX template and tried the below benchmark after running pgbench.

Run#1

pgbench -c 50 -p 5678 -d postgres -T 180 -r -P 10 -L 10 -j 20

pgbench (18devel)
starting vacuum...end.
progress: 10.0 s, 2603.2 tps, lat 18.692 ms stddev 61.947, 0 failed
progress: 20.0 s, 3373.2 tps, lat 14.841 ms stddev 17.724, 0 failed
progress: 30.0 s, 2599.6 tps, lat 19.222 ms stddev 99.307, 0 failed
progress: 40.0 s, 3531.3 tps, lat 14.159 ms stddev 14.786, 0 failed
progress: 50.0 s, 2561.3 tps, lat 15.180 ms stddev 33.532, 0 failed
progress: 60.0 s, 3315.4 tps, lat 18.421 ms stddev 111.988, 0 failed
progress: 70.0 s, 3517.4 tps, lat 14.203 ms stddev 14.931, 0 failed
progress: 80.0 s, 2023.4 tps, lat 21.858 ms stddev 125.718, 0 failed
progress: 90.0 s, 3472.1 tps, lat 16.049 ms stddev 55.152, 0 failed
progress: 100.0 s, 3580.5 tps, lat 13.966 ms stddev 14.636, 0 failed
progress: 110.0 s, 2823.4 tps, lat 14.572 ms stddev 20.433, 0 failed
progress: 120.0 s, 3140.3 tps, lat 18.717 ms stddev 120.447, 0 failed
progress: 130.0 s, 3488.4 tps, lat 14.329 ms stddev 15.057, 0 failed
progress: 140.0 s, 2503.7 tps, lat 19.966 ms stddev 125.551, 0 failed
progress: 150.0 s, 3083.3 tps, lat 16.212 ms stddev 56.652, 0 failed
progress: 160.0 s, 3572.0 tps, lat 13.991 ms stddev 14.660, 0 failed
progress: 170.0 s, 3642.2 tps, lat 13.722 ms stddev 14.507, 0 failed
progress: 180.0 s, 2453.6 tps, lat 20.364 ms stddev 133.126, 0 failed
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 50
query mode: simple
number of clients: 50
number of threads: 20
maximum number of tries: 1
duration: 180 s
number of transactions actually processed: 552889
number of failed transactions: 0 (0.000%)
number of transactions above the 10.0 ms latency limit: 227816/552889 (41.205%)
latency average = 16.252 ms
latency stddev = 69.656 ms
initial connection time = 237.245 ms
tps = 3074.421213 (without initial connection time)
statement latencies in milliseconds and failures:
0.002 0 \set aid random(1, 100000 * :scale)
0.001 0 \set bid random(1, 1 * :scale)
0.001 0 \set tid random(1, 10 * :scale)
0.001 0 \set delta random(-5000, 5000)
1.090 0 BEGIN;
3.153 0 UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
1.462 0 SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
2.012 0 UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
4.060 0 UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
1.224 0 INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_T
3.246 0 END;

Run#2

pgbench -c 50 -p 5678 -d postgres -T 180 -r -P 10 -L 10 -j 20

pgbench (18devel)
starting vacuum...end.

transaction type: <builtin: TPC-B (sort of)>
scaling factor: 50
query mode: simple
number of clients: 50
number of threads: 20
maximum number of tries: 1
duration: 180 s
number of transactions actually processed: 577290
number of failed transactions: 0 (0.000%)
number of transactions above the 10.0 ms latency limit: 234815/577290 (40.675%)
latency average = 15.558 ms
latency stddev = 65.428 ms
initial connection time = 314.109 ms
tps = 3211.642930 (without initial connection time)
statement latencies in milliseconds and failures:
0.002 0 \set aid random(1, 100000 * :scale)
0.001 0 \set bid random(1, 1 * :scale)
0.001 0 \set tid random(1, 10 * :scale)
0.001 0 \set delta random(-5000, 5000)
1.084 0 BEGIN;
2.761 0 UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
1.371 0 SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
2.000 0 UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
4.014 0 UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
1.229 0 INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_T
3.093 0 END;

diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h

- Does GCC on AIX (still) use the IBM assembler?
- Does the IBM assembler still not understand the label syntax?
- Is there some other label syntax that would work on the IBM assembler?
- Is it possible to use the GNU assembler instead?

GCC on AIX still uses the AIX native assembler only. The GNU assembler has some level of support in AIX through some of the patches. But still GCC/gnu assembler combination is not very much tested.

We removed AIX specific changes for TAS(), which would now use the __sync_lock_test_and_set() routines directly instead, and we ran pgbench on it.

+ pgbench -c 50 -p 5678 -d postgres -T 180 -r -P 10 -L 10 -j 20
pgbench (18devel)
starting vacuum...end.

scaling factor: 50
query mode: simple
number of clients: 50
number of threads: 20
maximum number of tries: 1
duration: 180 s
number of transactions actually processed: 550838
number of failed transactions: 0 (0.000%)
number of transactions above the 10.0 ms latency limit: 227805/550838 (41.356%)
latency average = 16.323 ms
latency stddev = 68.404 ms
initial connection time = 235.449 ms
tps = 3061.041640 (without initial connection time)
statement latencies in milliseconds and failures:
0.002 0 \set aid random(1, 100000 * :scale)
0.001 0 \set bid random(1, 1 * :scale)
0.001 0 \set tid random(1, 10 * :scale)
0.001 0 \set delta random(-5000, 5000)
1.098 0 BEGIN;
2.993 0 UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
1.501 0 SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
2.004 0 UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
4.127 0 UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
1.238 0 INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
3.356 0 END;

21 -- test overflow/underflow handling

22 SELECT gamma(float8 '-infinity');

23 ERROR: value out of range: overflow

WRT failure in lgamma(), we worked with the libm team to resolve it. It’s an issue with the errno that is being set. I’ll work on the testcase.

./gamma-test NaN

Gamma and natural logarithm of gamma for the input values:
Gamma(NaNS) = NaNQ errno: 34
lgamma(NaNS) = NaNQ errno: 34

With fixed libm

+ ./gamma-test NaN

Gamma and natural logarithm of gamma for the input values:
Gamma(NaNS) = NaNQ errno: 0
lgamma(NaNS) = NaNQ errno: 0

Warm Regards,
Sriram

#93Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#92)
RE: AIX support

Working on the patch. I will update you.

-Sriram.

#94Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#92)
3 attachment(s)
RE: AIX support

Hi Team, Please find the attached diff with the latest changes.

The diff file changes that were done for memset and spinlock, are modified
on top of the previous patch.

New changes for review: 0001-AIX-support.tas.memset.diffs
Previous patch: 0001-AIX-support.v8.patch

diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h

We have replaced the asm code with the gcc specific routines __sync_lock_test_and_set ()
and ran the pgbench. On AIX both have the similar performance, On PPcle we see a slight
variation in the performance. It seems the asm code is performing better on PPCle. Please
let us know, would it be better to continue to use the PPC assemble code over gcc routines.

Attached are the complete stats. (spinlock.stats.log)
Below is the summary…

AIX With asm AIX With __sync PPCle With asm PPCle With __sync
number of transactions "226554/ "230810/ "356945/ "364346/
above the 10.0 ms 556329 567936 918647 863937
latency limit (40.723%)" (40.640%)" (38.856%)" (42.173%)"

latency average 16.160 ms 15.821 ms 9.796 ms 10.416 ms
initial connection time 230.786 ms 249.668 ms 19.606 ms 20.090 ms
tps 3086.209412 3158.14915 5103.024267 4799.621896

diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix

At least it needs to be updated to match what MemSet() looks like
nowadays. The changes may be just cosmetic, but better check. Should
also check the effect on MemSetAligned(). That might matter more for
performance in practice.

As per the stats in the previous mail wrt to memset, both the loop and the native
memset are performing similar after optimization “-O2”. So for now we removed the
native memset changes.
We will setup the memset performance on different platforms and will post the
details in a different thread.

+# -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

Added additional details about the -blibpath usage. These details are available in the below link
https://download.boulder.ibm.com/ibmdl/pub/software/dw/aix/es-aix_ll.pdf

21 -- test overflow/underflow handling

22 SELECT gamma(float8 '-infinity');

23 ERROR: value out of range: overflow

This testcase is resolved from AIX libm side. Below is the result.

postgres=#
SELECT x, gamma(x),lgamma(x)
FROM (VALUES (0.5), (1), (2), (3), (4), (5),
(float8 'infinity'), (float8 'nan')) AS t(x);

0.5 | 1.772453850905516 | 0.5723649429247001
1 | 1 | 0
2 | 1 | 0
3 | 2 | 0.6931471805599453
4 | 6 | 1.791759469228055
5 | 24 | 3.1780538303479458
Infinity | Infinity | Infinity
NaN | NaN | NaN

Kindly let us know your feedback on the diffs.
I will commit the diffs to the patch(0001-AIX-support.v8.patch) once you are fine.

Warm regards,
Sriram.

Attachments:

0001-AIX-support.tas.memset.diffsapplication/octet-stream; name=0001-AIX-support.tas.memset.diffsDownload

diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 5da9b3acda4..ba120c08d14 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -398,54 +398,18 @@ 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     $+16            \n"             /* branch to li %1,1 */
-"      addi    %0,%0,1         \n"
-"      stwcx.  %0,0,%3         \n"
-"      beq     $+12            \n"             /* branch to lwsync */
-"      li      %1,1            \n"
-"      b       $+12            \n"             /* branch to end of asm sequence */
-"      lwsync                          \n"
-"      li      %1,0            \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 */

diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
index ab6581533d8..4c4de8b0be7 100644
--- a/src/makefiles/Makefile.aix
+++ b/src/makefiles/Makefile.aix
@@ -1,3 +1,8 @@
+# -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

diff --git a/src/template/aix b/src/template/aix
index 48a3ce55cf7..ea7f7fb3487 100644
--- a/src/template/aix
+++ b/src/template/aix
@@ -1,7 +1,8 @@
+# This file is referred for specific flags wrt to AIX build process like
+# cflags.
 # src/template/aix

 # Extra CFLAGS for code that will go into a shared library
-CFLAGS_SL=""
+# With optimization, the MemSet() and MemSetAlign() perform better.
+CFLAGS_SL=" -O2 "

-# Native memset() is faster.
-MEMSET_LOOP_LIMIT=0
spinlock.stats.logtext/plain; name=spinlock.stats.logDownload
0001-AIX-support.v8.patchapplication/octet-stream; name=0001-AIX-support.v8.patchDownload
From c854025252ca3dfff9f7f1c4d4aed21cf0cf5346 Mon Sep 17 00:00:00 2001
From: Sriram RK <sriram.rk@in.ibm.com>
Date: Fri, 4 Apr 2025 13:16:21 -0500
Subject: [PATCH] AIX support.

---
 Makefile                           |  2 -
 configure                          | 34 ++++++++++++++---
 configure.ac                       | 34 ++++++++++++++---
 src/Makefile.shlib                 | 29 ++++++++++++++
 src/backend/Makefile               | 20 ++++++++++
 src/backend/port/aix/mkldexport.sh | 61 ++++++++++++++++++++++++++++++
 src/backend/utils/error/elog.c     |  2 +
 src/include/port/aix.h             |  4 ++
 src/include/storage/s_lock.h       | 10 ++---
 src/makefiles/Makefile.aix         | 29 ++++++++++++++
 src/port/strerror.c                |  2 +
 src/template/aix                   |  7 ++++
 12 files changed, 214 insertions(+), 20 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 create mode 100644 src/include/port/aix.h
 create mode 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index 8a2ec9396b6..9bc1a4ec17b 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/configure b/configure
index 11615d1122d..6088fa26679 100755
--- a/configure
+++ b/configure
@@ -3008,6 +3008,7 @@ else
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -16953,13 +16954,34 @@ _ACEOF
 # 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 "$PORTNAME" != "aix"; then
+    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 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+#
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+    fi
 
-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
diff --git a/configure.ac b/configure.ac
index debdf165044..c21aaa52064 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ PGAC_ARG_REQ(with, template, [NAME], [override operating system template],
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -1987,13 +1988,34 @@ AC_CHECK_ALIGNOF(double)
 # 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 "$PORTNAME" != "aix"; then
+    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 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+# 
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t ; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+    fi
 
-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.])
 
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index fa81f6ffdd6..13ea84ac185 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,20 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +268,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps both shared libraries and static library, which can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +289,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +401,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +419,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 7344c8c7f5c..572f5430a60 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -63,12 +63,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -95,6 +97,24 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
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/utils/error/elog.c b/src/backend/utils/error/elog.c
index 8a6b6905079..3a8e9dc30b0 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -904,7 +904,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/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 00000000000..7d08480c8c0
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,4 @@
+/*
+ * src/include/port/aix.h
+ */
+
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 2f73f9fcf57..5da9b3acda4 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -421,17 +421,15 @@ tas(volatile slock_t *lock)
 	__asm__ __volatile__(
 "	lwarx   %0,0,%3,1	\n"
 "	cmpwi   %0,0		\n"
-"	bne     1f			\n"
+"	bne     $+16		\n"		/* branch to li %1,1 */
 "	addi    %0,%0,1		\n"
 "	stwcx.  %0,0,%3		\n"
-"	beq     2f			\n"
-"1: \n"
+"	beq     $+12		\n"		/* branch to lwsync */
 "	li      %1,1		\n"
-"	b       3f			\n"
-"2: \n"
+"	b       $+12		\n"		/* branch to end of asm sequence */
 "	lwsync				\n"
 "	li      %1,0		\n"
-"3: \n"
+
 :	"=&b"(_t), "=r"(_res), "+m"(*lock)
 :	"r"(lock)
 :	"memory", "cc");
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 00000000000..ab6581533d8
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,29 @@
+# -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
+
+# 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/port/strerror.c b/src/port/strerror.c
index f0746517770..c46b9dc91fc 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,8 +214,10 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
 			return "ENOTEMPTY";
+#endif
 		case ENOTSOCK:
 			return "ENOTSOCK";
 #ifdef ENOTSUP
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 00000000000..48a3ce55cf7
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,7 @@
+# src/template/aix
+
+# Extra CFLAGS for code that will go into a shared library
+CFLAGS_SL=""
+
+# Native memset() is faster.
+MEMSET_LOOP_LIMIT=0
-- 
2.41.0

#95Thomas Munro
thomas.munro@gmail.com
In reply to: Heikki Linnakangas (#91)
Re: AIX support

On Mon, Apr 7, 2025 at 10:04 PM Heikki Linnakangas <hlinnaka@iki.fi> wrote:

I'm surprised how big the difference is, because I actually expected the
compiler to detect the memory-zeroing loop and replace it with some
fancy vector instructions (does powerpc have any?).

It certainly does, and we've played with explicit AltiVec
vectorisation before with the idea that our abstraction over x86 and
ARM instructions could be extended to POWER, but that was just trying
stuff and learning while wondering if those abstractions are general
enough and how well all the instructions match up. No one with modern
hardware and a vested interest has seriously investigated it. That's
independent of automatic vectorisation done by the compiler or libc,
and I guess it would not really be AIX-specific since it would also
apply to Linux on POWER. One of those patches is linked from this
small list of "ideas for a future PostgreSQL/AIX maintainer":

https://wiki.postgresql.org/wiki/AIX

#96Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#94)
4 attachment(s)
RE: AIX support

Hi Heikki and team,

As part of our ongoing efforts to enhance AIX platform compatibility, we’ve been running the code across all stable PostgreSQL release branches using the build farm infrastructure. All test suites, including TAP tests, are passing consistently, indicating no regressions.

https://buildfarm.postgresql.org/cgi-bin/show_history.pl?nm=douc&amp;br=REL_13_STABLE
https://buildfarm.postgresql.org/cgi-bin/show_history.pl?nm=douc&amp;br=REL_14_STABLE
https://buildfarm.postgresql.org/cgi-bin/show_history.pl?nm=douc&amp;br=REL_15_STABLE
https://buildfarm.postgresql.org/cgi-bin/show_history.pl?nm=douc&amp;br=REL_16_STABLE << Also tested locally.

To further validated the patch, we executed the build farm scripts locally for PostgreSQL 17 and 18 on AIX. The corresponding test results are attached for reference.

We value your feedback and would appreciate your insights on the attached patch. Kindly request you to review and share your comments.

Warm regards,
Sriram.

Attachments:

build-farm-19.pg18.logtext/plain; name=build-farm-19.pg18.logDownload
0001-AIX-support.v9.patchapplication/octet-stream; name=0001-AIX-support.v9.patchDownload
From 24e96d9849f3e6a6217a284aff717ad4d7f2d45a Mon Sep 17 00:00:00 2001
From: AIX-dev <postgres-ibm-aix@wwpdl.vnet.ibm.com>
Date: Wed, 3 Sep 2025 09:37:14 -0500
Subject: [PATCH] AIX support.

---
 Makefile                           |  2 -
 configure                          | 37 +++++++++++++++---
 configure.ac                       | 29 +++++++++++++-
 src/Makefile.shlib                 | 29 ++++++++++++++
 src/backend/Makefile               | 20 ++++++++++
 src/backend/port/aix/mkldexport.sh | 61 ++++++++++++++++++++++++++++++
 src/backend/utils/error/elog.c     |  2 +
 src/include/port/aix.h             |  4 ++
 src/include/storage/s_lock.h       | 48 +++--------------------
 src/makefiles/Makefile.aix         | 34 +++++++++++++++++
 src/port/strerror.c                |  2 +
 src/template/aix                   |  7 ++++
 12 files changed, 223 insertions(+), 52 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 create mode 100644 src/include/port/aix.h
 create mode 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index b363b2f2476..786424613ab 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/configure b/configure
index 1b9980226c5..abda4be633e 100755
--- a/configure
+++ b/configure
@@ -3022,6 +3022,7 @@ else
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -17204,13 +17205,37 @@ _ACEOF
 # 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
+echo "Checking for MAX ALIGN - $PORTNAME"
+if test "$PORTNAME" != "aix"; then
+    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_long -gt $MAX_ALIGNOF ; then
+      as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+    if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
+      as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+#
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+      echo "MAX ALIGN ac_cv_alignof_long"
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+      echo "MAX ALIGN ac_cv_alignof_double"
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+      echo "MAX ALIGN ac_cv_alignof_int64_t"
+    fi
 fi
 
 cat >>confdefs.h <<_ACEOF
diff --git a/configure.ac b/configure.ac
index 3e3fcfa9831..1ef58a1d7a0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ PGAC_ARG_REQ(with, template, [NAME], [override operating system template],
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -2021,7 +2022,33 @@ AC_CHECK_ALIGNOF(double)
 # 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 "$PORTNAME" != "aix"; then
+    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 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+# 
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t ; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+    fi
 
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'double'])
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index 3825af5b228..35adc4174ed 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,20 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +268,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps both shared libraries and static library, which can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +289,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +401,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +419,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 7344c8c7f5c..572f5430a60 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -63,12 +63,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -95,6 +97,24 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
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/utils/error/elog.c b/src/backend/utils/error/elog.c
index 47af743990f..f0f4ff051b5 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -905,7 +905,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/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 00000000000..7d08480c8c0
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,4 @@
+/*
+ * src/include/port/aix.h
+ */
+
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 2f73f9fcf57..ba120c08d14 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -398,56 +398,18 @@ 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 */
 
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 00000000000..4c4de8b0be7
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,34 @@
+# -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
+
+# 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/port/strerror.c b/src/port/strerror.c
index f0746517770..c46b9dc91fc 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,8 +214,10 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
 			return "ENOTEMPTY";
+#endif
 		case ENOTSOCK:
 			return "ENOTSOCK";
 #ifdef ENOTSUP
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 00000000000..bfc193348f4
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,7 @@
+# This file is referred for specific flags wrt to AIX build process like
+# cflags.
+# src/template/aix
+
+# Extra CFLAGS for code that will go into a shared library
+# With optimization, the MemSet() and MemSetAlign() perform better.
+CFLAGS_SL=" -O2 "
-- 
2.41.0

build-farm-19.pg16.logtext/plain; name=build-farm-19.pg16.logDownload
build-farm-19.pg17.logtext/plain; name=build-farm-19.pg17.logDownload
#97Vamshikrishna T
tvk1271@gmail.com
In reply to: Srirama Kucherlapati (#96)
Re: AIX support

Hi Team,

Just checking in regarding the AIX support patch shared earlier. As
mentioned, we’ve successfully run the patch across all stable PostgreSQL
releases using the build farm, and all tests—including TAP—have passed. We
also ran the build farm scripts locally for PostgreSQL 17 and 18 on AIX,
and the test results were attached for your reference.

We’d appreciate your review and feedback on the patch. Once we receive your
input, our next steps will be:

1. Address any comments or suggestions you may have.

2. Finalize the patch based on feedback.

3. Proceed with integration into the relevant branches.

Please let us know if you need any additional details or clarification.

Thanks

Vamshi.

#98Laurenz Albe
laurenz.albe@cybertec.at
In reply to: Vamshikrishna T (#97)
Re: AIX support

On Thu, 2025-09-11 at 10:50 +0530, Vamshikrishna T wrote:

Just checking in regarding the AIX support patch shared earlier.

Did you create a commitfest entry?
That way, your patch is less likely to fall between the cracks.

Yours,
Laurenz Albe

#99Vamshikrishna T
tvk1271@gmail.com
In reply to: Laurenz Albe (#98)
Re: AIX support

Thank you Laurenz for the info, Raised the review request here.

#100Bruce Momjian
bruce@momjian.us
In reply to: Vamshikrishna T (#97)
Re: AIX support

On Thu, Sep 11, 2025 at 10:50:45AM +0530, Vamshikrishna T wrote:

We’d appreciate your review and feedback on the patch. Once we receive your
input, our next steps will be:

1. Address any comments or suggestions you may have.

2. Finalize the patch based on feedback.

3. Proceed with integration into the relevant branches.        

I assume the only relevant branch is PG 19.

--
Bruce Momjian <bruce@momjian.us> https://momjian.us
EDB https://enterprisedb.com

Do not let urgent matters crowd out time for investment in the future.

#101Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Bruce Momjian (#100)
2 attachment(s)
RE: AIX support

Hi Bruce,
Please find the attached patch that is run on master branch PG19.
Kindly request you to go through and let us know your feedback.

Also attached are the builfarm results.

Warm regards,
Sriram.

Attachments:

0001-Changes-to-add-support-for-AIX.v9.pg19.patchapplication/octet-stream; name=0001-Changes-to-add-support-for-AIX.v9.pg19.patchDownload
From 407b42b1fbe562dff69820f7456dbb32a8a37d79 Mon Sep 17 00:00:00 2001
From: AIX-dev <postgres-ibm-aix@wwpdl.vnet.ibm.com>
Date: Tue, 16 Sep 2025 08:59:22 -0500
Subject: [PATCH] Changes to add support for AIX.

---
 Makefile                           |  2 -
 configure                          | 37 +++++++++++++++---
 configure.ac                       | 29 +++++++++++++-
 src/Makefile.shlib                 | 29 ++++++++++++++
 src/backend/Makefile               | 20 ++++++++++
 src/backend/port/aix/mkldexport.sh | 61 ++++++++++++++++++++++++++++++
 src/backend/utils/error/elog.c     |  2 +
 src/include/port/aix.h             |  4 ++
 src/include/storage/s_lock.h       | 48 +++--------------------
 src/makefiles/Makefile.aix         | 34 +++++++++++++++++
 src/port/strerror.c                |  2 +
 src/template/aix                   |  7 ++++
 12 files changed, 223 insertions(+), 52 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 create mode 100644 src/include/port/aix.h
 create mode 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index 8a2ec9396b6..9bc1a4ec17b 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/configure b/configure
index 507a2437c33..67cad0f5581 100755
--- a/configure
+++ b/configure
@@ -3022,6 +3022,7 @@ else
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -17204,13 +17205,37 @@ _ACEOF
 # 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
+echo "Checking for MAX ALIGN - $PORTNAME"
+if test "$PORTNAME" != "aix"; then
+    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_long -gt $MAX_ALIGNOF ; then
+      as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+    if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
+      as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+#
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+      echo "MAX ALIGN ac_cv_alignof_long"
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+      echo "MAX ALIGN ac_cv_alignof_double"
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+      echo "MAX ALIGN ac_cv_alignof_int64_t"
+    fi
 fi
 
 cat >>confdefs.h <<_ACEOF
diff --git a/configure.ac b/configure.ac
index 5f4548adc5c..a25aedacef2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ PGAC_ARG_REQ(with, template, [NAME], [override operating system template],
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -2021,7 +2022,33 @@ AC_CHECK_ALIGNOF(double)
 # 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 "$PORTNAME" != "aix"; then
+    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 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+# 
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t ; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+    fi
 
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'double'])
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index 3825af5b228..35adc4174ed 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,20 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +268,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps both shared libraries and static library, which can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +289,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +401,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +419,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 7344c8c7f5c..572f5430a60 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -63,12 +63,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -95,6 +97,24 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
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/utils/error/elog.c b/src/backend/utils/error/elog.c
index b7b9692f8c8..d0c4b7ba3ac 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -905,7 +905,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/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 00000000000..7d08480c8c0
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,4 @@
+/*
+ * src/include/port/aix.h
+ */
+
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 2f73f9fcf57..ba120c08d14 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -398,56 +398,18 @@ 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 */
 
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 00000000000..4c4de8b0be7
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,34 @@
+# -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
+
+# 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/port/strerror.c b/src/port/strerror.c
index f0746517770..c46b9dc91fc 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,8 +214,10 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
 			return "ENOTEMPTY";
+#endif
 		case ENOTSOCK:
 			return "ENOTSOCK";
 #ifdef ENOTSUP
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 00000000000..bfc193348f4
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,7 @@
+# This file is referred for specific flags wrt to AIX build process like
+# cflags.
+# src/template/aix
+
+# Extra CFLAGS for code that will go into a shared library
+# With optimization, the MemSet() and MemSetAlign() perform better.
+CFLAGS_SL=" -O2 "
-- 
2.41.0

bfarm.19.logtext/plain; name=bfarm.19.logDownload
#102Vamshikrishna T
tvk1271@gmail.com
In reply to: Srirama Kucherlapati (#101)
Re: AIX support

This patch marked 10/10 with all CI checks passing. Your feedback on the patch would be greatly appreciated.

#103Alvaro Herrera
alvherre@kurilemu.de
In reply to: Srirama Kucherlapati (#96)
Re: AIX support

On 2025-Sep-03, Srirama Kucherlapati wrote:

As part of our ongoing efforts to enhance AIX platform compatibility,
we’ve been running the code across all stable PostgreSQL release
branches using the build farm infrastructure. All test suites,
including TAP tests, are passing consistently, indicating no
regressions.

The buildfarm results you sent look good. You should definitely be
testing branch master though rather than the stable ones, because it's
not clear to me, as Bruce said, that we would really backpatch AIX
support to stable branches. (You're of course free to produce your own
packages from patched versions, in the interim).

I noticed that you add mkldexport.sh and that the makefiles use it. I
wonder if that really is necessary with the current AIX tooling (it
looks an outdated gadget).

Also, I notice that Meson supports AIX starting from version 0.56; did
you verify whether it works to build this with that?

--
Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/

#104AIX PG user
postgres-ibm-aix@wwpdl.vnet.ibm.com
In reply to: Alvaro Herrera (#103)
Re: AIX support

Hi Alvaro,
Thank you for taking your time to look into the details.

I’ve submitted the latest changes to the master branch, which are now available in the annotations section here:
https://commitfest.postgresql.org/patch/6050/
I kindly request you to review this updated patch and share your valuable feedback.

Regarding your observation about the inclusion of mkldexport.sh and its usage in the makefiles — as previously
discussed, this is a necessary workaround due to current limitations on AIX. To build shared libraries, we need to
extract symbols using this script. The relevant details are as follows:
Script Location: src/backend/port/aix/mkldexport.sh
Purpose: Implements AIX-specific changes for shared library creation using export files.
Background: Based on discussions with the internal linker team, this method is currently required to extract symbols and build shared libraries.
Reference Practices: This approach is consistent with methods used in other open-source projects such as Python and OpenBLAS:
Python
https://github.com/python/cpython/blob/main/Modules/ld_so_aix.in
OpenBLAS
https://github.com/OpenMathLib/OpenBLAS/commit/892f8ff3e55e24fda9af3f6364319cce3f60116b#diff-4011a114c75fe804332139868806cbe23f275963e4e6afa9b57e51b2b98

As for Meson builds, we did explore them earlier but encountered some issues. Here are some issues/fixes we submitted to the meson community
https://github.com/mesonbuild/meson/issues/14334
For now, we would like to focus initially on the regular gmake build since our buildfarms predominantly use it. That said, we do plan to submit Meson-related changes as a separate patch in the future.

Looking forward to your feedback.

-Sriram

#105Andres Freund
andres@anarazel.de
In reply to: AIX PG user (#104)
Re: AIX support

Hi,

On 2025-09-22 11:09:53 +0000, AIX PG user wrote:

As for Meson builds, we did explore them earlier but encountered some
issues. Here are some issues/fixes we submitted to the meson community
https://github.com/mesonbuild/meson/issues/14334 For now, we would like to
focus initially on the regular gmake build since our buildfarms
predominantly use it. That said, we do plan to submit Meson-related changes
as a separate patch in the future.

I think we should do the opposite if anything. We're planning to eventually
remove make based builds.

But I'm also suprprised - before the removal meson based builds on AIX were
working. Why didn't you just revive it as it was?

Greetings,

Andres Freund

#106AIX PG user
postgres-ibm-aix@wwpdl.vnet.ibm.com
In reply to: Andres Freund (#105)
Re: AIX support

Hi Andres,
Thank you for your feedback and for highlighting the importance of Meson-based builds.

We fully recognize the long-term objective of transitioning away from
make-based builds, and we are actively working on reviving Meson support for
AIX in alignment with that direction. However, we are currently encountering a
few errors with the revived changes, and we are working actively to
resolve them. I will keep you updated and share the finalized Meson-related
changes at the earliest opportunity.

In the meantime, we would sincerely appreciate it if you/team could review the patch
with respect to the gmake build and the associated source-level modifications
submitted on commitfest.
https://commitfest.postgresql.org/patch/6050/

Your input would be invaluable in helping us ensure the correctness and
completeness of the implementation before we proceed further. Thank you once
again for your continued guidance and support.

Warm regards,
Sriram.

#107Andres Freund
andres@anarazel.de
In reply to: AIX PG user (#106)
Re: AIX support

Hi,

On 2025-09-23 14:26:08 +0000, AIX PG user wrote:

Thank you for your feedback and for highlighting the importance of Meson-based builds.

We fully recognize the long-term objective of transitioning away from
make-based builds, and we are actively working on reviving Meson support for
AIX in alignment with that direction. However, we are currently encountering a
few errors with the revived changes, and we are working actively to
resolve them. I will keep you updated and share the finalized Meson-related
changes at the earliest opportunity.

It worked without meson changes just before the AIX support was dropped. I do
not see why you *need* that meson patch, rather it just being convenient -
after all I had made it work before, without that.

In the meantime, we would sincerely appreciate it if you/team could review the patch
with respect to the gmake build and the associated source-level modifications
submitted on commitfest.

I'd personally just not add gmake support at all, but ...

https://commitfest.postgresql.org/patch/6050/

Your input would be invaluable in helping us ensure the correctness and
completeness of the implementation before we proceed further. Thank you once
again for your continued guidance and support.

One suggestion I do have is to split the patch into a few constitutent pieces.

Greetings,

Andres Freund

#108Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Andres Freund (#107)
RE: AIX support

Hi Andres,

It worked without meson changes just before the AIX support was dropped. I do
not see why you *need* that meson patch, rather it just being convenient -
after all I had made it work before, without that.

I was able to build successfully using Meson on PostgreSQL 16. However, when attempting the same on the latest master(with the revived changes), I encountered a few errors. We are currently investigating these issues and working on the necessary fixes.
I’ll keep you updated once the Meson-related fixes are ready.

One suggestion I do have is to split the patch into a few constitutent pieces.

Thank you for the suggestion.
Splitting the patch into smaller, constituent pieces makes sense and would certainly help with clarity and review.
Appreciate your guidance.

Warm regards,
Sriram.

#109Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#108)
2 attachment(s)
RE: AIX support

Hi Andres and team,

Please find attached the patch addressing Meson build changes for AIX.
We tried to build using below meson
## meson -v
1.6.1

For the following files, the shared_module() function requires specifying the
appropriate symbol import file, which is provided via the aix_link_args
variable:
src/backend/jit/llvm/meson.build
src/backend/replication/libpqwalreceiver/meson.build
src/backend/replication/pgoutput/meson.build
src/backend/snowball/meson.build
src/backend/utils/mb/conversion_procs/meson.build

Additionally, with the latest version of Meson, when building static libraries,
the library file name must be suffixed with “_static” in the following files:
src/interfaces/ecpg/compatlib/meson.build
src/interfaces/ecpg/ecpglib/meson.build
src/interfaces/ecpg/pgtypeslib/meson.build
src/interfaces/libpq/meson.build

Main AIX changes patch - 0001-Changes-to-add-support-for-AIX.v9.pg19.patch (previously submitted one)
Meson AIX changes patch - 0001-AIX-changes-for-meson-build.patch

Looking forward to hearing your thoughts on these changes.
Your feedback on these updates is highly valued.

Thanks,
Sriram.

Attachments:

0001-AIX-changes-for-meson-build.v9.pg19.patchapplication/octet-stream; name=0001-AIX-changes-for-meson-build.v9.pg19.patchDownload
From 18dd09463342bbc836c7a8dda3a3864ceb083176 Mon Sep 17 00:00:00 2001
From: AIX-dev <postgres-ibm-aix@wwpdl.vnet.ibm.com>
Date: Wed, 15 Oct 2025 09:33:07 -0500
Subject: [PATCH] AIX changes for meson build.

---
 meson.build                                   | 25 +++++++++++--
 src/backend/jit/llvm/meson.build              |  6 ++++
 src/backend/meson.build                       | 36 ++++++++++++++++++-
 .../replication/libpqwalreceiver/meson.build  |  8 ++++-
 src/backend/replication/pgoutput/meson.build  |  6 ++++
 src/backend/snowball/meson.build              |  8 ++++-
 .../utils/mb/conversion_procs/meson.build     |  6 ++++
 src/include/port/aix.h                        | 22 ++++++++++++
 src/interfaces/ecpg/compatlib/meson.build     |  8 ++++-
 src/interfaces/ecpg/ecpglib/meson.build       |  7 +++-
 src/interfaces/ecpg/pgtypeslib/meson.build    |  7 +++-
 src/interfaces/libpq/meson.build              | 14 ++++++--
 src/tools/gen_export.pl                       | 13 +++++--
 13 files changed, 154 insertions(+), 12 deletions(-)

diff --git a/meson.build b/meson.build
index a87eb913fff..27c0f38ebc8 100644
--- a/meson.build
+++ b/meson.build
@@ -198,7 +198,26 @@ endif
 # that purpose.
 portname = host_system
 
-if host_system == 'cygwin'
+if host_system == 'aix'
+  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'
+
+  # M:SRE sets a flag indicating that an object is a shared library. Seems to
+  # work in some circumstances without, but required in others.
+  ldflags_sl += '-Wl,-bM:SRE'
+  ldflags_be += '-Wl,-brtllib'
+
+  # Native memset() is faster, tested on:
+  # - AIX 5.1 and 5.2, XLC 6.0 (IBM's cc)
+  # - AIX 5.3 ML3, gcc 4.0.1
+  #memset_loop_limit = 0
+
+elif host_system == 'cygwin'
   sema_kind = 'unnamed_posix'
   cppflags += '-D_GNU_SOURCE'
   dlsuffix = '.dll'
@@ -1775,7 +1794,9 @@ endforeach
 # 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')
+  if host_system != 'aix'
+    error('alignment of int64_t is greater than the alignment of double')
+  endif
 endif
 cdata.set('MAXIMUM_ALIGNOF', alignof_double)
 
diff --git a/src/backend/jit/llvm/meson.build b/src/backend/jit/llvm/meson.build
index 805fbd69006..f83db9d0d6e 100644
--- a/src/backend/jit/llvm/meson.build
+++ b/src/backend/jit/llvm/meson.build
@@ -29,11 +29,17 @@ if host_system == 'windows'
     '--FILEDESC', 'llvmjit - JIT using LLVM',])
 endif
 
+aix_link_args= []
+if host_machine.system() == 'aix'
+  aix_link_args = ['-Wl,-bI:' + meson.project_build_root() + '/src/backend/postgres.imp']
+endif
+
 llvmjit = shared_module('llvmjit',
   llvmjit_sources,
   kwargs: pg_mod_args + {
     'dependencies': pg_mod_args['dependencies'] + [llvm],
     'cpp_args': pg_mod_args['cpp_args'] + llvm.get_variable(configtool: 'cxxflags').split(),
+    link_args: aix_link_args
   }
 )
 
diff --git a/src/backend/meson.build b/src/backend/meson.build
index b831a541652..47c0eae1309 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -125,6 +125,40 @@ if host_system == 'windows'
     '--FILEDESC', 'PostgreSQL Server',])
 endif
 
+if host_system == 'aix'
+find_obj_files = find_program('sh', required: true)
+
+cb_o = custom_target(
+   'SUBSYS.o',
+    input: [postgres_lib.extract_all_objects(recursive: true)],
+    output: 'SUBSYS.o',
+   command: ['ld', '-r', '-o', '@OUTPUT@', '@INPUT@'],
+   install: false,
+  )
+postgres_imp = 'postgres.imp'
+
+generate_import_file = custom_target('generate_import_file', output: postgres_imp, command: ['sh', '-c', '../src/backend/port/aix/mkldexport.sh src/backend/SUBSYS.o . > src/backend/postgres.imp'], build_by_default: true, depends: [cb_o])
+
+my_dep = declare_dependency(sources:[generate_import_file])
+#libpq_aix_deps += my_dep
+backend_link_depends += generate_import_file
+
+endif
+
+if host_system == 'aix'
+ postgres = executable('postgres',
+   backend_input,
+   sources: post_export_backend_sources,
+   objects: backend_objs,
+   link_args: backend_link_args + ['-Wl,-bE:src/backend/postgres.imp'],
+   link_with: backend_link_with,
+   link_depends: backend_link_depends,
+   export_dynamic: true,
+   implib: 'postgres',
+   dependencies: backend_build_deps + [my_dep],
+   kwargs: default_bin_args,
+)
+else
 postgres = executable('postgres',
   backend_input,
   sources: post_export_backend_sources,
@@ -137,7 +171,7 @@ postgres = executable('postgres',
   dependencies: backend_build_deps,
   kwargs: default_bin_args,
 )
-
+endif
 backend_targets += postgres
 
 pg_mod_c_args = cflags_mod
diff --git a/src/backend/replication/libpqwalreceiver/meson.build b/src/backend/replication/libpqwalreceiver/meson.build
index 2150f31cfa3..135062244d4 100644
--- a/src/backend/replication/libpqwalreceiver/meson.build
+++ b/src/backend/replication/libpqwalreceiver/meson.build
@@ -10,12 +10,18 @@ if host_system == 'windows'
     '--FILEDESC', 'libpqwalreceiver - receive WAL during streaming replication',])
 endif
 
+aix_link_args= []
+if host_machine.system() == 'aix'
+  aix_link_args = ['-Wl,-bI:' + meson.project_build_root() + '/src/backend/postgres.imp']
+endif
+
 libpqwalreceiver = shared_module('pqwalreceiver',
   libpqwalreceiver_sources,
   kwargs: pg_mod_args + {
     'name_prefix': 'lib',
     'dependencies': pg_mod_args['dependencies'] + [libpq],
-  }
+  },
+  link_args: aix_link_args
 )
 
 backend_targets += libpqwalreceiver
diff --git a/src/backend/replication/pgoutput/meson.build b/src/backend/replication/pgoutput/meson.build
index 14e2f03ada0..9fbd035988b 100644
--- a/src/backend/replication/pgoutput/meson.build
+++ b/src/backend/replication/pgoutput/meson.build
@@ -10,9 +10,15 @@ if host_system == 'windows'
     '--FILEDESC', 'pgoutput - standard logical replication output plugin',])
 endif
 
+aix_link_args= []
+if host_machine.system() == 'aix'
+  aix_link_args = ['-Wl,-bI:' + meson.project_build_root() + '/src/backend/postgres.imp']
+endif
+
 pgoutput = shared_module('pgoutput',
   pgoutput_sources,
   kwargs: pg_mod_args,
+  link_args: aix_link_args
 )
 
 backend_targets += pgoutput
diff --git a/src/backend/snowball/meson.build b/src/backend/snowball/meson.build
index 8e73d9d7368..92b3934bcc6 100644
--- a/src/backend/snowball/meson.build
+++ b/src/backend/snowball/meson.build
@@ -66,12 +66,18 @@ if host_system == 'windows'
     '--FILEDESC', 'snowball - natural language stemmers',])
 endif
 
+aix_link_args= []
+if host_machine.system() == 'aix'
+  aix_link_args = ['-Wl,-bI:' + meson.project_build_root() + '/src/backend/postgres.imp']
+endif
+
 dict_snowball = shared_module('dict_snowball',
   dict_snowball_sources,
   c_pch: pch_postgres_h,
   kwargs: pg_mod_args + {
     'include_directories': [stemmer_inc],
-  }
+  },
+  link_args: aix_link_args
 )
 
 snowball_create = custom_target('snowball_create',
diff --git a/src/backend/utils/mb/conversion_procs/meson.build b/src/backend/utils/mb/conversion_procs/meson.build
index 0e8273e0b61..a76c4993055 100644
--- a/src/backend/utils/mb/conversion_procs/meson.build
+++ b/src/backend/utils/mb/conversion_procs/meson.build
@@ -38,8 +38,14 @@ foreach encoding, sources : encodings
       '--NAME', encoding])
   endif
 
+  aix_link_args= []
+  if host_machine.system() == 'aix'
+    aix_link_args = ['-Wl,-bI:' + meson.project_build_root() + '/src/backend/postgres.imp']
+  endif
+
   backend_targets += shared_module(encoding,
     source_files,
     kwargs: pg_mod_args,
+    link_args: aix_link_args
   )
 endforeach
diff --git a/src/include/port/aix.h b/src/include/port/aix.h
index 7d08480c8c0..450e68da657 100644
--- a/src/include/port/aix.h
+++ b/src/include/port/aix.h
@@ -2,3 +2,25 @@
  * src/include/port/aix.h
  */
 
+/* These changes are required for the meson changes as the autoconf is not run
+ * and corresponding  key feature macros are defined here.
+ */
+ 
+#ifdef _AIX
+#ifndef PGDLLIMPORT
+#define PGDLLIMPORT
+#endif  /* PGDLLIMPORT */
+typedef float float4;
+typedef double float8;
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+#define pg_noreturn _Noreturn
+#elif defined(__GNUC__)
+#define pg_noreturn __attribute__((noreturn))
+#else
+#define pg_noreturn
+#endif
+
+#include <stdbool.h>
+
+#endif  /*_AIX */
diff --git a/src/interfaces/ecpg/compatlib/meson.build b/src/interfaces/ecpg/compatlib/meson.build
index 56e0a21651b..d199002f7ed 100644
--- a/src/interfaces/ecpg/compatlib/meson.build
+++ b/src/interfaces/ecpg/compatlib/meson.build
@@ -15,8 +15,14 @@ if host_system == 'windows'
     '--FILEDESC', 'ECPG compat - compatibility library for ECPG',])
 endif
 
+libname = 'libecpg_compat'
+if host_machine.system() == 'aix'
+  libname += '_static'
+endif
+
+
 # see src/interfaces/libpq/meson.build
-ecpg_compat_st = static_library('libecpg_compat',
+ecpg_compat_st = static_library(libname,
   ecpg_compat_sources,
   include_directories: ecpg_compat_inc,
   c_args: ecpg_compat_c_args,
diff --git a/src/interfaces/ecpg/ecpglib/meson.build b/src/interfaces/ecpg/ecpglib/meson.build
index 8f478c6a73e..448a0038a71 100644
--- a/src/interfaces/ecpg/ecpglib/meson.build
+++ b/src/interfaces/ecpg/ecpglib/meson.build
@@ -24,8 +24,13 @@ if host_system == 'windows'
     '--FILEDESC', 'ECPG - embedded SQL in C',])
 endif
 
+libname = 'libecpg'
+if host_machine.system() == 'aix'
+  libname += '_static'
+endif
+
 # see src/interfaces/libpq/meson.build
-ecpglib_st = static_library('libecpg',
+ecpglib_st = static_library(libname,
   ecpglib_sources,
   include_directories: ecpglib_inc,
   c_args: ecpglib_c_args,
diff --git a/src/interfaces/ecpg/pgtypeslib/meson.build b/src/interfaces/ecpg/pgtypeslib/meson.build
index 02301ec9acb..6421930dc05 100644
--- a/src/interfaces/ecpg/pgtypeslib/meson.build
+++ b/src/interfaces/ecpg/pgtypeslib/meson.build
@@ -20,8 +20,13 @@ if host_system == 'windows'
     '--FILEDESC', 'pgtypes - library for data type mapping',])
 endif
 
+libname = 'libpgtypes'
+if host_machine.system() == 'aix'
+  libname += '_static'
+endif
+
 # see src/interfaces/libpq/meson.build
-ecpg_pgtypes_st = static_library('libpgtypes',
+ecpg_pgtypes_st = static_library(libname,
   ecpg_pgtypes_sources,
   include_directories: ecpg_pgtypes_inc,
   c_args: ecpg_pgtypes_c_args,
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index a74e885b169..3e96d3f073e 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -49,6 +49,11 @@ libpq_c_args = ['-DSO_MAJOR_VERSION=5']
 # The OAuth implementation differs depending on the type of library being built.
 libpq_so_c_args = ['-DUSE_DYNAMIC_OAUTH']
 
+libname = 'libpq'
+if host_machine.system() == 'aix'
+  libname += '_static'
+endif
+
 # Not using both_libraries() here as
 # 1) resource files should only be in the shared library
 # 2) we want the .pc file to include a dependency to {pgport,common}_static for
@@ -57,7 +62,7 @@ libpq_so_c_args = ['-DUSE_DYNAMIC_OAUTH']
 # We could try to avoid building the source files twice, but it probably adds
 # more complexity than its worth (reusing object files requires also linking
 # to the library on windows or breaks precompiled headers).
-libpq_st = static_library('libpq',
+libpq_st = static_library(libname,
   libpq_sources,
   include_directories: [libpq_inc],
   c_args: libpq_c_args,
@@ -66,6 +71,11 @@ libpq_st = static_library('libpq',
   kwargs: default_lib_args,
 )
 
+aix_link_args = []
+if host_machine.system() == 'aix'
+  aix_link_args = ['-Wl,-bI:' + export_file.full_path()]
+endif
+
 libpq_so = shared_library('libpq',
   libpq_sources + libpq_so_sources,
   include_directories: [libpq_inc, postgres_inc],
@@ -76,7 +86,7 @@ libpq_so = shared_library('libpq',
   darwin_versions: ['5', '5.' + pg_version_major.to_string()],
   dependencies: [frontend_shlib_code, libpq_deps],
   link_depends: export_file,
-  link_args: export_fmt.format(export_file.full_path()),
+  link_args: [export_fmt.format(export_file.full_path()), aix_link_args],
   kwargs: default_lib_args,
 )
 
diff --git a/src/tools/gen_export.pl b/src/tools/gen_export.pl
index 86a7742b369..19c8b60560f 100644
--- a/src/tools/gen_export.pl
+++ b/src/tools/gen_export.pl
@@ -18,9 +18,10 @@ 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";
+	die "$0: $format is not yet handled (only darwin, gnu, win, aix are)\n";
 }
 
 open(my $input_handle, '<', $input)
@@ -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.41.0

0001-Changes-to-add-support-for-AIX.v9.pg19.patchapplication/octet-stream; name=0001-Changes-to-add-support-for-AIX.v9.pg19.patchDownload
From 407b42b1fbe562dff69820f7456dbb32a8a37d79 Mon Sep 17 00:00:00 2001
From: AIX-dev <postgres-ibm-aix@wwpdl.vnet.ibm.com>
Date: Tue, 16 Sep 2025 08:59:22 -0500
Subject: [PATCH] Changes to add support for AIX.

---
 Makefile                           |  2 -
 configure                          | 37 +++++++++++++++---
 configure.ac                       | 29 +++++++++++++-
 src/Makefile.shlib                 | 29 ++++++++++++++
 src/backend/Makefile               | 20 ++++++++++
 src/backend/port/aix/mkldexport.sh | 61 ++++++++++++++++++++++++++++++
 src/backend/utils/error/elog.c     |  2 +
 src/include/port/aix.h             |  4 ++
 src/include/storage/s_lock.h       | 48 +++--------------------
 src/makefiles/Makefile.aix         | 34 +++++++++++++++++
 src/port/strerror.c                |  2 +
 src/template/aix                   |  7 ++++
 12 files changed, 223 insertions(+), 52 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 create mode 100644 src/include/port/aix.h
 create mode 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index 8a2ec9396b6..9bc1a4ec17b 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/configure b/configure
index 507a2437c33..67cad0f5581 100755
--- a/configure
+++ b/configure
@@ -3022,6 +3022,7 @@ else
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -17204,13 +17205,37 @@ _ACEOF
 # 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
+echo "Checking for MAX ALIGN - $PORTNAME"
+if test "$PORTNAME" != "aix"; then
+    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_long -gt $MAX_ALIGNOF ; then
+      as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+    if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
+      as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+#
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+      echo "MAX ALIGN ac_cv_alignof_long"
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+      echo "MAX ALIGN ac_cv_alignof_double"
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+      echo "MAX ALIGN ac_cv_alignof_int64_t"
+    fi
 fi
 
 cat >>confdefs.h <<_ACEOF
diff --git a/configure.ac b/configure.ac
index 5f4548adc5c..a25aedacef2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ PGAC_ARG_REQ(with, template, [NAME], [override operating system template],
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -2021,7 +2022,33 @@ AC_CHECK_ALIGNOF(double)
 # 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 "$PORTNAME" != "aix"; then
+    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 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+# 
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t ; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+    fi
 
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'double'])
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index 3825af5b228..35adc4174ed 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,20 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +268,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps both shared libraries and static library, which can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +289,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +401,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +419,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 7344c8c7f5c..572f5430a60 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -63,12 +63,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -95,6 +97,24 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
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/utils/error/elog.c b/src/backend/utils/error/elog.c
index b7b9692f8c8..d0c4b7ba3ac 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -905,7 +905,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/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 00000000000..7d08480c8c0
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,4 @@
+/*
+ * src/include/port/aix.h
+ */
+
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 2f73f9fcf57..ba120c08d14 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -398,56 +398,18 @@ 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 */
 
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 00000000000..4c4de8b0be7
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,34 @@
+# -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
+
+# 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/port/strerror.c b/src/port/strerror.c
index f0746517770..c46b9dc91fc 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,8 +214,10 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
 			return "ENOTEMPTY";
+#endif
 		case ENOTSOCK:
 			return "ENOTSOCK";
 #ifdef ENOTSUP
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 00000000000..bfc193348f4
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,7 @@
+# This file is referred for specific flags wrt to AIX build process like
+# cflags.
+# src/template/aix
+
+# Extra CFLAGS for code that will go into a shared library
+# With optimization, the MemSet() and MemSetAlign() perform better.
+CFLAGS_SL=" -O2 "
-- 
2.41.0

#110Peter Eisentraut
peter@eisentraut.org
In reply to: Srirama Kucherlapati (#109)
Re: AIX support

On 15.10.25 17:58, Srirama Kucherlapati wrote:

Main AIX changes patch - 0001-Changes-to-add-support-for-
AIX.v9.pg19.patch (previously submitted one)

Meson AIX changes patch - 0001-AIX-changes-for-meson-build.patch

Looking forward to hearing your thoughts on these changes.

Your feedback on these updates is highly valued.

The largest problem I see in this patch set is that you are making
unexplained changes in src/include/storage/s_lock.h. The code that you
are changing does not only affect AIX but also PPC with other operating
systems. AFAICT, the change you are proposing does not correspond to
the commit that removed AIX support.

Maybe the proposed changes are beneficial for other operating systems as
well. But in that case, propose this as a separate patch in a separate
thread, with supporting information (and probably benchmarks in this case).

If not, then you need to find a way to make this work on AIX without
materially changing the code that exists for already-supported operating
systems.

#111AIX PG user
postgres-ibm-aix@wwpdl.vnet.ibm.com
In reply to: Peter Eisentraut (#110)
Re: AIX support

Hi Peter,
Thank you for your comments.

We’ve had a few discussions in the past regarding the changes related to the
spin lock. Some of those conversations stemmed from this thread:
"/messages/by-id/95a44be0-b2f8-464a-8984-771d892b1cac@iki.fi&quot;
The earlier assembly code was generic across the PPC platform. However, based
on previous discussions, we transitioned to using GCC-specific routines to
enhance platform independence and maintain generality.

These are the comments I have added, let me know if you need more info here.
    +/* On PPC, use the compiler provided Built-in functions for atomic memory
    + * exchange operations.
    + */

For reference, here are some benchmark statistics we gathered earlier:
"/messages/by-id/CY8PR15MB5602EB54EFE30D4C21F061BEDB722@CY8PR15MB5602.namprd15.prod.outlook.com&quot;

I'll run some more benchmarking on this sync_lock and submit the results.
Meanwhile, it would be helpful if you and your team could take a look at the remaining changes.

Thank you,
Sriram.

The new status of this patch is: Needs review

#112AIX PG user
postgres-ibm-aix@wwpdl.vnet.ibm.com
In reply to: AIX PG user (#111)
Re: AIX support

Hi Team,
We look forward to your comments and kindly request you to share your feedback on the proposed changes(in the annotations).
Your input is greatly appreciated and will help us refine the solution while ensuring all aspects are thoughtfully addressed.
Thank you in advance for your time and support.

-Sriram.

#113Heikki Linnakangas
hlinnaka@iki.fi
In reply to: AIX PG user (#111)
Re: AIX support

On 16/10/2025 18:28, AIX PG user wrote:

diff --git a/src/template/aix b/src/template/aix                                                                                                                           
new file mode 100644                                                                                                                                                       
index 00000000000..bfc193348f4                                                                                                                                             
--- /dev/null                                                                                                                                                              
+++ b/src/template/aix                                                                                                                                                     
@@ -0,0 +1,7 @@                                                                                                                                                            
+# This file is referred for specific flags wrt to AIX build process like                                                                                                  
+# cflags.                                                                                                                                                                 
+# src/template/aix                                                                                                                                                        
+                                                                                                                                                                          
+# Extra CFLAGS for code that will go into a shared library                                                                                                                
+# With optimization, the MemSet() and MemSetAlign() perform better.                                                                                                       
+CFLAGS_SL=" -O2 "                                                                                                                                                         
--     

This looks weird. Sure, "-O2" makes things faster, but we shouldn't
force that here. If you want optimizations, you should use pass
CFLAGS="-O2" or CFLAGS="-O3" to configure. And why the special mention
of MemSet() and MemSetAlign()?

@@ -95,6 +97,24 @@ libpostgres.a: postgres

endif # win32

+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
$(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport

I see there's some references to MAKE_EXPORTS in src/backend/Makefile.
They seem related to MKLDEXPORT, but we never set MAKE_EXPORTS. Are they
still needed?

- Heikki

#114AIX PG user
postgres-ibm-aix@wwpdl.vnet.ibm.com
In reply to: Heikki Linnakangas (#113)
Re: AIX support

Hi Heikki,
Thank you for your feedback.

This looks weird. Sure, "-O2" makes things faster, but we shouldn't
force that here. If you want optimizations, you should use pass
CFLAGS="-O2" or CFLAGS="-O3" to configure. And why the special mention
of MemSet() and MemSetAlign()?

I have removed these.

I see there's some references to MAKE_EXPORTS in src/backend/Makefile.
They seem related to MKLDEXPORT, but we never set MAKE_EXPORTS. Are they
still needed?

If MAKE_EXPORTS is not being used by any platforms other than AIX, we can
consider removing it. However, I’m not entirely certain whether it might still
be required elsewhere. Since these changes appear to be general and not
strictly AIX-specific, would it be fine to submit them as a separate
patch?

Looking forward to your continued support and guidance.

- Sriram.

#115Peter Eisentraut
peter@eisentraut.org
In reply to: Srirama Kucherlapati (#109)
Re: AIX support

On 15.10.25 17:58, Srirama Kucherlapati wrote:

Hi Andres and team,

Please find attached the patch addressing Meson build changes for AIX.

We tried to build using below meson

## meson -v

1.6.1

For the following files, the shared_module() function requires
specifying the

appropriate symbol import file, which is provided via the aix_link_args

variable:

src/backend/jit/llvm/meson.build

src/backend/replication/libpqwalreceiver/meson.build

src/backend/replication/pgoutput/meson.build

src/backend/snowball/meson.build

src/backend/utils/mb/conversion_procs/meson.build

Additionally, with the latest version of Meson, when building static
libraries,

the library file name must be suffixed with “_static” in the following
files:

src/interfaces/ecpg/compatlib/meson.build

src/interfaces/ecpg/ecpglib/meson.build

src/interfaces/ecpg/pgtypeslib/meson.build

src/interfaces/libpq/meson.build

It is not going to be acceptable to sprinkle this much AIX-specific code
around. Those changes to the meson.build files were not needed before
AIX support was removed. You should find a way to do it without these
changes.

The changes in src/include/port/aix.h in your patch don't make sense.
This indicates that you are doing something wrong in your local builds.
Please fix that.

#116AIX PG user
postgres-ibm-aix@wwpdl.vnet.ibm.com
In reply to: Peter Eisentraut (#115)
Re: AIX support

Hi Peter,

Those changes to the meson.build files were not needed before
AIX support was removed. You should find a way to do it without these
changes.

The change was necessary to ensure that the import file used during the static
PostgreSQL library build begins with the required #! directive and includes the
correct symbol references from the object files. This structure is essential
for compatibility with AIX's linking behaviour, which relies on explicitly
defined symbol import files during static linking. Without this adjustment, the
build process may fail or result in incomplete symbol resolution, particularly
on AIX systems. By aligning the import file format and symbol inclusion with
platform-specific requirements.

We referred to previously removed code that handled similar logic and found it
to be effective. Based on this, we plan to revert the changes in the affected
files and proceed with a more robust solution.

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=0b16bb8776bb834eb1ef8204ca95dd7667ab948b#patch11
src/backend/jit/llvm/meson.build
src/backend/replication/libpqwalreceiver/meson.build
src/backend/replication/pgoutput/meson.build
src/backend/snowball/meson.build
src/backend/utils/mb/conversion_procs/meson.build

Regarding the archiving of shared and static libraries, the latest version of
Meson raises a conflict as both targets have the same name. This issue
arises because, on AIX, both shared and static libraries are named as same
archive, which leads to naming collisions during the build process. We
would still need the below changes.

src/interfaces/ecpg/compatlib/meson.build
src/interfaces/ecpg/ecpglib/meson.build
ecpglib_st = static_library(libname,
src/interfaces/ecpg/pgtypeslib/meson.build
ecpg_pgtypes_st = static_library(libname,
src/interfaces/libpq/meson.build
libpq_st = static_library(libname

The changes in src/include/port/aix.h in your patch don't make sense.
This indicates that you are doing something wrong in your local builds.
Please fix that.

We had to do these changes in the src/include/c.h,
As the MACROS, are getting undefined by the below sys header files.

We made changes to src/include/c.h because certain macros were being
undefined by the system header files listed below. To address this issue,
we introduced updates in aix.h.
+#ifndef PGDLLIMPORT +#define PGDLLIMPORT

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

We are continuing to analyze the impact of these changes and will refine
the solution as needed. Once finalized, we will submit the updated changes accordingly.

-Sriram.

#117Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: AIX PG user (#116)
1 attachment(s)
RE: AIX support

Hi Team, (Peter/Heikki)

I have implemented the requested modifications in the latest patch. Below are the key technical updates:

• Meson Build Configuration: Adjusted below meson.build scripts to incorporate the suggested changes, ensuring proper dependency resolution and improved build consistency.

Removed the AIX changes in the below from the previous patch.

src/backend/jit/llvm/meson.build
src/backend/replication/libpqwalreceiver/meson.build
src/backend/replication/pgoutput/meson.build
src/backend/snowball/meson.build
src/backend/utils/mb/conversion_procs/meson.build

Added the static_library() changes.

Regarding the archiving of shared and static libraries, the latest version of
Meson raises a conflict as both targets have the same name. This issue
arises because, on AIX, both shared and static libraries are named as same
archive, which leads to naming collisions during the build process. We
would still need the below changes.

src/interfaces/ecpg/compatlib/meson.build
src/interfaces/ecpg/ecpglib/meson.build
src/interfaces/ecpg/pgtypeslib/meson.build
src/interfaces/libpq/meson.build

• CFLAGS Optimization Removal: Removed high-level optimization flags from CFLAGS to prevent unpredictable behaviour and maintain stability during compilation.

I would greatly appreciate it if you could review the patch and share your feedback or any additional recommendations.

Apologies for the delayed response; I was occupied with other tasks.

Your insights are greatly appreciated and will help enhance the patch.

Warm regards,
-Sriram.

Attachments:

0001-Support-for-AIX.pg19.v10.patchapplication/octet-stream; name=0001-Support-for-AIX.pg19.v10.patchDownload
From 98af27c6331c4fe161f7cab5c16768587f7fcb9a Mon Sep 17 00:00:00 2001
From: AIX-dev <postgres-ibm-aix@wwpdl.vnet.ibm.com>
Date: Tue, 9 Dec 2025 09:49:31 -0600
Subject: [PATCH] Support for AIX.

---
 Makefile                                   |  2 -
 configure                                  | 37 ++++++++++---
 configure.ac                               | 29 +++++++++-
 meson.build                                | 27 ++++++++--
 src/Makefile.shlib                         | 29 ++++++++++
 src/backend/Makefile                       | 20 +++++++
 src/backend/meson.build                    | 18 +++++++
 src/backend/port/aix/mkldexport.sh         | 61 ++++++++++++++++++++++
 src/backend/utils/error/elog.c             |  2 +
 src/include/port/aix.h                     | 26 +++++++++
 src/include/storage/s_lock.h               | 52 +++---------------
 src/interfaces/ecpg/compatlib/meson.build  |  2 +-
 src/interfaces/ecpg/ecpglib/meson.build    |  2 +-
 src/interfaces/ecpg/pgtypeslib/meson.build |  2 +-
 src/interfaces/libpq/meson.build           |  2 +-
 src/makefiles/Makefile.aix                 | 34 ++++++++++++
 src/port/strerror.c                        |  2 +
 src/template/aix                           |  6 +++
 src/tools/gen_export.pl                    | 11 +++-
 19 files changed, 300 insertions(+), 64 deletions(-)
 create mode 100755 src/backend/port/aix/mkldexport.sh
 create mode 100644 src/include/port/aix.h
 create mode 100644 src/makefiles/Makefile.aix
 create mode 100644 src/template/aix

diff --git a/Makefile b/Makefile
index 8a2ec9396b6..9bc1a4ec17b 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,6 @@
 
 # AIX make defaults to building *every* target of the first rule.  Start with
 # a single-target, empty rule to make the other targets non-default.
-# (We don't support AIX anymore, but if someone tries to build on AIX anyway,
-# at least they'll get the instructions to run 'configure' first.)
 all:
 
 all check install installdirs installcheck installcheck-parallel uninstall clean distclean maintainer-clean dist distcheck world check-world install-world installcheck-world:
diff --git a/configure b/configure
index 3a0ed11fa8e..c4749a8e5b6 100755
--- a/configure
+++ b/configure
@@ -3020,6 +3020,7 @@ else
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -17006,13 +17007,37 @@ _ACEOF
 # 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
+echo "Checking for MAX ALIGN - $PORTNAME"
+if test "$PORTNAME" != "aix"; then
+    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_long -gt $MAX_ALIGNOF ; then
+      as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+    if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
+      as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+#
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+      echo "MAX ALIGN ac_cv_alignof_long"
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+      echo "MAX ALIGN ac_cv_alignof_double"
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+      echo "MAX ALIGN ac_cv_alignof_int64_t"
+    fi
 fi
 
 cat >>confdefs.h <<_ACEOF
diff --git a/configure.ac b/configure.ac
index c2413720a18..7f1530df2b1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ PGAC_ARG_REQ(with, template, [NAME], [override operating system template],
 # --with-template not given
 
 case $host_os in
+  aix*) template=aix ;;
   cygwin*|msys*) template=cygwin ;;
   darwin*) template=darwin ;;
 dragonfly*) template=netbsd ;;
@@ -2006,7 +2007,33 @@ AC_CHECK_ALIGNOF(double)
 # 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 "$PORTNAME" != "aix"; then
+    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 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+    fi
+else
+# The AIX 'power' alignment rules apply the natural alignment of the "first
+# member" if it is of a floating-point data type (or is an aggregate whose
+# recursively "first" member or element is such a type). The alignment
+# associated with these types for subsequent members use an alignment value
+# where the floating-point data type is considered to have 4-byte alignment.
+# More info
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+# 
+# The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+# alignement across platforms the max alignment of long should be considered.
+    MAX_ALIGNOF=$ac_cv_alignof_long
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_double ; then
+      MAX_ALIGNOF=$ac_cv_alignof_double
+    fi
+    if test $MAX_ALIGNOF -lt $ac_cv_alignof_int64_t ; then
+      MAX_ALIGNOF="$ac_cv_alignof_int64_t"
+    fi
 
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'double'])
diff --git a/meson.build b/meson.build
index 6e7ddd74683..304a9184075 100644
--- a/meson.build
+++ b/meson.build
@@ -206,6 +206,25 @@ if host_system == 'cygwin'
   mod_link_with_name = 'lib@0@.a'
   mod_link_with_dir = 'libdir'
 
+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 += '-D_GNU_SOURCE'
+
+  # M:SRE sets a flag indicating that an object is a shared library. Seems to
+  # work in some circumstances without, but required in others.
+  ldflags_sl += '-Wl,-bM:SRE'
+  ldflags_be += '-Wl,-brtllib'
+
+  # Native memset() is faster, tested on:
+  memset_loop_limit = 0
+
 elif host_system == 'darwin'
   dlsuffix = '.dylib'
   library_path_var = 'DYLD_LIBRARY_PATH'
@@ -1766,9 +1785,9 @@ endforeach
 # 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
+#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))
@@ -1820,7 +1839,7 @@ if cc.links('''
   if not meson.is_cross_build()
     r = cc.run('''
     /* This must match the corresponding code in c.h: */
-    #if defined(__GNUC__)
+    #if defined(__GNUC__) || defined(__IBMC__)
     #define pg_attribute_aligned(a) __attribute__((aligned(a)))
     #elif defined(_MSC_VER)
     #define pg_attribute_aligned(a) __declspec(align(a))
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index 3825af5b228..35adc4174ed 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -106,6 +106,20 @@ ifdef SO_MAJOR_VERSION
 override CPPFLAGS += -DSO_MAJOR_VERSION=$(SO_MAJOR_VERSION)
 endif
 
+ifeq ($(PORTNAME), aix)
+  LINK.shared		= $(COMPILER)
+  ifdef SO_MAJOR_VERSION
+    shlib		= lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
+  endif
+  haslibarule   = yes
+  # $(exports_file) is also usable as an import file
+  exports_file		= lib$(NAME).exp
+  BUILD.exports		= ( echo '\#! $(shlib)'; $(AWK) '/^[^\#]/ {printf "%s\n",$$1}' $< ) > $@
+  ifneq (,$(SHLIB_EXPORTS))
+    LINK.shared		+= -Wl,-bE:$(exports_file)
+  endif
+endif
+
 ifeq ($(PORTNAME), darwin)
   ifdef soname
     # linkable library
@@ -254,6 +268,14 @@ $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	touch $@
 endif #haslibarule
 
+# AIX wraps both shared libraries and static library, which can be used both
+# for static and shared linking
+ifeq ($(PORTNAME), aix)
+$(stlib): $(shlib)
+	rm -f $(stlib)
+	$(AR) $(AROPT) $(stlib) $(shlib)
+endif # aix
+
 ifeq (,$(filter cygwin win32,$(PORTNAME)))
 
 # Normal case
@@ -267,8 +289,11 @@ ifneq ($(shlib), $(shlib_major))
 endif
 # Make sure we have a link to a name without any version numbers
 ifneq ($(shlib), $(shlib_bare))
+# except on AIX, where that's not a thing
+ifneq ($(PORTNAME), aix)
 	rm -f $(shlib_bare)
 	$(LN_S) $(shlib) $(shlib_bare)
+endif # aix
 endif # shlib_bare
 endif # shlib_major
 
@@ -376,6 +401,9 @@ install-lib-static: $(stlib) installdirs-lib
 
 install-lib-shared: $(shlib) installdirs-lib
 ifdef soname
+# we don't install $(shlib) on AIX
+# (see http://archives.postgresql.org/message-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at)
+ifneq ($(PORTNAME), aix)
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/$(shlib)'
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -391,6 +419,7 @@ ifneq ($(shlib), $(shlib_bare))
 endif
 endif # not win32
 endif # not cygwin
+endif # not aix
 ifneq (,$(findstring $(PORTNAME),win32 cygwin))
 	$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
 endif
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 7344c8c7f5c..572f5430a60 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -63,12 +63,14 @@ all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
+ifneq ($(PORTNAME), aix)
 
 postgres: $(OBJS)
 	$(CC) $(CFLAGS) $(call expand_subsys,$^) $(LDFLAGS) $(LIBS) -o $@
 
 endif
 endif
+endif
 
 ifeq ($(PORTNAME), cygwin)
 
@@ -95,6 +97,24 @@ libpostgres.a: postgres
 
 endif # win32
 
+ifeq ($(PORTNAME), aix)
+
+postgres: $(POSTGRES_IMP)
+	$(CC) $(CFLAGS) $(call expand_subsys,$(OBJS)) $(LDFLAGS) -Wl,-bE:$(top_builddir)/src/backend/$(POSTGRES_IMP) $(LIBS) -Wl,-brtllib -o $@
+
+# Linking to a single .o with -r is a lot faster than building a .a or passing
+# all objects to MKLDEXPORT.
+#
+# It looks alluring to use $(CC) -r instead of ld -r, but that doesn't
+# trivially work with gcc, due to gcc specific static libraries linked in with
+# -r.
+$(POSTGRES_IMP): $(OBJS)
+	ld -r -o SUBSYS.o $(call expand_subsys,$^)
+	$(MKLDEXPORT) SUBSYS.o . > $@
+	@rm -f SUBSYS.o
+
+endif # aix
+
 $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
diff --git a/src/backend/meson.build b/src/backend/meson.build
index b831a541652..4838f245ab3 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/utils/error/elog.c b/src/backend/utils/error/elog.c
index 29643c51439..1c933b5afad 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/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 00000000000..dd7cfb197cd
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,26 @@
+/*
+ * src/include/port/aix.h
+ */
+
+/* This change is required for the meson changes as the autoconf is not run and
+ * to resolve the conflicts in picking the float.h details by default from the
+ * postgres defined datatypes.
+ */
+#ifdef _AIX
+#ifndef PGDLLIMPORT
+#define PGDLLIMPORT
+#endif  /* PGDLLIMPORT */
+typedef float float4;
+typedef double float8;
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+#define pg_noreturn _Noreturn
+#elif defined(__GNUC__)
+#define pg_noreturn __attribute__((noreturn))
+#else
+#define pg_noreturn
+#endif
+
+#include <stdbool.h>
+
+#endif  /*_AIX */
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 7f8f566bd40..1a0cd5ec019 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -398,60 +398,20 @@ 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/interfaces/ecpg/compatlib/meson.build b/src/interfaces/ecpg/compatlib/meson.build
index 56e0a21651b..3f39187cdcc 100644
--- a/src/interfaces/ecpg/compatlib/meson.build
+++ b/src/interfaces/ecpg/compatlib/meson.build
@@ -16,7 +16,7 @@ if host_system == 'windows'
 endif
 
 # see src/interfaces/libpq/meson.build
-ecpg_compat_st = static_library('libecpg_compat',
+ecpg_compat_st = static_library('libecpg_compat_static',
   ecpg_compat_sources,
   include_directories: ecpg_compat_inc,
   c_args: ecpg_compat_c_args,
diff --git a/src/interfaces/ecpg/ecpglib/meson.build b/src/interfaces/ecpg/ecpglib/meson.build
index 8f478c6a73e..e9faf290a2b 100644
--- a/src/interfaces/ecpg/ecpglib/meson.build
+++ b/src/interfaces/ecpg/ecpglib/meson.build
@@ -25,7 +25,7 @@ if host_system == 'windows'
 endif
 
 # see src/interfaces/libpq/meson.build
-ecpglib_st = static_library('libecpg',
+ecpglib_st = static_library('libecpg_static',
   ecpglib_sources,
   include_directories: ecpglib_inc,
   c_args: ecpglib_c_args,
diff --git a/src/interfaces/ecpg/pgtypeslib/meson.build b/src/interfaces/ecpg/pgtypeslib/meson.build
index 02301ec9acb..94d1d0ad1ef 100644
--- a/src/interfaces/ecpg/pgtypeslib/meson.build
+++ b/src/interfaces/ecpg/pgtypeslib/meson.build
@@ -21,7 +21,7 @@ if host_system == 'windows'
 endif
 
 # see src/interfaces/libpq/meson.build
-ecpg_pgtypes_st = static_library('libpgtypes',
+ecpg_pgtypes_st = static_library('libpgtypes_static',
   ecpg_pgtypes_sources,
   include_directories: ecpg_pgtypes_inc,
   c_args: ecpg_pgtypes_c_args,
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index a74e885b169..eea175ad14a 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -57,7 +57,7 @@ libpq_so_c_args = ['-DUSE_DYNAMIC_OAUTH']
 # We could try to avoid building the source files twice, but it probably adds
 # more complexity than its worth (reusing object files requires also linking
 # to the library on windows or breaks precompiled headers).
-libpq_st = static_library('libpq',
+libpq_st = static_library('libpq_static',
   libpq_sources,
   include_directories: [libpq_inc],
   c_args: libpq_c_args,
diff --git a/src/makefiles/Makefile.aix b/src/makefiles/Makefile.aix
new file mode 100644
index 00000000000..e91b250fd19
--- /dev/null
+++ b/src/makefiles/Makefile.aix
@@ -0,0 +1,34 @@
+# -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
+
+# 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/port/strerror.c b/src/port/strerror.c
index f0746517770..c46b9dc91fc 100644
--- a/src/port/strerror.c
+++ b/src/port/strerror.c
@@ -214,8 +214,10 @@ get_errno_symbol(int errnum)
 			return "ENOTCONN";
 		case ENOTDIR:
 			return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
 		case ENOTEMPTY:
 			return "ENOTEMPTY";
+#endif
 		case ENOTSOCK:
 			return "ENOTSOCK";
 #ifdef ENOTSUP
diff --git a/src/template/aix b/src/template/aix
new file mode 100644
index 00000000000..22f61093b1b
--- /dev/null
+++ b/src/template/aix
@@ -0,0 +1,6 @@
+# This file is referred for specific flags wrt to AIX build process like
+# cflags.
+# src/template/aix
+
+# Extra CFLAGS for code that will go into a shared library
+CFLAGS_SL=" "
diff --git a/src/tools/gen_export.pl b/src/tools/gen_export.pl
index 86a7742b369..25827c42a68 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.41.0

#118Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Srirama Kucherlapati (#117)
Re: AIX support

On 09/12/2025 18:50, Srirama Kucherlapati wrote:

@@ -1766,9 +1785,9 @@ endforeach
# 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
+#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))

This is unfinished.

@@ -1820,7 +1839,7 @@ if cc.links('''
if not meson.is_cross_build()
r = cc.run('''
/* This must match the corresponding code in c.h: */
-    #if defined(__GNUC__)
+    #if defined(__GNUC__) || defined(__IBMC__)
#define pg_attribute_aligned(a) __attribute__((aligned(a)))
#elif defined(_MSC_VER)
#define pg_attribute_aligned(a) __declspec(align(a))

There's a comment right there that it must match the corresponding code
in c.h, but you didn't modify c.h.

+  # Native memset() is faster, tested on:
+  memset_loop_limit = 0

Incomplete sentence: tested on what?

We talked about this before. I'm reluctant to have a special case for
AIX, because I suspect this has little to do with the operating system,
and more with the compiler and the CPU architecture. I could be wrong;
maybe the libc memset() implementation on AIX is superior to that on
linux, for example. I'd love to see thorough performance testing of
MemSetAligned() vs memset() on common combinations of CPUs and libc
implementations. Ideally, we can just replace MemSetAligned() with
memset() everywhere.

If you do such testing, please start a separate thread for that. On this
thread, it will get lost with all the AIX-specific stuff.

+/* This change is required for the meson changes as the autoconf is not run and
+ * to resolve the conflicts in picking the float.h details by default from the
+ * postgres defined datatypes.
+ */
+#ifdef _AIX
+#ifndef PGDLLIMPORT
+#define PGDLLIMPORT
+#endif  /* PGDLLIMPORT */
+typedef float float4;
+typedef double float8;

I don't understand these typedefs. What is the conflict the comment
talks about?

+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+#define pg_noreturn _Noreturn
+#elif defined(__GNUC__)
+#define pg_noreturn __attribute__((noreturn))
+#else
+#define pg_noreturn
+#endif

Isn't this just duplicating the snippet in c.h?

+#include <stdbool.h>

This is in c.h too.

src/include/storage/s_lock.h
[ switches to __sync_lock_release(lock) on all powerpc systems ]

We talked about this before.

@@ -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";
}

Forgot to update the error message.

I didn't review the autoconf / Makefile changes.

Apologies for the delayed response; I was occupied with other tasks.

Oh no worries, I'm not in any hurry with this. On the contrary to be honest.

- Heikki

#119Peter Eisentraut
peter@eisentraut.org
In reply to: Srirama Kucherlapati (#117)
Re: AIX support

On 09.12.25 17:50, Srirama Kucherlapati wrote:

Hi Team, (Peter/Heikki)

I have implemented the requested modifications in the latest patch.
Below are the key technical updates:

• Meson Build Configuration: Adjusted below meson.build scripts to
incorporate the suggested changes, ensuring proper dependency resolution
and improved build consistency.

    Removed the AIX changes in the below from the previous patch.

    src/backend/jit/llvm/meson.build
src/backend/replication/libpqwalreceiver/meson.build
src/backend/replication/pgoutput/meson.build
src/backend/snowball/meson.build
src/backend/utils/mb/conversion_procs/meson.build

    Added the static_library() changes.

    > Regarding the archiving of shared and static libraries, the
latest version of

Meson raises a conflict as both targets have the same name. This issue
arises because, on AIX, both shared and static libraries are named as same
archive, which leads to naming collisions during the build process. We
would still need the below changes.

     src/interfaces/ecpg/compatlib/meson.build
src/interfaces/ecpg/ecpglib/meson.build
src/interfaces/ecpg/pgtypeslib/meson.build
src/interfaces/libpq/meson.build

• CFLAGS Optimization Removal: Removed high-level optimization flags
from CFLAGS to prevent unpredictable behaviour and maintain stability
during compilation.

I would greatly appreciate it if you could review the patch and share
your feedback or any additional recommendations.

Apologies for the delayed response; I was occupied with other tasks.

Your insights are greatly appreciated and will help enhance the patch.

Warm regards,
-Sriram.

1) In meson.build:

+ cppflags += '-D_GNU_SOURCE'

I don't think this symbol is applicable to AIX.

2) In meson.build:

+  # Native memset() is faster, tested on:
+  memset_loop_limit = 0

The comment sentence appears to be truncated.

3) In meson.build:

+#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

This commented out code cannot be left like this. Either remove it or
adjust it as required.

4) In meson.build:

      /* This must match the corresponding code in c.h: */
-    #if defined(__GNUC__)
+    #if defined(__GNUC__) || defined(__IBMC__)

You code does not observe what the comment says.

5) The changes in src/include/port/aix.h are nonsense. This was
previously pointed out and you said you would address this.

6) I had previously pointed out that the changes in
src/include/storage/s_lock.h are not acceptable like that and you had
said that you would address that.

#120Tristan Partin
tristan@partin.io
In reply to: Srirama Kucherlapati (#117)
Re: AIX support

Howdy,

Heikki asked me to look at the renames of the static Meson targets.
I don't understand the reasoning for the changes. I am completely
unfamiliar with AIX, so maybe it's obvious. Does Meson produce a static
library and a shared library with the same file extension? If so, why is
that? That's the only reason I can think of for making those changes. Is
it AIX-specific or whatever OS you are testing on?

In your patch, I found a link to
/messages/by-id/52EF20B2E3209443BC37736D00C3C1380A6E79FE@EXADV1.host.magwien.gv.at.

-> On AIX, you can do a static as well as a dynamic
-> link against a shared library, it depends on how you
-> invoke the linker.

When you link statically, the shared objects from
the library are added to your executable as required;
when you link dynamically, only references
to the shared objects are included in the executable.

Consequently you do not need a separate static library
on AIX if you have a dynamic library.

This seems to imply that we don't need a static library at all on AIX.
However this email is also nearing 20 years old :D. Could we get away
without the renames on the Meson targets by just not defining the static
library targets?

--
Tristan Partin
Databricks (https://databricks.com)

#121Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Tristan Partin (#120)
RE: AIX support

Hi Tristan,

Thank you for reviewing the patch.

We encountered the following error when building without the "_static" suffix in the library name:
Found ninja-1.12.1 at /opt/freeware/bin/ninja
ERROR: Multiple producers for Ninja target "src/interfaces/ecpg/compatlib/libecpg_compat.a”.
Please rename your targets.

On AIX, shared libraries are archived in a way that allows multiple versions to
coexist within the same archive. This is primarily because shared library(.so)
is archived into .a, which leads to naming conflicts between static and shared
libraries. To address this, we suffixed the library with “_static".

However, we later tested by completely skipping the static library build, and
this approach worked successfully since it eliminates the conflict between
static and shared libraries. I'm working on the changes and will validate
further on this.

BTW, thank you, Heikki and Peter, for your comments. I’m working on the comments

and I’ll keep you updated.

Warm regards,

Sriram.

#122Tristan Partin
tristan@partin.io
In reply to: Srirama Kucherlapati (#121)
Re: AIX support

On Wed Dec 10, 2025 at 8:32 AM CST, Srirama Kucherlapati wrote:

We encountered the following error when building without the "_static" suffix in the library name:
Found ninja-1.12.1 at /opt/freeware/bin/ninja
ERROR: Multiple producers for Ninja target "src/interfaces/ecpg/compatlib/libecpg_compat.a”.
Please rename your targets.

On AIX, shared libraries are archived in a way that allows multiple versions to
coexist within the same archive. This is primarily because shared library(.so)
is archived into .a, which leads to naming conflicts between static and shared
libraries. To address this, we suffixed the library with “_static".

However, we later tested by completely skipping the static library build, and
this approach worked successfully since it eliminates the conflict between
static and shared libraries. I'm working on the changes and will validate
further on this.

Thanks for the explanation. I'm glad we can workaround this without
renaming the targets!

--
Tristan Partin
Databricks (https://databricks.com)

#123Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Peter Eisentraut (#119)
2 attachment(s)
RE: AIX support

Hi Peter/Heikki/Tristan

Please find the attached changes for the below comments. Along with comments from Tristan.
Please let me know if these meson specific changes are fine.

0001-Support-for-AIX-meson-updates.pg19.patch - has the changes for the below comments only.
0001-Support-for-AIX-all-meson.pg19.patch - has all the meson specific changes.

1) In meson.build:

+ cppflags += '-D_GNU_SOURCE’
I don't think this symbol is applicable to AIX.

AIX provides certain functions similar to Linux, but with different names and
signatures. To align them with Linux behaviour, the GNU_SOURCE macro is defined,
which enables AIX functions to behave like their Linux counterparts.
You are right, this is not needed for AIX. I have removed and everything got build.

2) In meson.build:

+  # Native memset() is faster, tested on:
+  memset_loop_limit = 0

The comment sentence appears to be truncated.

For now, removed this, I’ll provide statistics in a different thread as Heikki suggested.

3) In meson.build:

+#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

This commented out code cannot be left like this. Either remove it or
adjust it as required.

I have updated the similar logic as in regular GNU configure file.

4) In meson.build:

/* This must match the corresponding code in c.h: */
-    #if defined(__GNUC__)
+    #if defined(__GNUC__) || defined(__IBMC__)

You code does not observe what the comment says.

You are right, I have removed this as this is relevant only if we are compiling with XLC. Right now, its compiled with gcc

5) The changes in src/include/port/aix.h are nonsense. This was
previously pointed out and you said you would address this.

The changes are irrelevant now, removed them. As all these additional definitions are covered by the postgres defined header file (src/include/utils/float.h). We can use “_H_FLOAT” to skip the system header "float.h”.

I’d like to finalize all Meson-specific changes first. Meanwhile, I’m also working on the other comments.

Kindly let me know your thoughts and feedback on the changes.

Thanks,

Sriram.

Attachments:

0001-Support-for-AIX-all-meson.pg19.patchapplication/octet-stream; name=0001-Support-for-AIX-all-meson.pg19.patchDownload

diff --git a/meson.build b/meson.build
index 6e7ddd74683..6ba24187d15 100644
--- a/meson.build
+++ b/meson.build
@@ -206,6 +206,26 @@ if host_system == 'cygwin'
   mod_link_with_name = 'lib@0@.a'
   mod_link_with_dir = 'libdir'
 
+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'
+  # This flag is required to make sure the user spefic float.h is
+  # picked instead of the system float.h header file, which doesnot
+  # have definition like float8, etc
+  cflags += '-D_H_FLOAT'
+
+  # M:SRE sets a flag indicating that an object is a shared library. Seems to
+  # work in some circumstances without, but required in others.
+  ldflags_sl += '-Wl,-bM:SRE'
+  ldflags_be += '-Wl,-brtllib'
+
+
 elif host_system == 'darwin'
   dlsuffix = '.dylib'
   library_path_var = 'DYLD_LIBRARY_PATH'
@@ -1765,10 +1785,49 @@ endforeach
 # 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
+if host_system != 'aix'
+  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
+else
+  # The AIX 'power' alignment rules apply the natural alignment of the "first
+  # member" if it is of a floating-point data type (or is an aggregate whose
+  # recursively "first" member or element is such a type). The alignment
+  # associated with these types for subsequent members use an alignment value
+  # where the floating-point data type is considered to have 4-byte alignment.
+  # More info
+  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+  #
+  # The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+  # alignement across platforms the max alignment of long should be considered.
+
+  # Get the alignment values
+  ac_cv_alignof_long    = cc.alignment('long', args: test_c_args, prefix: '#include <stdint.h>')
+  ac_cv_alignof_double  = cc.alignment('double', args: test_c_args, prefix: '#include <stdint.h>') 
+  ac_cv_alignof_int64_t = cc.alignment('int64_t', args: test_c_args, prefix: '#include <stdint.h>')
+ 
+  message('Alignment of long    : @0@'.format(ac_cv_alignof_long))
+  message('Alignment of double  : @0@'.format(ac_cv_alignof_double))
+  message('Alignment of int64_t : @0@'.format(ac_cv_alignof_int64_t))
+  
+  # Start with long
+  alignof_double = ac_cv_alignof_long
+  message('MAX ALIGN ac_cv_alignof_long')
+
+  # Compare with double
+  if alignof_double < ac_cv_alignof_double
+    alignof_double = ac_cv_alignof_double
+    message('MAX ALIGN ac_cv_alignof_double')
+  endif
+
+  # Compare with int64_t
+  if alignof_double < ac_cv_alignof_int64_t
+    alignof_double = ac_cv_alignof_int64_t
+    message('MAX ALIGN ac_cv_alignof_int64_t')
+  endif
+endif
+message('MAX ALIGN OF DOUBLE : @0@'.format(alignof_double))
 cdata.set('MAXIMUM_ALIGNOF', alignof_double)
 
 cdata.set('SIZEOF_LONG', cc.sizeof('long', args: test_c_args))
@@ -3466,13 +3525,17 @@ endif
 installed_targets = [
   backend_targets,
   bin_targets,
-  libpq_st,
   pl_targets,
   contrib_targets,
   nls_mo_targets,
   ecpg_targets,
 ]
 
+# The static libpq is skipped in AIX. This is not required.
+if host_system != 'aix'
+  installed_targets += [libpq_st]
+endif
+
 if oauth_flow_supported
   installed_targets += [
     libpq_oauth_so,
@@ -3816,7 +3879,13 @@ add_test_setup('running',
 ###############################################################
 
 alias_target('backend', backend_targets)
-alias_target('bin', bin_targets + [libpq_st])
+if host_system != 'aix'
+  alias_target('bin', bin_targets + [libpq_st])
+else
+  # The static libpq is skipped in AIX. This is not required.
+  alias_target('bin', bin_targets)
+endif
+
 alias_target('pl', pl_targets)
 alias_target('contrib', contrib_targets)
 alias_target('testprep', testprep_targets)
diff --git a/src/backend/meson.build b/src/backend/meson.build
index b831a541652..4838f245ab3 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/interfaces/ecpg/compatlib/meson.build b/src/interfaces/ecpg/compatlib/meson.build
index 56e0a21651b..af96e375a9b 100644
--- a/src/interfaces/ecpg/compatlib/meson.build
+++ b/src/interfaces/ecpg/compatlib/meson.build
@@ -16,6 +16,7 @@ if host_system == 'windows'
 endif
 
 # see src/interfaces/libpq/meson.build
+if host_system != 'aix'
 ecpg_compat_st = static_library('libecpg_compat',
   ecpg_compat_sources,
   include_directories: ecpg_compat_inc,
@@ -25,6 +26,7 @@ ecpg_compat_st = static_library('libecpg_compat',
   kwargs: default_lib_args,
 )
 ecpg_targets += ecpg_compat_st
+endif
 
 ecpg_compat_so = shared_library('libecpg_compat',
   ecpg_compat_sources + ecpg_compat_so_sources,
diff --git a/src/interfaces/ecpg/ecpglib/meson.build b/src/interfaces/ecpg/ecpglib/meson.build
index 8f478c6a73e..7d28cd67388 100644
--- a/src/interfaces/ecpg/ecpglib/meson.build
+++ b/src/interfaces/ecpg/ecpglib/meson.build
@@ -25,6 +25,7 @@ if host_system == 'windows'
 endif
 
 # see src/interfaces/libpq/meson.build
+if host_system != 'aix'
 ecpglib_st = static_library('libecpg',
   ecpglib_sources,
   include_directories: ecpglib_inc,
@@ -35,6 +36,7 @@ ecpglib_st = static_library('libecpg',
   kwargs: default_lib_args,
 )
 ecpg_targets += ecpglib_st
+endif
 
 ecpglib_so = shared_library('libecpg',
   ecpglib_sources + ecpglib_so_sources,
diff --git a/src/interfaces/ecpg/pgtypeslib/meson.build b/src/interfaces/ecpg/pgtypeslib/meson.build
index 02301ec9acb..97f4e1c6eda 100644
--- a/src/interfaces/ecpg/pgtypeslib/meson.build
+++ b/src/interfaces/ecpg/pgtypeslib/meson.build
@@ -21,6 +21,7 @@ if host_system == 'windows'
 endif
 
 # see src/interfaces/libpq/meson.build
+if host_system != 'aix'
 ecpg_pgtypes_st = static_library('libpgtypes',
   ecpg_pgtypes_sources,
   include_directories: ecpg_pgtypes_inc,
@@ -30,6 +31,7 @@ ecpg_pgtypes_st = static_library('libpgtypes',
   kwargs: default_lib_args,
 )
 ecpg_targets += ecpg_pgtypes_st
+endif
 
 ecpg_pgtypes_so = shared_library('libpgtypes',
   ecpg_pgtypes_sources + ecpg_pgtypes_so_sources,
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index a74e885b169..98ced9376d9 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -57,6 +57,7 @@ libpq_so_c_args = ['-DUSE_DYNAMIC_OAUTH']
 # We could try to avoid building the source files twice, but it probably adds
 # more complexity than its worth (reusing object files requires also linking
 # to the library on windows or breaks precompiled headers).
+if host_system != 'aix'
 libpq_st = static_library('libpq',
   libpq_sources,
   include_directories: [libpq_inc],
@@ -65,6 +66,7 @@ libpq_st = static_library('libpq',
   dependencies: [frontend_stlib_code, libpq_deps],
   kwargs: default_lib_args,
 )
+endif
 
 libpq_so = shared_library('libpq',
   libpq_sources + libpq_so_sources,
0001-Support-for-AIX-meson-updates.pg19.patchapplication/octet-stream; name=0001-Support-for-AIX-meson-updates.pg19.patchDownload
diff --git a/meson.build b/meson.build
index 304a9184075..6ba24187d15 100644
--- a/meson.build
+++ b/meson.build
@@ -215,15 +215,16 @@ elif host_system == 'aix'
   mod_link_with_dir = 'libdir'
   mod_link_with_name = '@0@.imp'
   dl_suffix = '.a'
-  cppflags += '-D_GNU_SOURCE'
+  # This flag is required to make sure the user spefic float.h is
+  # picked instead of the system float.h header file, which doesnot
+  # have definition like float8, etc
+  cflags += '-D_H_FLOAT'
 
   # M:SRE sets a flag indicating that an object is a shared library. Seems to
   # work in some circumstances without, but required in others.
   ldflags_sl += '-Wl,-bM:SRE'
   ldflags_be += '-Wl,-brtllib'
 
-  # Native memset() is faster, tested on:
-  memset_loop_limit = 0
 
 elif host_system == 'darwin'
   dlsuffix = '.dylib'
@@ -1784,10 +1785,49 @@ endforeach
 # 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
+if host_system != 'aix'
+  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
+else
+  # The AIX 'power' alignment rules apply the natural alignment of the "first
+  # member" if it is of a floating-point data type (or is an aggregate whose
+  # recursively "first" member or element is such a type). The alignment
+  # associated with these types for subsequent members use an alignment value
+  # where the floating-point data type is considered to have 4-byte alignment.
+  # More info
+  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+  #
+  # The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+  # alignement across platforms the max alignment of long should be considered.
+
+  # Get the alignment values
+  ac_cv_alignof_long    = cc.alignment('long', args: test_c_args, prefix: '#include <stdint.h>')
+  ac_cv_alignof_double  = cc.alignment('double', args: test_c_args, prefix: '#include <stdint.h>') 
+  ac_cv_alignof_int64_t = cc.alignment('int64_t', args: test_c_args, prefix: '#include <stdint.h>')
+ 
+  message('Alignment of long    : @0@'.format(ac_cv_alignof_long))
+  message('Alignment of double  : @0@'.format(ac_cv_alignof_double))
+  message('Alignment of int64_t : @0@'.format(ac_cv_alignof_int64_t))
+  
+  # Start with long
+  alignof_double = ac_cv_alignof_long
+  message('MAX ALIGN ac_cv_alignof_long')
+
+  # Compare with double
+  if alignof_double < ac_cv_alignof_double
+    alignof_double = ac_cv_alignof_double
+    message('MAX ALIGN ac_cv_alignof_double')
+  endif
+
+  # Compare with int64_t
+  if alignof_double < ac_cv_alignof_int64_t
+    alignof_double = ac_cv_alignof_int64_t
+    message('MAX ALIGN ac_cv_alignof_int64_t')
+  endif
+endif
+message('MAX ALIGN OF DOUBLE : @0@'.format(alignof_double))
 cdata.set('MAXIMUM_ALIGNOF', alignof_double)
 
 cdata.set('SIZEOF_LONG', cc.sizeof('long', args: test_c_args))
@@ -1839,7 +1879,7 @@ if cc.links('''
   if not meson.is_cross_build()
     r = cc.run('''
     /* This must match the corresponding code in c.h: */
-    #if defined(__GNUC__) || defined(__IBMC__)
+    #if defined(__GNUC__)
     #define pg_attribute_aligned(a) __attribute__((aligned(a)))
     #elif defined(_MSC_VER)
     #define pg_attribute_aligned(a) __declspec(align(a))
@@ -3485,13 +3525,17 @@ endif
 installed_targets = [
   backend_targets,
   bin_targets,
-  libpq_st,
   pl_targets,
   contrib_targets,
   nls_mo_targets,
   ecpg_targets,
 ]
 
+# The static libpq is skipped in AIX. This is not required.
+if host_system != 'aix'
+  installed_targets += [libpq_st]
+endif
+
 if oauth_flow_supported
   installed_targets += [
     libpq_oauth_so,
@@ -3835,7 +3879,13 @@ add_test_setup('running',
 ###############################################################
 
 alias_target('backend', backend_targets)
-alias_target('bin', bin_targets + [libpq_st])
+if host_system != 'aix'
+  alias_target('bin', bin_targets + [libpq_st])
+else
+  # The static libpq is skipped in AIX. This is not required.
+  alias_target('bin', bin_targets)
+endif
+
 alias_target('pl', pl_targets)
 alias_target('contrib', contrib_targets)
 alias_target('testprep', testprep_targets)
diff --git a/src/include/port/aix.h b/src/include/port/aix.h
index dd7cfb197cd..c86983a4452 100644
--- a/src/include/port/aix.h
+++ b/src/include/port/aix.h
@@ -1,26 +1,3 @@
 /*
  * src/include/port/aix.h
  */
-
-/* This change is required for the meson changes as the autoconf is not run and
- * to resolve the conflicts in picking the float.h details by default from the
- * postgres defined datatypes.
- */
-#ifdef _AIX
-#ifndef PGDLLIMPORT
-#define PGDLLIMPORT
-#endif  /* PGDLLIMPORT */
-typedef float float4;
-typedef double float8;
-
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
-#define pg_noreturn _Noreturn
-#elif defined(__GNUC__)
-#define pg_noreturn __attribute__((noreturn))
-#else
-#define pg_noreturn
-#endif
-
-#include <stdbool.h>
-
-#endif  /*_AIX */
diff --git a/src/interfaces/ecpg/compatlib/meson.build b/src/interfaces/ecpg/compatlib/meson.build
index 3f39187cdcc..af96e375a9b 100644
--- a/src/interfaces/ecpg/compatlib/meson.build
+++ b/src/interfaces/ecpg/compatlib/meson.build
@@ -16,7 +16,8 @@ if host_system == 'windows'
 endif
 
 # see src/interfaces/libpq/meson.build
-ecpg_compat_st = static_library('libecpg_compat_static',
+if host_system != 'aix'
+ecpg_compat_st = static_library('libecpg_compat',
   ecpg_compat_sources,
   include_directories: ecpg_compat_inc,
   c_args: ecpg_compat_c_args,
@@ -25,6 +26,7 @@ ecpg_compat_st = static_library('libecpg_compat_static',
   kwargs: default_lib_args,
 )
 ecpg_targets += ecpg_compat_st
+endif
 
 ecpg_compat_so = shared_library('libecpg_compat',
   ecpg_compat_sources + ecpg_compat_so_sources,
diff --git a/src/interfaces/ecpg/ecpglib/meson.build b/src/interfaces/ecpg/ecpglib/meson.build
index e9faf290a2b..7d28cd67388 100644
--- a/src/interfaces/ecpg/ecpglib/meson.build
+++ b/src/interfaces/ecpg/ecpglib/meson.build
@@ -25,7 +25,8 @@ if host_system == 'windows'
 endif
 
 # see src/interfaces/libpq/meson.build
-ecpglib_st = static_library('libecpg_static',
+if host_system != 'aix'
+ecpglib_st = static_library('libecpg',
   ecpglib_sources,
   include_directories: ecpglib_inc,
   c_args: ecpglib_c_args,
@@ -35,6 +36,7 @@ ecpglib_st = static_library('libecpg_static',
   kwargs: default_lib_args,
 )
 ecpg_targets += ecpglib_st
+endif
 
 ecpglib_so = shared_library('libecpg',
   ecpglib_sources + ecpglib_so_sources,
diff --git a/src/interfaces/ecpg/pgtypeslib/meson.build b/src/interfaces/ecpg/pgtypeslib/meson.build
index 94d1d0ad1ef..97f4e1c6eda 100644
--- a/src/interfaces/ecpg/pgtypeslib/meson.build
+++ b/src/interfaces/ecpg/pgtypeslib/meson.build
@@ -21,7 +21,8 @@ if host_system == 'windows'
 endif
 
 # see src/interfaces/libpq/meson.build
-ecpg_pgtypes_st = static_library('libpgtypes_static',
+if host_system != 'aix'
+ecpg_pgtypes_st = static_library('libpgtypes',
   ecpg_pgtypes_sources,
   include_directories: ecpg_pgtypes_inc,
   c_args: ecpg_pgtypes_c_args,
@@ -30,6 +31,7 @@ ecpg_pgtypes_st = static_library('libpgtypes_static',
   kwargs: default_lib_args,
 )
 ecpg_targets += ecpg_pgtypes_st
+endif
 
 ecpg_pgtypes_so = shared_library('libpgtypes',
   ecpg_pgtypes_sources + ecpg_pgtypes_so_sources,
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index eea175ad14a..98ced9376d9 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -57,7 +57,8 @@ libpq_so_c_args = ['-DUSE_DYNAMIC_OAUTH']
 # We could try to avoid building the source files twice, but it probably adds
 # more complexity than its worth (reusing object files requires also linking
 # to the library on windows or breaks precompiled headers).
-libpq_st = static_library('libpq_static',
+if host_system != 'aix'
+libpq_st = static_library('libpq',
   libpq_sources,
   include_directories: [libpq_inc],
   c_args: libpq_c_args,
@@ -65,6 +66,7 @@ libpq_st = static_library('libpq_static',
   dependencies: [frontend_stlib_code, libpq_deps],
   kwargs: default_lib_args,
 )
+endif
 
 libpq_so = shared_library('libpq',
   libpq_sources + libpq_so_sources,
diff --git a/src/tools/gen_export.pl b/src/tools/gen_export.pl
index 25827c42a68..19c8b60560f 100644
--- a/src/tools/gen_export.pl
+++ b/src/tools/gen_export.pl
@@ -21,7 +21,7 @@ if (not(   $format eq 'darwin'
 		or $format eq 'win'
         or $format eq 'aix'))
 {
-	die "$0: $format is not yet handled (only darwin, gnu, win are)\n";
+	die "$0: $format is not yet handled (only darwin, gnu, win, aix are)\n";
 }
 
 open(my $input_handle, '<', $input)
#124Tristan Partin
tristan@partin.io
In reply to: Srirama Kucherlapati (#123)
Re: AIX support

Thanks for your continued push for AIX support! Here are a few comments:

# The static libpq is skipped in AIX. This is not required.

For comments like this, I would generally like to see some links or
inline documentation to why this is the case. Maybe Peter or Heikki
disagree.

There are a few places in the Meson code like the following:

if AIX:
don't define the static library target
endif

Make sure that the innards of the if statements are indented.
Alternatively, you could define something like:

static_library_dependencies = []
if host_machine.system() == 'AIX'
# TODO: Document this
AIX_poison_pill = disabler()
static_library_dependencies += AIX_poison_pill
endif

And then for all static library definitions, you would just make sure
that they all depend on the poison pill. You could document the AIX
shared/static library situation where the AIX_poison_pill variable is
defined. I'd like to see if Peter thinks this is a good idea before
implementing it.

I'm also a little confused by the second patch. Some of it seems to be
the same, and some other parts seem to be new. Should we consolidate all
Meson AIX support into one patch? Overall, I think the size of the patch
is good, and seem pretty maintainable.

--
Tristan Partin
Databricks (https://databricks.com)

#125Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Tristan Partin (#124)
RE: AIX support

Hi Tristan,
Thank you for your feedback and suggestions.

As suggested, we have tried to implement a dependency-driven approach for static library builds, rather than using AIX platform tags.

modified: meson.build
dep_static_lib = declare_dependency() << new dependency

if host_system == 'aix'
dep_static_lib = disabler()
endif

modified: src/interfaces/ecpg/compatlib/meson.build
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, dep_static_lib], << new dependency
link_with: [ecpglib_st, ecpg_pgtypes_st],
kwargs: default_lib_args,
)

modified: src/interfaces/ecpg/ecpglib/meson.build
ecpglib_st = static_library('libecpg',
ecpglib_sources,
include_directories: ecpglib_inc,
c_args: ecpglib_c_args,
c_pch: pch_postgres_fe_h,
dependencies: [frontend_stlib_code, thread_dep, libpq, dep_static_lib], << new dependency
link_with: [ecpg_pgtypes_st],
kwargs: default_lib_args,
)

modified: src/interfaces/ecpg/pgtypeslib/meson.build
ecpg_pgtypes_st = static_library('libpgtypes',
ecpg_pgtypes_sources,
include_directories: ecpg_pgtypes_inc,
c_args: ecpg_pgtypes_c_args,
c_pch: pch_postgres_fe_h,
dependencies: [frontend_stlib_code, dep_static_lib], << new dependency
kwargs: default_lib_args,
)

modified: src/interfaces/libpq/meson.build
libpq_st = static_library('libpq',
libpq_sources,
include_directories: [libpq_inc],
c_args: libpq_c_args,
c_pch: pch_postgres_fe_h,
dependencies: [frontend_stlib_code, libpq_deps, dep_static_lib], << new dependency
kwargs: default_lib_args,
)

I'd like to see if Peter thinks this is a good idea before implementing it.

Also I would like to understand Peter/Heikki thoughts as well on this new implementation.

Should we consolidate all Meson AIX support into one patch?
Overall, I think the size of the patch is good, and seem pretty maintainable.

Thank you, Tristan, for your assistance. At present, the build appears stable

with the recent changes, however, the new dependency is causing impacts

elsewhere(with tmp_install). I will provide the consolidated patch after addressing these concerns.

Thanks,
Sriram.

#126Srirama Kucherlapati
sriram.rk@in.ibm.com
In reply to: Srirama Kucherlapati (#125)
1 attachment(s)
RE: AIX support

Hi Tristan/Peter/Heikki,

Please find attached meson changes wrt to the comments from Tristan regarding the dependency approach.
Kindly let me know your thoughts and suggestions.

Warm regards,
Sriram.

Attachments:

0001-Support-for-AIX-pg19-meson.diffapplication/octet-stream; name=0001-Support-for-AIX-pg19-meson.diffDownload

diff --git a/meson.build b/meson.build
index 6e7ddd74683..0c03481d721 100644
--- a/meson.build
+++ b/meson.build
@@ -198,6 +198,8 @@ endif
 # that purpose.
 portname = host_system

+dep_static_lib = declare_dependency()
+
 if host_system == 'cygwin'
   sema_kind = 'unnamed_posix'
   cppflags += '-D_GNU_SOURCE'
@@ -206,6 +208,32 @@ if host_system == 'cygwin'
   mod_link_with_name = 'lib@0@.a'
   mod_link_with_dir = 'libdir'

+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'
+  # This flag is required to make sure the user spefic float.h is
+  # picked instead of the system float.h header file, which doesnot
+  # have definition like float8, etc
+  cflags += '-D_H_FLOAT'
+
+  # M:SRE sets a flag indicating that an object is a shared library. Seems to
+  # work in some circumstances without, but required in others.
+  ldflags_sl += '-Wl,-bM:SRE'
+  ldflags_be += '-Wl,-brtllib'
+
+  # https://mesonbuild.com/Release-notes-for-1-6-0.html
+  # According to Mesons documentation for AIX, both shared and static libraries
+  # are typically archived, and they should have distinct names if a project
+  # requires building both. However, in this case, only shared libraries are
+  # used on AIX, so we are skipping the build for static libraries.
+  dep_static_lib = disabler()
+
 elif host_system == 'darwin'
   dlsuffix = '.dylib'
   library_path_var = 'DYLD_LIBRARY_PATH'
@@ -1765,10 +1793,49 @@ endforeach
 # 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
+if host_system != 'aix'
+  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
+else
+  # The AIX 'power' alignment rules apply the natural alignment of the "first
+  # member" if it is of a floating-point data type (or is an aggregate whose
+  # recursively "first" member or element is such a type). The alignment
+  # associated with these types for subsequent members use an alignment value
+  # where the floating-point data type is considered to have 4-byte alignment.
+  # More info
+  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99557
+  #
+  # The double is aligned to 4-bytes on AIX in aggregates. But to maintain
+  # alignement across platforms the max alignment of long should be considered.
+
+  # Get the alignment values
+  ac_cv_alignof_long    = cc.alignment('long', args: test_c_args, prefix: '#include <stdint.h>')
+  ac_cv_alignof_double  = cc.alignment('double', args: test_c_args, prefix: '#include <stdint.h>')
+  ac_cv_alignof_int64_t = cc.alignment('int64_t', args: test_c_args, prefix: '#include <stdint.h>')
+
+  message('Alignment of long    : @0@'.format(ac_cv_alignof_long))
+  message('Alignment of double  : @0@'.format(ac_cv_alignof_double))
+  message('Alignment of int64_t : @0@'.format(ac_cv_alignof_int64_t))
+
+  # Start with long
+  alignof_double = ac_cv_alignof_long
+  message('MAX ALIGN ac_cv_alignof_long')
+
+  # Compare with double
+  if alignof_double < ac_cv_alignof_double
+    alignof_double = ac_cv_alignof_double
+    message('MAX ALIGN ac_cv_alignof_double')
+  endif
+
+  # Compare with int64_t
+  if alignof_double < ac_cv_alignof_int64_t
+    alignof_double = ac_cv_alignof_int64_t
+    message('MAX ALIGN ac_cv_alignof_int64_t')
+  endif
+endif
+message('MAX ALIGN OF DOUBLE : @0@'.format(alignof_double))
 cdata.set('MAXIMUM_ALIGNOF', alignof_double)

 cdata.set('SIZEOF_LONG', cc.sizeof('long', args: test_c_args))
@@ -3466,13 +3533,17 @@ endif
 installed_targets = [
   backend_targets,
   bin_targets,
-  libpq_st,
   pl_targets,
   contrib_targets,
   nls_mo_targets,
   ecpg_targets,
 ]

+# Include the libpq only if its build. For AIX its skipped.
+if not dep_static_lib.disabled()
+  installed_targets += [libpq_st]
+endif
+
 if oauth_flow_supported
   installed_targets += [
     libpq_oauth_so,
diff --git a/src/backend/meson.build b/src/backend/meson.build
index b831a541652..4838f245ab3 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/interfaces/ecpg/compatlib/meson.build b/src/interfaces/ecpg/compatlib/meson.build
index 56e0a21651b..5d32636c1e3 100644
--- a/src/interfaces/ecpg/compatlib/meson.build
+++ b/src/interfaces/ecpg/compatlib/meson.build
@@ -20,11 +20,13 @@ 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: [frontend_stlib_code, thread_dep, dep_static_lib],
   link_with: [ecpglib_st, ecpg_pgtypes_st],
   kwargs: default_lib_args,
 )
-ecpg_targets += ecpg_compat_st
+if not dep_static_lib.disabled()
+  ecpg_targets += ecpg_compat_st
+endif

 ecpg_compat_so = shared_library('libecpg_compat',
   ecpg_compat_sources + ecpg_compat_so_sources,
diff --git a/src/interfaces/ecpg/ecpglib/meson.build b/src/interfaces/ecpg/ecpglib/meson.build
index 8f478c6a73e..3c61bdeeffd 100644
--- a/src/interfaces/ecpg/ecpglib/meson.build
+++ b/src/interfaces/ecpg/ecpglib/meson.build
@@ -30,11 +30,13 @@ 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: [frontend_stlib_code, thread_dep, libpq, dep_static_lib],
   link_with: [ecpg_pgtypes_st],
   kwargs: default_lib_args,
 )
-ecpg_targets += ecpglib_st
+if not ecpglib_st.disabled()
+  ecpg_targets += ecpglib_st
+endif

 ecpglib_so = shared_library('libecpg',
   ecpglib_sources + ecpglib_so_sources,
diff --git a/src/interfaces/ecpg/pgtypeslib/meson.build b/src/interfaces/ecpg/pgtypeslib/meson.build
index 02301ec9acb..b6fc20e9db6 100644
--- a/src/interfaces/ecpg/pgtypeslib/meson.build
+++ b/src/interfaces/ecpg/pgtypeslib/meson.build
@@ -26,10 +26,12 @@ 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: [frontend_stlib_code, dep_static_lib],
   kwargs: default_lib_args,
 )
-ecpg_targets += ecpg_pgtypes_st
+if not ecpg_pgtypes_st.disabled()
+  ecpg_targets += ecpg_pgtypes_st
+endif

 ecpg_pgtypes_so = shared_library('libpgtypes',
   ecpg_pgtypes_sources + ecpg_pgtypes_so_sources,
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index a74e885b169..ea3f540f8bc 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: [frontend_stlib_code, libpq_deps, dep_static_lib],
   kwargs: default_lib_args,
 )