Live data from Hacker News

Zig's new bitCast semantics and LLVM back end improvements

ziglang.org

41–50 of 159 posts

Re: Zig's new bitCast semantics and LLVM back end improvements

#41

This change + the existing packed struct logic will be great for working with bit packed binary headers w/o having to manually twiddle so much about the bit handling along the way.

Zig is already great for this with ‘packed struct’ and arbitrary size ints. Allows for very clean protocol creation between systems with known properties. This is another great step in that direction.

Re: Zig's new bitCast semantics and LLVM back end improvements

#42
post #26
post #22

Earlier quoted context omitted.

If I understand it correctly, it basically boils down to copying bits from the source to the destination, in order from the least significant bit to the most significant bit. It's not equivalent to C++'s reinterpret_cast. I'm no Zig expert, but if you want endian-dependent semantics I'd assume either @ptrCast or a packed union would do the job.

But doesn't that show why this is a bad idea? If I understand correctly, this code: const MyUnion = packed union { full: u16, bytes: [2]u8, }; const value: u16 = 0x55aa; const in_union: MyUnion = @bitCast(value); const without_union: [2]u8 = @bitCast(value); std.debug.assert(without_union[0] == in_union.bytes[0]); std.debug.assert(without_union[1] == in_union.bytes[1]); ...will now succeed or fail depending on the en…

zig does not allow arrays in packed structs/unions specifically for endianness reasons (there may be other reasons as well but endianness is what i know of)

Re: Zig's new bitCast semantics and LLVM back end improvements

#43

