Support for 32-bit CPUs

I know that 64-bit CPUs offer many advantages, and that the main one is that there are more unused bits in an object pointer, which lets compiler writers implement constant values like short strings, floats, integers and so on as just a pointer rather than a malloc'd chunk of memory. (Sometimes called a packed pointer.)
However 32-bit CPUs still exist and are widely used in the Linux realm e.g. in IoT, in single-board computers, and of course in older computers that haven't been abandoned.
What are the current reasons for Swift's not supporting 32-bit CPUs?
I did compile Swift for a 32-bit Raspberry pi and it got almost entirely through it before the last link phase which failed.

1 Like

Swift doesn’t not support 32-bit platforms. As an open source project, interested developers can certainly step up to maintain those ports.

In fact, we already support several 32-bit platforms, including both architectures of the Apple Watch. I believe supporting 32-bit Windows is also on the roadmap, although @compnerd can speak better to that.

In general, ports to other platforms are extremely welcome, and I think there are already people in the community working on Raspberry support.

7 Likes

@John_McCall is absolutely correct about the 32-bit support. In addition to the apple platforms, the Windows and Linux do support 32-bit targets.

The Windows 32-bit target needs some attention to address regressions, and is part of the roadmap. There isn’t as much benefit to the 64-bit on Windows unlike other platforms, and would be better served with improvements to the 32-bit target. The toolchain itself uses swift, and in order to improve the developer experience the majority of the focus has remained on the 64-bit target as that does benefit from the 64-bit support.

The Linux 32-bit targets also are in somewhat similar state with needing attention for addressing regressions. Using the android armv7 as a proxy for Linux armv7, which is still 32-bit, there’s only a couple of failures, so it should be possible to get things working. I had a couple of local patches for it, but @Finagolfin actually independently had the same changes and actually was kind enough to work through upstreaming them.

The statement of “swift doesn’t support 32-bit” is not very accurate. The support is there in the toolchain, and improving that requires regular maintenance work which needs more engineering support due to competing priorities.

I maintain maybe the only 32-bit Swift 5.3 toolchain right now, available on any Android ARMv7 device running 7.0 or later, and @uraimo has been putting out 32-bit ARM builds for much longer. As Saleem says, 32-bit arches are supported but since not many are actively building for or maintaining those platforms, regressions have cropped up. I upstreamed the small patch I needed for Android ARMv7 last month (two of the changes were not Android-specific and fixed all 32-bit platforms) and if you share the link error you got, I'm sure that could be fixed too.

I use Swift on Raspberry Pi 4 every day in 64-bit mode.

2 Likes

We're building a ~15k line Swift library for macOS, iOS, Windows, Ubuntu, and Android at the moment. We are trying to round out our platform support before releasing the library for deployment along with a large software product on those platforms. We have good builds and CI/CD set up for macOS 10.13 and up, iOS v13 and up, Ubuntu 16.04 and up, Android 7 (32-bit & 64-bit) (thanks @Finagolfin!) and up, and Windows 10 x86_64.

Since we have many users of the product, we had hoped to also release Windows 10 x86, as it appears we do have a small percentage of users on it. However I have not been able to get a development environment set up to compile for 32-bit. It also appears that the DLLs bundled with the official releases are all compiled for 64-bit.

How should I best invest time in trying to get a Windows 10 x86 build going? Use the existing binary toolchain release and cross-compile from Windows 10 x86_64? Build the SDK and toolchain from source? Another way?

This is intentional. I don't think that we should ever bother with a 32-bit toolchain for Windows. The toolchain should always be 64-bit, and you would cross-compile to 32-bit. The only piece that should be needed is the i686 SDK and runtime (for distribution and testing). The currently distributed Windows toolchain is already setup to support x86 target.

Windows x86 was supported a long time back. However, it currently is not possible to build. If you want to revive the target, the first "last" piece to be done is fixing LLVM. The LLVM code generation for x86 Windows currently does not handle floating point conversion correctly, and the result is that you cannot build the standard library for x86.

The next piece where I suspect that you will hit issues is with Foundation as I never actually built that for a 32-bit platform, and so there may be issues with value truncation that will need to be addressed, but that should be relatively easy to get working, and is a matter of just running through the test suite.

Wow! Thanks for the prompt reply! I will see how much effort I can get scheduled for 32-bit support given the percentage of current users. If / when I start trying to revive the target, I'll follow up.

We've unfortunately decided to skip Windows 10 32-bit support for now. Windows 10 64-bit, Ubuntu, macOS, iOS, Android are a pretty good list to start I suppose. If anyone does choose to take up the Windows 10 32-bit effort, please let us all know!

I would like to revive this issue, as the only person seemingly distributing a 32-bit Swift toolchain now, with my 5.6.1 build for Android armv7. I had to apply a commit from trunk to get the compiler to build and it appears to work well now, other than a runtime regression and a few prior bugs.

