| 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; |
| 4 | const expect = std.testing.expect; |
| 5 | const expectEqual = std.testing.expectEqual; |
| 6 | const math = std.math; |
| 7 | const maxInt = std.math.maxInt; |
| 8 | const minInt = std.math.minInt; |
| 9 | const native_endian = builtin.target.cpu.arch.endian(); |
| 10 | |
| 11 | test "@bitCast iX -> uX (32, 64)" { |
| 12 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 13 | |
| 14 | const bit_values = [_]usize{ 32, 64 }; |
| 15 | |
| 16 | inline for (bit_values) |bits| { |
| 17 | try testBitCast(bits); |
| 18 | try comptime testBitCast(bits); |
| 19 | } |
| 20 | } |
| 21 | |
| 22 | test "@bitCast iX -> uX (8, 16, 128)" { |
| 23 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 24 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 25 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 26 | const bit_values = [_]usize{ 8, 16, 128 }; |
| 27 | |
| 28 | inline for (bit_values) |bits| { |
| 29 | try testBitCast(bits); |
| 30 | try comptime testBitCast(bits); |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | test "@bitCast iX -> uX exotic integers" { |
| 35 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 36 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 37 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 38 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 39 | |
| 40 | const bit_values = [_]usize{ 1, 48, 27, 512, 493, 293, 125, 204, 112 }; |
| 41 | |
| 42 | inline for (bit_values) |bits| { |
| 43 | try testBitCast(bits); |
| 44 | try comptime testBitCast(bits); |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | fn testBitCast(comptime N: usize) !void { |
| 49 | const iN = @Int(.signed, N); |
| 50 | const uN = @Int(.unsigned, N); |
| 51 | |
| 52 | try expect(conv_iN(N, -1) == maxInt(uN)); |
| 53 | try expect(conv_uN(N, maxInt(uN)) == -1); |
| 54 | |
| 55 | try expect(conv_iN(N, maxInt(iN)) == maxInt(iN)); |
| 56 | try expect(conv_uN(N, maxInt(iN)) == maxInt(iN)); |
| 57 | |
| 58 | try expect(conv_uN(N, 1 << (N - 1)) == minInt(iN)); |
| 59 | try expect(conv_iN(N, minInt(iN)) == (1 << (N - 1))); |
| 60 | |
| 61 | try expect(conv_uN(N, 0) == 0); |
| 62 | try expect(conv_iN(N, 0) == 0); |
| 63 | |
| 64 | if (N > 24) { |
| 65 | try expect(conv_uN(N, 0xf23456) == 0xf23456); |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | fn conv_iN(comptime N: usize, x: @Int(.signed, N)) @Int(.unsigned, N) { |
| 70 | return @as(@Int(.unsigned, N), @bitCast(x)); |
| 71 | } |
| 72 | |
| 73 | fn conv_uN(comptime N: usize, x: @Int(.unsigned, N)) @Int(.signed, N) { |
| 74 | return @as(@Int(.signed, N), @bitCast(x)); |
| 75 | } |
| 76 | |
| 77 | test "nested bitcast" { |
| 78 | const S = struct { |
| 79 | fn moo(x: isize) !void { |
| 80 | try expect(@as(isize, @intCast(42)) == x); |
| 81 | } |
| 82 | |
| 83 | fn foo(x: isize) !void { |
| 84 | try @This().moo( |
| 85 | @as(isize, @bitCast(if (x != 0) @as(usize, @bitCast(x)) else @as(usize, @bitCast(x)))), |
| 86 | ); |
| 87 | } |
| 88 | }; |
| 89 | |
| 90 | try S.foo(42); |
| 91 | try comptime S.foo(42); |
| 92 | } |
| 93 | |
| 94 | // issue #3010: compiler segfault |
| 95 | test "bitcast literal [4]u8 param to u32" { |
| 96 | const ip = @as(u32, @bitCast([_]u8{ 255, 255, 255, 255 })); |
| 97 | try expect(ip == maxInt(u32)); |
| 98 | } |
| 99 | |
| 100 | test "bitcast generates a temporary value" { |
| 101 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 102 | |
| 103 | var y: u16 = 0x55AA; |
| 104 | _ = &y; |
| 105 | const x: u16 = @bitCast(@as([2]u8, @bitCast(y))); |
| 106 | try expect(y == x); |
| 107 | } |
| 108 | |
| 109 | test "@bitCast packed structs at runtime and comptime" { |
| 110 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 111 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 112 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 113 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 114 | |
| 115 | const Full = packed struct { |
| 116 | number: u16, |
| 117 | }; |
| 118 | const Divided = packed struct { |
| 119 | half1: u8, |
| 120 | quarter3: u4, |
| 121 | quarter4: u4, |
| 122 | }; |
| 123 | const S = struct { |
| 124 | fn doTheTest() !void { |
| 125 | var full = Full{ .number = 0x1234 }; |
| 126 | _ = &full; |
| 127 | const two_halves: Divided = @bitCast(full); |
| 128 | try expect(two_halves.half1 == 0x34); |
| 129 | try expect(two_halves.quarter3 == 0x2); |
| 130 | try expect(two_halves.quarter4 == 0x1); |
| 131 | } |
| 132 | }; |
| 133 | try S.doTheTest(); |
| 134 | try comptime S.doTheTest(); |
| 135 | } |
| 136 | |
| 137 | test "bitcast packed struct to integer and back" { |
| 138 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 139 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 140 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 141 | |
| 142 | const LevelUpMove = packed struct { |
| 143 | move_id: u9, |
| 144 | level: u7, |
| 145 | }; |
| 146 | const S = struct { |
| 147 | fn doTheTest() !void { |
| 148 | var move = LevelUpMove{ .move_id = 1, .level = 2 }; |
| 149 | _ = &move; |
| 150 | const v: u16 = @bitCast(move); |
| 151 | const back_to_a_move: LevelUpMove = @bitCast(v); |
| 152 | try expect(back_to_a_move.move_id == 1); |
| 153 | try expect(back_to_a_move.level == 2); |
| 154 | } |
| 155 | }; |
| 156 | try S.doTheTest(); |
| 157 | try comptime S.doTheTest(); |
| 158 | } |
| 159 | |
| 160 | test "implicit cast to error union by returning" { |
| 161 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 162 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 163 | |
| 164 | const S = struct { |
| 165 | fn entry() !void { |
| 166 | try expect((func(-1) catch unreachable) == maxInt(u64)); |
| 167 | } |
| 168 | pub fn func(sz: i64) anyerror!u64 { |
| 169 | return @as(u64, @bitCast(sz)); |
| 170 | } |
| 171 | }; |
| 172 | try S.entry(); |
| 173 | try comptime S.entry(); |
| 174 | } |
| 175 | |
| 176 | test "bitcast packed struct literal to byte" { |
| 177 | const Foo = packed struct { |
| 178 | value: u8, |
| 179 | }; |
| 180 | const casted = @as(u8, @bitCast(Foo{ .value = 0xF })); |
| 181 | try expect(casted == 0xf); |
| 182 | } |
| 183 | |
| 184 | test "comptime bitcast used in expression has the correct type" { |
| 185 | const Foo = packed struct { |
| 186 | value: u8, |
| 187 | }; |
| 188 | try expect(@as(u8, @bitCast(Foo{ .value = 0xF })) == 0xf); |
| 189 | } |
| 190 | |
| 191 | test "bitcast passed as tuple element" { |
| 192 | const S = struct { |
| 193 | fn foo(args: anytype) !void { |
| 194 | comptime assert(@TypeOf(args[0]) == f32); |
| 195 | try expect(args[0] == 12.34); |
| 196 | } |
| 197 | }; |
| 198 | try S.foo(.{@as(f32, @bitCast(@as(u32, 0x414570A4)))}); |
| 199 | } |
| 200 | |
| 201 | test "triple level result location with bitcast sandwich passed as tuple element" { |
| 202 | const S = struct { |
| 203 | fn foo(args: anytype) !void { |
| 204 | comptime assert(@TypeOf(args[0]) == f64); |
| 205 | try expect(args[0] > 12.33 and args[0] < 12.35); |
| 206 | } |
| 207 | }; |
| 208 | try S.foo(.{@as(f64, @as(f32, @bitCast(@as(u32, 0x414570A4))))}); |
| 209 | } |
| 210 | |
| 211 | test "@bitCast packed struct of floats" { |
| 212 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 213 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 214 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 215 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 216 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 217 | |
| 218 | const Foo = packed struct { |
| 219 | a: f16 = 0, |
| 220 | b: f32 = 1, |
| 221 | c: f64 = 2, |
| 222 | d: f128 = 3, |
| 223 | }; |
| 224 | |
| 225 | const Foo2 = packed struct { |
| 226 | a: f16 = 0, |
| 227 | b: f32 = 1, |
| 228 | c: f64 = 2, |
| 229 | d: f128 = 3, |
| 230 | }; |
| 231 | |
| 232 | const S = struct { |
| 233 | fn doTheTest() !void { |
| 234 | var foo = Foo{}; |
| 235 | _ = &foo; |
| 236 | const v: Foo2 = @bitCast(foo); |
| 237 | try expect(v.a == foo.a); |
| 238 | try expect(v.b == foo.b); |
| 239 | try expect(v.c == foo.c); |
| 240 | try expect(v.d == foo.d); |
| 241 | } |
| 242 | }; |
| 243 | try S.doTheTest(); |
| 244 | try comptime S.doTheTest(); |
| 245 | } |
| 246 | |
| 247 | test "comptime @bitCast packed struct to int and back" { |
| 248 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 249 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 250 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 251 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 252 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 253 | |
| 254 | const S = packed struct { |
| 255 | void: void = {}, |
| 256 | uint: u8 = 13, |
| 257 | uint_bit_aligned: u3 = 2, |
| 258 | iint_pos: i4 = 1, |
| 259 | iint_neg4: i3 = -4, |
| 260 | iint_neg2: i3 = -2, |
| 261 | float: f32 = 3.14, |
| 262 | @"enum": enum(u2) { A, B = 1, C, D } = .B, |
| 263 | }; |
| 264 | const Int = @typeInfo(S).@"struct".backing_integer.?; |
| 265 | |
| 266 | // S -> Int |
| 267 | var s: S = .{}; |
| 268 | _ = &s; |
| 269 | try expectEqual(@as(Int, @bitCast(s)), comptime @as(Int, @bitCast(S{}))); |
| 270 | |
| 271 | // Int -> S |
| 272 | var i: Int = 0; |
| 273 | _ = &i; |
| 274 | const rt_cast = @as(S, @bitCast(i)); |
| 275 | const ct_cast = comptime @as(S, @bitCast(@as(Int, 0))); |
| 276 | inline for (@typeInfo(S).@"struct".field_names) |field_name| { |
| 277 | try expectEqual(@field(rt_cast, field_name), @field(ct_cast, field_name)); |
| 278 | } |
| 279 | } |
| 280 | |
| 281 | test "bitcast vector to integer and back" { |
| 282 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 283 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 284 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 285 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 286 | |
| 287 | var vec: @Vector(16, bool) = @splat(true); |
| 288 | vec[1] = false; |
| 289 | |
| 290 | const int: u16 = @bitCast(vec); |
| 291 | try expect(int == 0b1111_1111_1111_1101); |
| 292 | |
| 293 | const vec_again: @Vector(16, bool) = @bitCast(int); |
| 294 | try expect(vec_again[0]); |
| 295 | try expect(!vec_again[1]); |
| 296 | try expect(vec_again[2]); |
| 297 | try expect(vec_again[3]); |
| 298 | try expect(vec_again[4]); |
| 299 | try expect(vec_again[5]); |
| 300 | try expect(vec_again[6]); |
| 301 | try expect(vec_again[7]); |
| 302 | try expect(vec_again[8]); |
| 303 | try expect(vec_again[9]); |
| 304 | try expect(vec_again[10]); |
| 305 | try expect(vec_again[11]); |
| 306 | try expect(vec_again[12]); |
| 307 | try expect(vec_again[13]); |
| 308 | try expect(vec_again[14]); |
| 309 | try expect(vec_again[15]); |
| 310 | |
| 311 | const int_again: u16 = @bitCast(vec_again); |
| 312 | try expect(int_again == 0b1111_1111_1111_1101); |
| 313 | } |
| 314 | |
| 315 | fn bitCastWrapper16(x: f16) u16 { |
| 316 | return @as(u16, @bitCast(x)); |
| 317 | } |
| 318 | fn bitCastWrapper32(x: f32) u32 { |
| 319 | return @as(u32, @bitCast(x)); |
| 320 | } |
| 321 | fn bitCastWrapper64(x: f64) u64 { |
| 322 | return @as(u64, @bitCast(x)); |
| 323 | } |
| 324 | fn bitCastWrapper128(x: f128) u128 { |
| 325 | return @as(u128, @bitCast(x)); |
| 326 | } |
| 327 | test "bitcast nan float does not modify signaling bit" { |
| 328 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 329 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 330 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 331 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; |
| 332 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 333 | |
| 334 | const snan_u16: u16 = 0x7D00; |
| 335 | const snan_u32: u32 = 0x7FA00000; |
| 336 | const snan_u64: u64 = 0x7FF4000000000000; |
| 337 | const snan_u128: u128 = 0x7FFF4000000000000000000000000000; |
| 338 | |
| 339 | // 16 bit |
| 340 | const snan_f16_const = math.snan(f16); |
| 341 | try expectEqual(snan_u16, @as(u16, @bitCast(snan_f16_const))); |
| 342 | try expectEqual(snan_u16, bitCastWrapper16(snan_f16_const)); |
| 343 | |
| 344 | var snan_f16_var = math.snan(f16); |
| 345 | _ = &snan_f16_var; |
| 346 | try expectEqual(snan_u16, @as(u16, @bitCast(snan_f16_var))); |
| 347 | try expectEqual(snan_u16, bitCastWrapper16(snan_f16_var)); |
| 348 | |
| 349 | // 32 bit |
| 350 | const snan_f32_const = math.snan(f32); |
| 351 | try expectEqual(snan_u32, @as(u32, @bitCast(snan_f32_const))); |
| 352 | try expectEqual(snan_u32, bitCastWrapper32(snan_f32_const)); |
| 353 | |
| 354 | var snan_f32_var = math.snan(f32); |
| 355 | _ = &snan_f32_var; |
| 356 | try expectEqual(snan_u32, @as(u32, @bitCast(snan_f32_var))); |
| 357 | try expectEqual(snan_u32, bitCastWrapper32(snan_f32_var)); |
| 358 | |
| 359 | // 64 bit |
| 360 | const snan_f64_const = math.snan(f64); |
| 361 | try expectEqual(snan_u64, @as(u64, @bitCast(snan_f64_const))); |
| 362 | try expectEqual(snan_u64, bitCastWrapper64(snan_f64_const)); |
| 363 | |
| 364 | var snan_f64_var = math.snan(f64); |
| 365 | _ = &snan_f64_var; |
| 366 | try expectEqual(snan_u64, @as(u64, @bitCast(snan_f64_var))); |
| 367 | try expectEqual(snan_u64, bitCastWrapper64(snan_f64_var)); |
| 368 | |
| 369 | // 128 bit |
| 370 | const snan_f128_const = math.snan(f128); |
| 371 | try expectEqual(snan_u128, @as(u128, @bitCast(snan_f128_const))); |
| 372 | try expectEqual(snan_u128, bitCastWrapper128(snan_f128_const)); |
| 373 | |
| 374 | var snan_f128_var = math.snan(f128); |
| 375 | _ = &snan_f128_var; |
| 376 | try expectEqual(snan_u128, @as(u128, @bitCast(snan_f128_var))); |
| 377 | try expectEqual(snan_u128, bitCastWrapper128(snan_f128_var)); |
| 378 | } |
| 379 | |
| 380 | test "@bitCast of packed struct of bools all true" { |
| 381 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 382 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 383 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO |
| 384 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 385 | |
| 386 | const P = packed struct { |
| 387 | b0: bool, |
| 388 | b1: bool, |
| 389 | b2: bool, |
| 390 | b3: bool, |
| 391 | }; |
| 392 | var p = std.mem.zeroes(P); |
| 393 | p.b0 = true; |
| 394 | p.b1 = true; |
| 395 | p.b2 = true; |
| 396 | p.b3 = true; |
| 397 | try expect(@as(u8, @as(u4, @bitCast(p))) == 15); |
| 398 | } |
| 399 | |
| 400 | test "@bitCast of packed struct of bools all false" { |
| 401 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 402 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 403 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO |
| 404 | |
| 405 | const P = packed struct { |
| 406 | b0: bool, |
| 407 | b1: bool, |
| 408 | b2: bool, |
| 409 | b3: bool, |
| 410 | }; |
| 411 | var p = std.mem.zeroes(P); |
| 412 | p.b0 = false; |
| 413 | p.b1 = false; |
| 414 | p.b2 = false; |
| 415 | p.b3 = false; |
| 416 | try expect(@as(u8, @as(u4, @bitCast(p))) == 0); |
| 417 | } |
| 418 | |
| 419 | test "@bitCast of packed struct with void field to integer" { |
| 420 | const S = packed struct(u8) { |
| 421 | v: void, |
| 422 | x: u8, |
| 423 | |
| 424 | fn doTheTest(x: u8) !void { |
| 425 | // Intentionally using `@as` to avoid RLS which masks the bug |
| 426 | const foo = @as(@This(), .{ .v = {}, .x = x }); |
| 427 | const as_int: u8 = @bitCast(foo); |
| 428 | try expect(as_int == x); |
| 429 | } |
| 430 | }; |
| 431 | try S.doTheTest(123); |
| 432 | try comptime S.doTheTest(123); |
| 433 | } |
| 434 | |
| 435 | test "@bitCast of packed struct with void field and multiple integers" { |
| 436 | const S = packed struct { |
| 437 | x: u8, |
| 438 | v: void, |
| 439 | y: u8, |
| 440 | |
| 441 | fn doTheTest(x: u8, y: u8) !void { |
| 442 | const foo = @as(@This(), .{ .x = x, .v = {}, .y = y }); |
| 443 | const as_int: u16 = @bitCast(foo); |
| 444 | try expect(as_int == @as(u16, y) << 8 | x); |
| 445 | } |
| 446 | }; |
| 447 | try S.doTheTest(123, 45); |
| 448 | try comptime S.doTheTest(123, 45); |
| 449 | } |
| 450 | |
| 451 | test "@bitCast vector to array with different element size" { |
| 452 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 453 | |
| 454 | const static = struct { |
| 455 | fn doTheTest(v: @Vector(4, u5)) !void { |
| 456 | const result: [5]u4 = @bitCast(v); |
| 457 | // See the definition of `v` in the test proper for these values. |
| 458 | try expect(result[0] == 0b0010); |
| 459 | try expect(result[1] == 0b1110); |
| 460 | try expect(result[2] == 0b0101); |
| 461 | try expect(result[3] == 0b0110); |
| 462 | try expect(result[4] == 0b0000); |
| 463 | } |
| 464 | }; |
| 465 | // The strange digit groupings here are to indicate how this maps to `expected` above. |
| 466 | const v: @Vector(4, u5) = .{ |
| 467 | 0b0_0010, |
| 468 | 0b01_111, |
| 469 | 0b110_01, |
| 470 | 0b0000_0, |
| 471 | }; |
| 472 | try static.doTheTest(v); |
| 473 | try comptime static.doTheTest(v); |
| 474 | } |
| 475 | |
| 476 | test "@bitCast packed struct to array of bits" { |
| 477 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 478 | |
| 479 | const S = packed struct(u16) { |
| 480 | foo: u5, |
| 481 | bar: i7, |
| 482 | baz: u3, |
| 483 | qux: bool, |
| 484 | fn doTheTest(val: @This(), comptime Bits: type) !void { |
| 485 | const bits: Bits = @bitCast(val); |
| 486 | |
| 487 | // foo |
| 488 | try expect(bits[0] == 1); |
| 489 | try expect(bits[1] == 0); |
| 490 | try expect(bits[2] == 0); |
| 491 | try expect(bits[3] == 1); |
| 492 | try expect(bits[4] == 0); |
| 493 | // bar |
| 494 | try expect(bits[5] == 0); |
| 495 | try expect(bits[6] == 1); |
| 496 | try expect(bits[7] == 1); |
| 497 | try expect(bits[8] == 1); |
| 498 | try expect(bits[9] == 1); |
| 499 | try expect(bits[10] == 1); |
| 500 | try expect(bits[11] == 1); |
| 501 | // baz |
| 502 | try expect(bits[12] == 0); |
| 503 | try expect(bits[13] == 1); |
| 504 | try expect(bits[14] == 0); |
| 505 | // qux |
| 506 | try expect(bits[15] == 1); |
| 507 | } |
| 508 | }; |
| 509 | |
| 510 | const val: S = .{ |
| 511 | .foo = 0b01001, |
| 512 | .bar = -2, |
| 513 | .baz = 0b010, |
| 514 | .qux = true, |
| 515 | }; |
| 516 | |
| 517 | try val.doTheTest(@Vector(16, u1)); |
| 518 | try val.doTheTest([16]u1); |
| 519 | |
| 520 | try comptime val.doTheTest(@Vector(16, u1)); |
| 521 | try comptime val.doTheTest([16]u1); |
| 522 | } |
| 523 | |
| 524 | test "@bitCast nested arrays of vectors" { |
| 525 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 526 | |
| 527 | const Src = [2][2]@Vector(4, u5); |
| 528 | const Dest = [5]@Vector(2, u8); |
| 529 | |
| 530 | // The strange digit groupings here are to indicate how this maps to the output. |
| 531 | const src: Src = .{ .{ |
| 532 | .{ 0b00011, 0b00_100, 0b11100, 0b0010_1 }, |
| 533 | .{ 0b1_0110, 0b11011, 0b101_10, 0b10101 }, |
| 534 | }, .{ |
| 535 | .{ 0b10101, 0b00_001, 0b01011, 0b0001_0 }, |
| 536 | .{ 0b0_0001, 0b01111, 0b111_10, 0b00001 }, |
| 537 | } }; |
| 538 | |
| 539 | const expected: Dest = .{ |
| 540 | .{ 0b10000011, 0b11110000 }, |
| 541 | .{ 0b01100010, 0b10110111 }, |
| 542 | .{ 0b10101101, 0b00110101 }, |
| 543 | .{ 0b00101100, 0b00010001 }, |
| 544 | .{ 0b10011110, 0b00001111 }, |
| 545 | }; |
| 546 | |
| 547 | const static = struct { |
| 548 | fn doTheTest(src_arg: Src) !void { |
| 549 | const actual: Dest = @bitCast(src_arg); |
| 550 | for (actual, expected) |actual_vec, expected_vec| { |
| 551 | try expect(actual_vec[0] == expected_vec[0]); |
| 552 | try expect(actual_vec[1] == expected_vec[1]); |
| 553 | } |
| 554 | } |
| 555 | }; |
| 556 | |
| 557 | try static.doTheTest(src); |
| 558 | try comptime static.doTheTest(src); |
| 559 | } |
| 560 | |
| 561 | test "@bitCast nested arrays of bool to scalar" { |
| 562 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 563 | |
| 564 | const static = struct { |
| 565 | fn doTheTest(src: [4][4]bool) !void { |
| 566 | const result: u16 = @bitCast(src); |
| 567 | try expect(result == 0b1100_0101_1010_0011); |
| 568 | } |
| 569 | }; |
| 570 | const src: [4][4]bool = .{ |
| 571 | .{ true, true, false, false }, // 0b0011 |
| 572 | .{ false, true, false, true }, // 0b1010 |
| 573 | .{ true, false, true, false }, // 0b0101 |
| 574 | .{ false, false, true, true }, // 0b1100 |
| 575 | }; |
| 576 | try static.doTheTest(src); |
| 577 | try comptime static.doTheTest(src); |
| 578 | } |
| 579 | |
| 580 | test "@bitCast deeply nested arrays to scalar" { |
| 581 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 582 | |
| 583 | const static = struct { |
| 584 | fn doTheTest(src: [2][1][3][5]u4) !void { |
| 585 | const signed: i120 = @bitCast(src); |
| 586 | try expect(signed < 0); // top nibble is 0x8 so sign bit is 1 |
| 587 | const unsigned: u120 = @bitCast(src); |
| 588 | try expect(unsigned == 0x8873B_5BF6F_F4020_0E7AC_1EFED_40F51); |
| 589 | try expect(@as(i120, @bitCast(unsigned)) == signed); |
| 590 | try expect(@as(u120, @bitCast(signed)) == unsigned); |
| 591 | } |
| 592 | }; |
| 593 | const src: [2][1][3][5]u4 = .{ .{.{ |
| 594 | .{ 0x1, 0x5, 0xF, 0x0, 0x4 }, |
| 595 | .{ 0xD, 0xE, 0xF, 0xE, 0x1 }, |
| 596 | .{ 0xC, 0xA, 0x7, 0xE, 0x0 }, |
| 597 | }}, .{.{ |
| 598 | .{ 0x0, 0x2, 0x0, 0x4, 0xF }, |
| 599 | .{ 0xF, 0x6, 0xF, 0xB, 0x5 }, |
| 600 | .{ 0xB, 0x3, 0x7, 0x8, 0x8 }, |
| 601 | }} }; |
| 602 | try static.doTheTest(src); |
| 603 | try comptime static.doTheTest(src); |
| 604 | } |