> Consider, for instance, bitcasting a [2]u8 to a u16. Under the old semantics, the result of this operation depends on the target endian: on big-endian targets, the first array element became the 8 most significant bits, whereas on little-endian targets, the first array element became the 8 least significant bits. Under the new semantics, because we only care about logical bit representation (which is endian-agnosti…

You don't need to use @bitCast for the behavior you're talking about. @ptrCast still exists.

@ptrCast,

> Converts a pointer of one type to a pointer of another type. [1]

[1] https://ziglang.org/documentation/master/#toc-ptrCast

So it is not the same.

You could use it to define a function that implements bitCast. Which defeats the purpose of having any @bitCast intrinsic instead of using @mempcy for everything

Re: Zig's new bitCast semantics and LLVM back end improvements

#44

OT: I'm always surprised at how popular Zig discussions get here, or Youtube and other medias. Don't get me wrong, I love Zig and I think it's a great C replacement, but I'm very confused on why C3 or Odin rarely get any attention at all, despite being in the same C-replacement crowd. But still surprised at what Zig does better than these other projects? Is Andrew much better at marketing/promoting the language? He's…

With Zig, I can just import SDL.h and use it without writing a binding. Can I do that in C3 or Odin?

Odin has SDL built into the language (shipped as a vendored library).

Re: Zig's new bitCast semantics and LLVM back end improvements

#45

OT: I'm always surprised at how popular Zig discussions get here, or Youtube and other medias. Don't get me wrong, I love Zig and I think it's a great C replacement, but I'm very confused on why C3 or Odin rarely get any attention at all, despite being in the same C-replacement crowd. But still surprised at what Zig does better than these other projects? Is Andrew much better at marketing/promoting the language? He's…

With Zig, I can just import SDL.h and use it without writing a binding. Can I do that in C3 or Odin?

And then you can get AI do a nicer port of SDL.zig and you get way better decls.

Proper enums, proper tagged unions, and often reading the docs can allow the AI to distinguish T * to one of

1. [*]T

2. [:0]T

3. ?T

4. *T

And these are just the most common ones. If you know it’s a read only pointer/array then you can add the const modifier

Re: Zig's new bitCast semantics and LLVM back end improvements

#46

Earlier quoted context omitted.

With Zig, I can just import SDL.h and use it without writing a binding. Can I do that in C3 or Odin?

Odin has SDL built into the language (shipped as a vendored library).

That's not what I mean...

There is a mountain of code written in C that you can simply include in Zig without a wrapper dependency and without having to create the wrapper yourself.

Re: Zig's new bitCast semantics and LLVM back end improvements

#47
post #27

> Consider, for instance, bitcasting a [2]u8 to a u16. Under the old semantics, the result of this operation depends on the target endian: on big-endian targets, the first array element became the 8 most significant bits, whereas on little-endian targets, the first array element became the 8 least significant bits. Under the new semantics, because we only care about logical bit representation (which is endian-agnosti…

> Just don't allow casting to u24, as it makes no sense unless you define u24 to be u32 sized as I think c standard does. The reason u32->u24 casting must be well defined is because some hardware (e.g. many GPUs, microcontrollers) only have floating point multipliers. A 24 bit unsigned integer (stored in a 32 bit register) can be losslessly converted to a 32 bit float by the hardware, multiplied, then converted back.…

> many GPUs

Citation please - every single GPU in the literal world supports integer arithmetic for operating on tid, gid, etc.

Re: Zig's new bitCast semantics and LLVM back end improvements

#48

> Consider, for instance, bitcasting a [2]u8 to a u16. Under the old semantics, the result of this operation depends on the target endian: on big-endian targets, the first array element became the 8 most significant bits, whereas on little-endian targets, the first array element became the 8 least significant bits. Under the new semantics, because we only care about logical bit representation (which is endian-agnosti…

GCC has had __int24 for the AVR backend for some time. Useful for larger integers than int16_t while saving 25% over a 32-bit value. C23 does not mandate padding for _BitInt types. It is wrong to assume that will happen or is the optimal implementation for portable code.

Thanks for the context, but what I am criticising is this part:

> it became allowed to use @bitCast to reinterpret a [3]u8 as a u24

This cant't make sense unless u24 is defined to be 24bits in the first place. It is just silly to allow something like this. It would make so much more sense to me if they started disallowing this or just even print a deprecation notice for it for one release version.

> Useful for larger integers than int16_t while saving 25% over a 32-bit value

You can't even do []u24 in zig as far as I can remember and understand anyway so this is only happening in a packed struct context.

C doesn't mandate padding but C compilers allow having pointers and arrays of irregular _BitInt types as far as I can understand.

In this [1] document, in Abi considerations section, it writes that it is defined to have next-power-of-two layout size.

Also here (for RISCV) [2] it seems like it is defined with next-power-of-two layout.

Also the document here (for x86_64) defines it similarly [3]

[1] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2709.pdf

[2] https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/...

[3] https://gitlab.com/x86-psABIs/x86-64-ABI/-/tree/master?ref_t...

Re: Zig's new bitCast semantics and LLVM back end improvements

#49
post #26

Earlier quoted context omitted.

But doesn't that show why this is a bad idea? If I understand correctly, this code: const MyUnion = packed union { full: u16, bytes: [2]u8, }; const value: u16 = 0x55aa; const in_union: MyUnion = @bitCast(value); const without_union: [2]u8 = @bitCast(value); std.debug.assert(without_union[0] == in_union.bytes[0]); std.debug.assert(without_union[1] == in_union.bytes[1]); ...will now succeed or fail depending on the en…

I wonder if packed union also got/will get the same "logical bits" treatment?

My understanding is that the "logical bits" view breaks down for unions, because the nth logical bit could be at different offsets depending on the union variant that's considered active.

Re: Zig's new bitCast semantics and LLVM back end improvements

#50

> Consider, for instance, bitcasting a [2]u8 to a u16. Under the old semantics, the result of this operation depends on the target endian: on big-endian targets, the first array element became the 8 most significant bits, whereas on little-endian targets, the first array element became the 8 least significant bits. Under the new semantics, because we only care about logical bit representation (which is endian-agnosti…

To me it makes sense. If you don't know what endianness is, it doesn't make sense that a program you write in one programming language works for one target but doesn't work for the other. I think endianness is the footgun that Zig is solving, rather than Zig being the one introducing a footgun when you deal with endianness.

> If you don't know what endianness is

It is not feasible for someone to write endian portable code in a language like Zig without understanding what endianness is imo. Regardless of how they change @bitCast there will be other cases that break this like doing @ptrCast + @memcpy.

Also this breaks currently written code that is endian portable and uses @byteSwap like it is done in most other programming languages that do these things.

Post reply on HN