Looks like a sign confusion, signed -300 hex is the same as unsigned FFFD00 hex (eg the second case are the same bits when viewed through the type u24 instead of i24).
Maybe different sign extension when widening to register width (eg replicating the MSB vs filling up with zero bits). Not sure how an i24 would ever print as unsigned FFFD00 though, since technically that’s out of range for an i24.
My guess was self-hosted backend incorrectly doing @intCast (in the hex print code), but changing foo to @bitCast(@as(u24, 0xfffd00)) fixes it.
So I inspected the raw bytes and the unused bits are different between your foo init and mine which seems to affect the sign extension. Looks like @floooh’s guess is correct.
I took a look at the assembly and I can tell you I have no idea how sign extension works in assembly :3, but the backends are definitely doing it in different ways. Self-hosted is using movslq (hardware sign extension) whereas LLVM does something that looks more correct shl, sar, ..
I believe what you are doing is actually IB. Note that @sizeOf(i24) == 4 and std.mem.bytesToValue is basically just a pointer cast and a dereference of this pointer.
I think what you probably want to do instead is use std.mem.readInt or directly use @bitCast.
Using @bitCast also shouldn’t work according to its doc comment.
Asserts that @sizeOf(@TypeOf(value)) == @sizeOf(DestType).
But what it actually does is check whether @bitSizeOf(@TypeOf(value)) == @bitSizeOf(DestType)
Thanks for the replies! I ended up using std.mem.readInt for now, it works well enough.
I understand why this happens for the most part, but just to confirm @floooh’s point about FFFD00 being handled as unsigned in i24, it is affecting calculations as well: I found out about this problem by getting some extreme clipping when playing audio, and discovered samples like FFFD00 being converted into into :f128 = 1.9999086856733185855530006352663797, when it should’ve been a value between -1 and 1.
I wonder if this behavioral difference is intentional in the zig backend or not