Commit 07630eb696

Matt Knight <mattnite@protonmail.com>
2023-02-18 20:10:27
Value: implement writeToMemory for packed unions
1 parent c993af6
Changed files (2)
src/value.zig
@@ -1340,6 +1340,14 @@ pub const Value = extern union {
                 const int = mod.global_error_set.get(val.castTag(.@"error").?.data.name).?;
                 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), endian);
             },
+            .Union => switch (ty.containerLayout()) {
+                .Auto => unreachable,
+                .Extern => @panic("TODO implement writeToMemory for extern unions"),
+                .Packed => {
+                    const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;
+                    writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);
+                },
+            },
             else => @panic("TODO implement writeToMemory for more types"),
         }
     }
@@ -1430,6 +1438,17 @@ pub const Value = extern union {
                     }
                 },
             },
+            .Union => switch (ty.containerLayout()) {
+                .Auto => unreachable, // Sema is supposed to have emitted a compile error already
+                .Extern => unreachable, // Handled in non-packed writeToMemory
+                .Packed => {
+                    const field_index = ty.unionTagFieldIndex(val.unionTag(), mod);
+                    const field_type = ty.unionFields().values()[field_index.?].ty;
+                    const field_val = val.fieldValue(field_type, field_index.?);
+
+                    field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset);
+                },
+            },
             else => @panic("TODO implement writeToPackedMemory for more types"),
         }
     }
test/behavior/comptime_memory.zig
@@ -394,3 +394,21 @@ test "accessing reinterpreted memory of parent object" {
         try testing.expect(b == expected);
     }
 }
+
+test "bitcast packed union to integer" {
+    const U = packed union {
+        x: u1,
+        y: u2,
+    };
+
+    comptime {
+        const a = U{ .x = 1 };
+        const b = U{ .y = 2 };
+        const cast_a = @bitCast(u2, a);
+        const cast_b = @bitCast(u2, b);
+
+        // truncated because the upper bit is garbage memory that we don't care about
+        try testing.expectEqual(@as(u1, 1), @truncate(u1, cast_a));
+        try testing.expectEqual(@as(u2, 2), cast_b);
+    }
+}