Commit 19e343b8d4

Igor Stojkovic <stojkovic.igor+git@gmail.com>
2022-04-09 12:43:30
stage1: Additional fix for packed structs
1 parent 109e730
Changed files (2)
src
stage1
test
src/stage1/ir.cpp
@@ -15484,6 +15484,9 @@ static Stage1AirInst *ir_analyze_struct_field_ptr(IrAnalyze *ira, Scope *scope,
         assert(struct_ptr->value->type->id == ZigTypeIdPointer);
         uint32_t ptr_bit_offset = struct_ptr->value->type->data.pointer.bit_offset_in_host;
         uint32_t ptr_host_int_bytes = struct_ptr->value->type->data.pointer.host_int_bytes;
+        if (ptr_host_int_bytes > 0) {
+            ptr_bit_offset += field->offset * 8;
+        }
         uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
             get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes;
         ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
test/behavior/packed-struct.zig
@@ -322,3 +322,33 @@ test "nested packed structs" {
     try expectEqual(9, @offsetOf(S6, "c"));
     try expectEqual(72, @bitOffsetOf(S6, "c"));
 }
+
+test "regular in irregular packed struct" {
+    if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+
+    const Irregular = packed struct {
+        bar: Regular = Regular{},
+
+        // This field forces the regular packed struct to be a part of single u48
+        // and thus it all gets represented as an array of 6 bytes in LLVM
+        _: u24 = 0,
+
+        // This struct on its own can represent its fields directly in LLVM
+        // with no need to use array of bytes as underlaying representation.
+        pub const Regular = packed struct { a: u16 = 0, b: u8 = 0 };
+    };
+
+    var foo = Irregular{};
+    foo.bar.a = 235;
+    foo.bar.b = 42;
+
+    try expectEqual(@as(u16, 235), foo.bar.a);
+    try expectEqual(@as(u8, 42), foo.bar.b);
+}