From 109e730c8ccdfe144f568f232578ab600ef4f33c Mon Sep 17 00:00:00 2001 From: Igor Stojkovic Date: Wed, 23 Mar 2022 20:29:53 +0100 Subject: stage1: Fix packed structs (#2627, #10104) Fixed formatting in packed-struct-zig Skipped packed_structs tests in stage2 simplified packed struct tests --- src/stage1/ir.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/stage1/ir.cpp') diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 11f47c592b..22ed5befe1 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -15490,6 +15490,13 @@ static Stage1AirInst *ir_analyze_struct_field_ptr(IrAnalyze *ira, Scope *scope, is_const, is_volatile, PtrLenSingle, field->align, (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), (uint32_t)host_int_bytes_for_result_type, false); + + if (field == struct_type->data.structure.misaligned_field) { + // If field is the last single misaligned field it will be represented as array + // of bytes in LLVM but get_pointer_to_type_extra will set its host_int_bytes to 0. + // We need it not to be 0 so later stage would generate proper bit casting code. + ptr_type->data.pointer.host_int_bytes = host_int_bytes_for_result_type; + } } if (instr_is_comptime(struct_ptr)) { ZigValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad); -- cgit v1.2.3 From 19e343b8d46725265eb72796bec506050e182900 Mon Sep 17 00:00:00 2001 From: Igor Stojkovic Date: Sat, 9 Apr 2022 12:43:30 +0200 Subject: stage1: Additional fix for packed structs --- src/stage1/ir.cpp | 3 +++ test/behavior/packed-struct.zig | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) (limited to 'src/stage1/ir.cpp') diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 22ed5befe1..df3439d25c 100644 --- a/src/stage1/ir.cpp +++ b/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, diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index 86ef9e3c1e..44ac21aea9 100644 --- a/test/behavior/packed-struct.zig +++ b/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); +} -- cgit v1.2.3