Given the upcoming embedded push and focus on performance, we should set up a CI for some 32-bit platform, to make sure it keeps building. I had to apply three patches to include/swift/ to get the Apr. 17 snapshot of the 5.7 branch to build for Android armv7 but the resulting compiler segfaults, haven't looked into why. I also recently reported some trunk regressions when building the stdlib for armv7 on my Android CI.

@futurejones, I don't know how well AArch32 support works on linux AArch64, would you be willing to set up 32-bit builds as part of your upcoming ARM CI? @ColemanCDA, you may be interested in getting a proper 32-bit CI going too, considering your recent 32-bit pulls.

I'm not interested in a 32-bit toolchain for Windows, but definitely care about the 32-bit runtime (for x86 and ARMv7).

1 Like

We definitely want to maintain the ability to host the toolchain in a 32-bit environment, but I'm not surprised that portability bugs have crept in, given how much we use PointerUnion and given that prevalence of 64-bit on developer machines these days. Having a 32-bit host CI would be a great start.

4 Likes

@Finagolfin
Yes, definitely looking at adding 32-bit builds to the new Swift Arm Community CI
I am currently experimenting with docker and qemu to emulate armv7l on aarch64. If anyone has experience in this or other VM emulation options I would love to hear from you.

1 Like

I haven't used docker or qemu for this, but on linux x86_64, I've seen distros add a 32-bit compat mode, where you can install a bunch of i686 packages and build and run software for 32-bit linux i686 without a problem.

Given that most AArch64 CPUs can similarly run AArch32 software without a problem, I was hoping there would be a similar armv7 compat mode in the packaging system of whatever linux distro you are running on your CI. That would be the easiest way to set this up on 64-bit ARM, and I've been manually doing something similar to test my Android armv7 Swift toolchain on my Android AArch64 phone.

If you'd like to discuss further, feel free to PM or email me instead and maybe we can get a 32-bit CI easily set up on your 64-bit server.

I am making good progress with docker emulation of arm32v7 on the 64-bit server.
It turns out there are already official 32 bit docker images for both Debian and Ubuntu.
Ubuntu - Docker Hub
Debian - Docker Hub
These can be run using the --platform linux/arm/v7 option to give 32-bit armv7 build environment.

~$ docker run --platform linux/arm/v7 -it arm32v7/ubuntu
root@07e0cbfdc06d:/# uname -a
Linux 07e0cbfdc06d 5.4.0-107-generic #121-Ubuntu SMP Thu Mar 24 16:07:22 UTC 2022 armv7l armv7l armv7l GNU/Linux

I am running some test armv7 builds of swift on Debian and Ubuntu at the moment. Hopefully will have the 32-bit CI set up by the end of the week.

3 Likes

I am making good progress with docker emulation of arm32v7 on the 64-bit server.

Great, but does Docker run armv7 natively on AArch64 or run it through QEMU emulation first, as it would on x86_64? The latter is going to be much slower, which is why I suggested the 32-bit packaging compat mode instead, if it exists for armv7. I have almost no experience with Docker, so just asking how it works.

Docker runs armv7 through QEMU emulation so there is a big performance drop compared to native aarch64.

The build environment needs to docker contained so it can coexist with the other Jenkins build jobs running on the server. There will be multiple build jobs for many different Debian and Ubuntu versions running.

Swift toolchain builds are usually taking around 50mins in native aarch64. The test armv7 builds I have run are taking around 2 hours. (builds are failing but near completion)
So even though this is a lot longer I still think this is a very good and usable build time.

Docker runs armv7 through QEMU emulation so there is a big performance drop compared to native aarch64.

I just looked it up and Debian/Ubuntu both claim to support armv7 in a Multiarch mode, with some people saying it worked for them. You could always get that set up in an AArch64 Docker, if you need the isolation from other build jobs, but get much faster builds and test runs by running the armv7 binaries natively by using this Multiarch mode.

As for the failing builds, check out the patches I linked above. I'm about to try out an Android armv7 build of the Apr. 20 trunk snapshot source on my Android AArch64 phone, will let you know what I find. Edit: The trunk snapshot crashes too when built for armv7.

I have managed to improve 32-bit build performance greatly by using combination of docker platform (linux/arm/v7) and a custom arch32v7 docker image with a patched uname. This gives us near native performance and what was taking 2 hours is now only taking 15 mins.

The server is up and running at https://ci.swiftlang.xyz/
Debian Bullseye Armv7 build job - swift-5.6.1-debian-bullseye-armv7 [Jenkins]
The Docker images are available here - Docker Hub

I have also setup a Github repository ci-swiftlang for the build jobs and will have more details on how to contribute patches and fixes soon, once I get PR testing setup.

4 Likes