Skip to content

add @bitSizeOf #2177

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

Closed
shawnl opened this issue Apr 3, 2019 · 7 comments · Fixed by #4202
Closed

add @bitSizeOf #2177

shawnl opened this issue Apr 3, 2019 · 7 comments · Fixed by #4202
Labels
accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@shawnl
Copy link
Contributor

shawnl commented Apr 3, 2019

Currently we can't pack []u1 less that a byte for example. This would be a requirement to do that.

@shawnl
Copy link
Contributor Author

shawnl commented Apr 3, 2019

I ran into this working on mem.copy 27e2589

@andrewrk andrewrk added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Apr 4, 2019
@andrewrk andrewrk added this to the 0.5.0 milestone Apr 4, 2019
@shawnl shawnl changed the title add @bitSizeOf and consider changing @sizeOf to return bits. add @bitSizeOf Apr 5, 2019
@shawnl
Copy link
Contributor Author

shawnl commented Apr 5, 2019

I was thinking @sizeOf should stay. If introduced, @bitSizeOf would be the size of a type when in a slice or array, and @sizeOf the size not in a slice or array. The types that would be packed would be bool u1 u2 and u4 (and i2 and i4).

Would this work? What would it break?

And if this works, we could consider a tri-state type, that would be u2 alone, but fit five-to-a-byte when packed.

@andrewrk
Copy link
Member

andrewrk commented Apr 5, 2019

@sizeOf should definitely stay and be defined the same way. Citing the docs:

This size may contain padding bytes. If there were two consecutive T in memory, this would be the offset in bytes between element at index 0 and the element at index 1. For integer, consider whether you want to use @sizeOf(T) or @typeInfo(T).Int.bits.

@sizeOf's current definition protects us against undefined behavior, because it makes sure that there is enough padding bytes for the aligned loads and stores that LLVM expects to be able to do.

However there is a concept of bit size, which corresponds in stage1 to type->size_in_bits. The relationship between the two is (given abi_align which is the required byte alignment of loads and stores):

  • (size_in_bits + 7) / 8 gives you the "store size", which is how much memory in bytes is actually used to store the bits. This concept is not exposed in the Zig language, other than @typeInfo(i32).Int.bits corresponding to size_in_bits.
  • alignForward(store_size, abi_align) gives you the @sizeOf, also known as "ABI size". The extra bytes are needed as ABI-aligned loads and stores assume that they have the padding bytes available. The LLVM language reference is not 100% clear about whether align(1) loads and stores will only touch the "store size" bytes, but when I asked about it on IRC, the answer I got was "don't rely on that."

@bitSizeOf would not be the size of a type when in a slice or array. That is the purpose of @sizeOf. @bitSizeOf would correspond exactly to type->size_in_bits in the stage1 compiler. That being said, I'm struggling to think of when it would make sense to use @bitSizeOf.

Can you elaborate on your use case?

@shawnl
Copy link
Contributor Author

shawnl commented Apr 5, 2019

Can you elaborate on your use case?

The idea is to support more compact packing. This may not belong in the language at all, but I'm thinking of how we would do it.

It would be a significant change to the language to allow sub-byte packings, as certain assumptions would break, such as using sizeOf(T) * source.len, and also sub-slices could only start at byte-aligned indexes.

Again, this could all be done in user-space, so it is mostly an idea. If we don't support the assumptions that would break should be documented as assumptions that can be relied on. Basically this is an ask for a accept or reject, on whether slices and arrays will ever be able to have sub-byte sizes and type-width.

@andrewrk
Copy link
Member

Also @bitOffsetOf needs to be audited. (see #1512 (comment))

@andrewrk andrewrk modified the milestones: 0.5.0, 0.6.0 Sep 20, 2019
@andrewrk andrewrk added the accepted This proposal is planned. label Jan 7, 2020
@andrewrk
Copy link
Member

andrewrk commented Jan 7, 2020

@bitSizeOf(T) where T is an integer returns @typeInfo(T).Int.bits. For types that are perfectly aligned it returns @sizeOf(T) * 8. However, for many types, the actual number of bits it takes to represent the data does not round to a byte. For example, a packed struct that does not have byte alignment. For these types @bitSizeOf will be meaningful. This concept exists in the compiler, and can be simply exposed.

@andrewrk andrewrk modified the milestones: 0.6.0, 0.7.0 Jan 7, 2020
@shawnl
Copy link
Contributor Author

shawnl commented Jan 16, 2020

 This function measures the size at runtime. For types that are disallowed at runtime, such as
{#syntax#}comptime_int{#endsyntax#} and {#syntax#}type{#endsyntax#}, the result is {#syntax#}0{#endsyntax#}.

I can't find a detailed reason why this is needed over erroring if we can't return a sensible result. Types are always comptime. Throwing an compile error when possible is part of the zen of zig, and prevents bugs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants