128-bit Integer Types
- Author: Stephen Canon
- Review Manager: TBD
- Status: Pitch
Motivation
128b integers are the largest fixed-size type that is currently commonly used in "general-purpose" code. They are much less common than 64b types, but common enough that adding them to the standard library makes sense.
We use them internally in the standard library already (e.g. as an implementation detail of Duration).
Proposed solution
Introduce two new structs, UInt128
and Int128
, conforming to all of the usual fixed-width integer protocols.
Detailed design
The API of these types are entirely constrained by their protocol conformances. No other API is being invented or introduced. They will have the same API as any other fixed-width integer type.
While the API of these types is fully determined, their ABI must be resolved. Specifically, we must address the question of their endianness and alignment. This has not been a decision that we had to make for other basic integer types--their layout was determined by the constraint of interoperability with the corresponding C type. However, C does not have _a _ 128-bit integer type--it has between zero and two.
There's no good reason not to maintain platform endianness, so we should simply do that. However, alignment is quite a bit murkier. Let's dive in.
Clang and GCC have historically exposed the extension types __uint128_t
and __int128_t
on 64b platforms only. These types basically behave like C builtin integer types--their size and alignment are 16B.
The C23 standard introduces _BitInt(N)
as a means to spell arbitrary-width integer types, but these still have some warts. In particular, _BitInt(128)
as implemented in clang has 8B alignment on x86_64 and arm64. For arm64, this is clearly a bug; the AAPCS specifies that it should have 16B alignment. For x86_64, the situation is less clear. The x86_64 psABI document specifies that it should have 8B alignment, but the authors of the proposal that added the feature tell me that it should be 16B aligned and that they are attempting to change the psABI.
I propose that [U]Int128
be 16B aligned on 64b platforms,Âą matching __[u]int128_t
(and _BitInt(128)
assuming that C fixes their mess before the ABI becomes locked in). On 32b platforms, I propose that it has whatever alignment UInt64
has. This matches the behavior of _BitInt()
on platforms where it's been defined, and is really the only sensible definion for platforms that do not have a clear precedent. It certainly should not be less-aligned than UInt64
, and there's not much reason to give it higher alignment on any 32b architecture either.
The clang importer will be updated to bridge __uint128_t
to UInt128
and __int128_t
to Int128
. We will not import _BitInt()
types until the ABI problems with those types have been clearly resolved.
Âą For the purposes of this discussion, arm64_32 is a 64b platform; i.e. UInt128
will be 16B aligned on that target; I would expect the same to apply to Swift targeting other "32-bit pointer in a 64b environment" platforms.
Source compatibility
This proposal has no effect on source compatibility.
ABI compatibility
This proposal has no effect on ABI compatibility.
Implications on adoption
Adopting this feature will require a target with runtime support.
Future directions
Implement clang importer support for _BitInt(128)
on any platforms where the finalized ABI is compatible with our layout.
Alternatives considered
Rather than adding [U]Int128
, we could implement some form of generic-sized fixed-width integer (like _BitInt()
in C). Given both the lack of consensus around what integer generic parameters ought to look like in Swift (or if they ought to exist at all), and the growing pains that _BitInt()
is currently going through, such a design would be premature.
While other fixed-width integer types are interesting, 128 bits is a couple orders of magnitude more useful than all the others for general-purpose software at this point in time. So doing only 128b integers now makes good sense.
I'm interested in feedback about my thinking regarding alignment; everything else about this pitch is entirely determined by existing protocol conformances. I'll make a package available sometime in the next few days for people to experiment with using these types.