Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ABI for _BitInt #419

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

ABI for _BitInt #419

wants to merge 1 commit into from

Conversation

kito-cheng
Copy link
Collaborator

_BitInt (N) is the type defined in C23, allow user to define an arbitrary-sized integer type, where N is a postive integer larger than zero.

This proposal defined the size and alignment of _BitInt, and define the unused bits as unspecified which is same as x86-64 and AArch64.

For the calling convention part, we keep unused bits as unspecified.

Ref:

Fix #300

`_BitInt (N)` is the type defined in C23, allow user to define an
arbitrary-sized integer type, where N is a postive integer larger than zero.

This proposal defined the size and alignment of _BitInt, and define the
unused bits as unspecified which is same as x86-64 and AArch64.

For the calling convention part, we keep unused bits as unspecified.

Ref:

- ISO/IEC WG14 N2763:
  https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2763.pdf

- [AArch64] Rationale Document for ABI related to the C23 _BitInt type.
  https://github.com/ARM-software/abi-aa/tree/main/design-documents/bit-precise-types.rst

- AAPCS64 for _BitInt(N)
  ARM-software/abi-aa@d621417

- x86-64 ABI for _BitInt(N)
  https://gitlab.com/x86-psABIs/x86-64-ABI/-/commit/8ca45392570e96920f8a15d903d6122f6d263cd0

Fix #300
@kito-cheng
Copy link
Collaborator Author

When passed in registers or on the stack, `__BitInt(N)`, unused bits are
undefined, types narrower than XLEN bits are widened to XLEN bits, with the
upper bits undefined.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The question of what can be done with unused bits is discussed here (incl. consequence for the ARM ABIs): https://github.com/ARM-software/abi-aa/blob/main/design-documents/bit-precise-types.rst#options-and-their-trade-offs-1.

I think it would be reasonable for RISC-V (both, RV32 and RV64) to require sign-extension/zero-extension depending on whether the type is signed/unsigned.

Benefits (inspired by the referenced document):

  • Operations ==,<,<=,>=,>,>>, widening conversions, and loading/storing to memory would all naturally work.
  • Matches the expectation of developers, with a _BitInt(8) in a register matching the representation of a char.

Drawbacks (again inspired by the referenced doc):

  • Operations +,-,*,<< would all cause the need for masking/extending at an ABI boundary.

The "matches the expectation of developers" is my main motivation for mentioning this.

Copy link
Contributor

@aswaterman aswaterman Jan 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd propose we do whatever is empirically most performant, regardless of intuitiveness. But my sense is that comparisons and conversions to wider types will be more common than basic arithmetic on these types. So maybe we get lucky, and the intuitive design and the performant design are the same one.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And performant should necessarily include safety and security as much as one thinks of speed and size.
It's like the distinction between malloc (or even alloc) and calloc. The former is lean and elegant and, thus, fast and small. It fits well in its particular use cases. The latter helps guarantee, for example, arrays of characters (i.e. strings) always are suffixed with terminators. The latter also makes sure yet unused elements of the allocated range don't have any previous information leaking through.
Performance and intuition should thus carefully consider elegance, scope, and use case.

Copy link
Collaborator

@MaskRay MaskRay Feb 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition, there is an ongoing discussion on x86-64-abi about the unused bits : https://groups.google.com/g/x86-64-abi/c/hO9lHnIf-tU

The unused bits are unspecified, which allows efficient +,-,*,<<, narrowing, and
atomics when supported.

BTW: "are undefined" is too strong. We should just say "are unspecified".

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I favor "undefined" for consistency with the aggregate rules in the standard calling convention.

Consistency with the treatment of other integer types, and following the logic used in aapcs, suggests type-sign extension up to 32 bits and sign extension to XLEN. Ideally, we would have empirical data from at least one real-world application before committing to this decision.

The sizes and alignments look reasonable to me.

@kito-cheng
Copy link
Collaborator Author

Plan to putting more table for the code gen among 3 different options, I was too optimistic that I could have time to doing that...:( anyway will put that once I have one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Define _BitInt ABI
6 participants