| author | |
| committer | |
| log | 405705cb76914072b9a91ac29f7cf0bf67b255f4 |
| tree | 2f2928e3a6c42626cf1464a2f52dba546ea6e50d |
| parent | 62d178e91af57c19d0ac000fe6930039a23e53a3 |
4 files changed, 38 insertions(+), 8 deletions(-)
src/arch/wasm/CodeGen.zig+2-1| ... | ... | @@ -3828,7 +3828,8 @@ fn structFieldPtr( |
| 3828 | 3828 | if (result_ty.ptrInfo(mod).packed_offset.host_size != 0) { |
| 3829 | 3829 | break :offset @as(u32, 0); |
| 3830 | 3830 | } |
| 3831 | break :offset struct_ty.packedStructFieldByteOffset(index, mod) + @divExact(struct_ptr_ty_info.packed_offset.bit_offset, 8); | |
| 3831 | const struct_type = mod.typeToStruct(struct_ty).?; | |
| 3832 | break :offset @divExact(mod.structPackedFieldBitOffset(struct_type, index) + struct_ptr_ty_info.packed_offset.bit_offset, 8); | |
| 3832 | 3833 | }, |
| 3833 | 3834 | .Union => 0, |
| 3834 | 3835 | else => unreachable, |
src/codegen/llvm.zig+2-1| ... | ... | @@ -10140,6 +10140,7 @@ pub const FuncGen = struct { |
| 10140 | 10140 | const result_ty = self.typeOfIndex(inst); |
| 10141 | 10141 | const result_ty_info = result_ty.ptrInfo(mod); |
| 10142 | 10142 | const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(mod); |
| 10143 | const struct_type = mod.typeToStruct(struct_ty).?; | |
| 10143 | 10144 | |
| 10144 | 10145 | if (result_ty_info.packed_offset.host_size != 0) { |
| 10145 | 10146 | // From LLVM's perspective, a pointer to a packed struct and a pointer |
| ... | ... | @@ -10151,7 +10152,7 @@ pub const FuncGen = struct { |
| 10151 | 10152 | |
| 10152 | 10153 | // We have a pointer to a packed struct field that happens to be byte-aligned. |
| 10153 | 10154 | // Offset our operand pointer by the correct number of bytes. |
| 10154 | const byte_offset = struct_ty.packedStructFieldByteOffset(field_index, mod) + @divExact(struct_ptr_ty_info.packed_offset.bit_offset, 8); | |
| 10155 | const byte_offset = @divExact(mod.structPackedFieldBitOffset(struct_type, field_index) + struct_ptr_ty_info.packed_offset.bit_offset, 8); | |
| 10155 | 10156 | if (byte_offset == 0) return struct_ptr; |
| 10156 | 10157 | const usize_ty = try o.lowerType(Type.usize); |
| 10157 | 10158 | const llvm_index = try o.builder.intValue(usize_ty, byte_offset); |
src/type.zig-6| ... | ... | @@ -3028,12 +3028,6 @@ pub const Type = struct { |
| 3028 | 3028 | }; |
| 3029 | 3029 | } |
| 3030 | 3030 | |
| 3031 | pub fn packedStructFieldByteOffset(ty: Type, field_index: u32, mod: *Module) u32 { | |
| 3032 | const ip = &mod.intern_pool; | |
| 3033 | const struct_type = ip.indexToKey(ty.toIntern()).struct_type; | |
| 3034 | return @divExact(mod.structPackedFieldBitOffset(struct_type, field_index), 8); | |
| 3035 | } | |
| 3036 | ||
| 3037 | 3031 | pub const FieldOffset = struct { |
| 3038 | 3032 | field: usize, |
| 3039 | 3033 | offset: u64, |
test/behavior/packed-struct.zig+34| ... | ... | @@ -622,6 +622,8 @@ test "@intFromPtr on a packed struct field unaligned and nested" { |
| 622 | 622 | } |
| 623 | 623 | |
| 624 | 624 | test "packed struct fields modification" { |
| 625 | // Originally reported at https://github.com/ziglang/zig/issues/16615 | |
| 626 | ||
| 625 | 627 | const Small = packed struct { |
| 626 | 628 | val: u8 = 0, |
| 627 | 629 | lo: u4 = 0, |
| ... | ... | @@ -989,6 +991,7 @@ test "bitcast back and forth" { |
| 989 | 991 | } |
| 990 | 992 | |
| 991 | 993 | test "field access of packed struct smaller than its abi size inside struct initialized with rls" { |
| 994 | // Originally reported at https://github.com/ziglang/zig/issues/14200 | |
| 992 | 995 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .arm) return error.SkipZigTest; |
| 993 | 996 | const S = struct { |
| 994 | 997 | ps: packed struct { x: i2, y: i2 }, |
| ... | ... | @@ -1003,3 +1006,34 @@ test "field access of packed struct smaller than its abi size inside struct init |
| 1003 | 1006 | try expect(@as(i2, 0) == s.ps.x); |
| 1004 | 1007 | try expect(@as(i2, 1) == s.ps.y); |
| 1005 | 1008 | } |
| 1009 | ||
| 1010 | test "modify nested packed struct aligned field" { | |
| 1011 | // Originally reported at https://github.com/ziglang/zig/issues/14632 | |
| 1012 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 1013 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 1014 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; | |
| 1015 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 1016 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 1017 | ||
| 1018 | const Options = packed struct { | |
| 1019 | foo: bool = false, | |
| 1020 | bar: bool = false, | |
| 1021 | pretty_print: packed struct { | |
| 1022 | enabled: bool = false, | |
| 1023 | num_spaces: u4 = 4, | |
| 1024 | space_char: enum { space, tab } = .space, | |
| 1025 | indent: u8 = 0, | |
| 1026 | } = .{}, | |
| 1027 | baz: bool = false, | |
| 1028 | }; | |
| 1029 | ||
| 1030 | var opts = Options{}; | |
| 1031 | opts.pretty_print.indent += 1; | |
| 1032 | try std.testing.expectEqual(@as(u17, 0b00000000100100000), @bitCast(opts)); | |
| 1033 | try std.testing.expect(!opts.foo); | |
| 1034 | try std.testing.expect(!opts.bar); | |
| 1035 | try std.testing.expect(!opts.pretty_print.enabled); | |
| 1036 | try std.testing.expectEqual(@as(u4, 4), opts.pretty_print.num_spaces); | |
| 1037 | try std.testing.expectEqual(@as(u8, 1), opts.pretty_print.indent); | |
| 1038 | try std.testing.expect(!opts.baz); | |
| 1039 | } |