This is an archive of the discontinued LLVM Phabricator instance.

Create a generic ABI document for _BitInt
Needs ReviewPublic

Authored by aaron.ballman on Dec 6 2021, 9:57 AM.

Details

Summary

This document describes a generic ABI for targets to opt into if they wish.

It was split off from the discussion started in https://reviews.llvm.org/D108643.

Diff Detail

Event Timeline

aaron.ballman created this revision.Dec 6 2021, 9:57 AM
aaron.ballman requested review of this revision.Dec 6 2021, 9:57 AM
Herald added a project: Restricted Project. · View Herald TranscriptDec 6 2021, 9:57 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 20 2022, 8:28 AM
aaron.ballman edited reviewers, added: efriedma; removed: rsmith.Sep 21 2022, 7:08 AM

Now that C2x is closer to getting finalized, I would like to get this documentation up somewhere public so that other implementations can see what we do and match our behavior more easily. Changing up the reviewers and pinging the review again, but I believe this documentation is still accurate except for mention of vector types (which are powers-of-two currently and so behave the same as existing vector types and thus don't need a lot of documentation aside from mentioning that).

gustedt added a comment.EditedSep 21 2022, 8:09 AM

It seems that this has already shipped on some platforms. Since this basically binds others to use the same ABI, it would perhaps be nice if the document could have a table that lists MaxFundamentalWidth and chunk_t for those platforms. Also discussing consequences for va_arg functions such as printf would be nice.
Thanks!`

It seems that this has already shipped on some platforms. Since this basically binds others to use the same ABI, it would perhaps be nice if the document could have a table that lists MaxFundamentalWidth and chunk_t for those platforms.

Sure, that seems reasonable.

Also discussing consequences for va_arg functions such as printf would be nice.

Does the information in the Passing and Returning an Object section suffice, or are there more details you're looking for there?

This comment was removed by gustedt.

Also discussing consequences for va_arg functions such as printf would be nice.

Does the information in the Passing and Returning an Object section suffice, or are there more details you're looking for there?

The narrow _BitInt types are not promoted to int for arithmetic.

For the function call ABI we would need to know if the same strategy holds for va_arg parameters. For each of these types with representing standard integer type T two scenarios would be possible

  • When passed to a va_arg function the same rules for T as an argument for a prototyped function parameter apply.
  • When passed to a va_arg function the value is promoted as if it where a T, that is in general there is a promotion to int.

This has in particular implications to whether or not the wN length modifier for printf and scanf can be used for narrow _BitInt types or not: in the first scenario that would not be possible in the second in would be possible without problems.

I would be much in favor of the second choice, va_arg functions usually are not made to handle narrow input well.

Also discussing consequences for va_arg functions such as printf would be nice.

Does the information in the Passing and Returning an Object section suffice, or are there more details you're looking for there?

The narrow _BitInt types are not promoted to int for arithmetic.

For the function call ABI we would need to know if the same strategy holds for va_arg parameters. For each of these types with representing standard integer type T two scenarios would be possible

  • When passed to a va_arg function the same rules for T as an argument for a prototyped function parameter apply.
  • When passed to a va_arg function the value is promoted as if it where a T, that is in general there is a promotion to int.

This has in particular implications to whether or not the wN length modifier for printf and scanf can be used for narrow _BitInt types or not: in the first scenario that would not be possible in the second in would be possible without problems.

I would be much in favor of the second choice, va_arg functions usually are not made to handle narrow input well.

Thanks for pointing out that the current docs aren't clear enough about the varargs case!

My strong preference is for the first choice.

My understanding of WG14 sentiment is that integer and default argument promotions are not for new types. It's even spelled out in DR206 (https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_206.htm): "This was intentional because real float promotion to double is in Standard C purely for compatibility with K&R. Since complex is new, that compatibility is not an issue, and having it behave like real float would introduce undesired overhead (and be less like Fortran)." _BitInt is similarly new and there is potential for overhead. Also, C2x did not change default argument promotion rules for _Decimal32 or _Float32, so _BitInt is consistent with the rest of the new fundamental types.

What worries me about what you'd like to see changed is that it strengthens the guarantees users have in that it's now *well defined* to pass in a _BitInt(4) at the call site of a variadic parameter, but pull it out as a _BitInt(32) when default argument promotions happen; we don't want users to be able to rely on that guarantee. This is our chance to have an integer type which makes a clean break from the K&R C days and given the positive user feedback I've received about *not* promoting, I'd want a pretty strong motivation for why _BitInt should undergo default argument promotions.

My recommendation for library authors who want to supply a printf or scanf implementation is to implement https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2858.pdf with the caveat that WG14 has not formed an official stance on the paper. As C2x is currently specified (which could still change due to NB comments), I don't think the wN format specifier can support bit-precise integers because of the promotion behavior (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2680.pdf). An int8_t is not the same as a _BitInt(8) despite both being eight bits wide.