| 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,7 +3828,8 @@ fn structFieldPtr( |
| 3828 | if (result_ty.ptrInfo(mod).packed_offset.host_size != 0) { | 3828 | if (result_ty.ptrInfo(mod).packed_offset.host_size != 0) { |
| 3829 | break :offset @as(u32, 0); | 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 | .Union => 0, | 3834 | .Union => 0, |
| 3834 | else => unreachable, | 3835 | else => unreachable, |
src/codegen/llvm.zig+2-1| ... | @@ -10140,6 +10140,7 @@ pub const FuncGen = struct { | ... | @@ -10140,6 +10140,7 @@ pub const FuncGen = struct { |
| 10140 | const result_ty = self.typeOfIndex(inst); | 10140 | const result_ty = self.typeOfIndex(inst); |
| 10141 | const result_ty_info = result_ty.ptrInfo(mod); | 10141 | const result_ty_info = result_ty.ptrInfo(mod); |
| 10142 | const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(mod); | 10142 | const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(mod); |
| 10143 | const struct_type = mod.typeToStruct(struct_ty).?; | ||
| 10143 | 10144 | ||
| 10144 | if (result_ty_info.packed_offset.host_size != 0) { | 10145 | if (result_ty_info.packed_offset.host_size != 0) { |
| 10145 | // From LLVM's perspective, a pointer to a packed struct and a pointer | 10146 | // From LLVM's perspective, a pointer to a packed struct and a pointer |
| ... | @@ -10151,7 +10152,7 @@ pub const FuncGen = struct { | ... | @@ -10151,7 +10152,7 @@ pub const FuncGen = struct { |
| 10151 | 10152 | ||
| 10152 | // We have a pointer to a packed struct field that happens to be byte-aligned. | 10153 | // We have a pointer to a packed struct field that happens to be byte-aligned. |
| 10153 | // Offset our operand pointer by the correct number of bytes. | 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 | if (byte_offset == 0) return struct_ptr; | 10156 | if (byte_offset == 0) return struct_ptr; |
| 10156 | const usize_ty = try o.lowerType(Type.usize); | 10157 | const usize_ty = try o.lowerType(Type.usize); |
| 10157 | const llvm_index = try o.builder.intValue(usize_ty, byte_offset); | 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,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 | pub const FieldOffset = struct { | 3031 | pub const FieldOffset = struct { |
| 3038 | field: usize, | 3032 | field: usize, |
| 3039 | offset: u64, | 3033 | offset: u64, |
test/behavior/packed-struct.zig+34| ... | @@ -622,6 +622,8 @@ test "@intFromPtr on a packed struct field unaligned and nested" { | ... | @@ -622,6 +622,8 @@ test "@intFromPtr on a packed struct field unaligned and nested" { |
| 622 | } | 622 | } |
| 623 | 623 | ||
| 624 | test "packed struct fields modification" { | 624 | test "packed struct fields modification" { |
| 625 | // Originally reported at https://github.com/ziglang/zig/issues/16615 | ||
| 626 | |||
| 625 | const Small = packed struct { | 627 | const Small = packed struct { |
| 626 | val: u8 = 0, | 628 | val: u8 = 0, |
| 627 | lo: u4 = 0, | 629 | lo: u4 = 0, |
| ... | @@ -989,6 +991,7 @@ test "bitcast back and forth" { | ... | @@ -989,6 +991,7 @@ test "bitcast back and forth" { |
| 989 | } | 991 | } |
| 990 | 992 | ||
| 991 | test "field access of packed struct smaller than its abi size inside struct initialized with rls" { | 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 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .arm) return error.SkipZigTest; | 995 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .arm) return error.SkipZigTest; |
| 993 | const S = struct { | 996 | const S = struct { |
| 994 | ps: packed struct { x: i2, y: i2 }, | 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,3 +1006,34 @@ test "field access of packed struct smaller than its abi size inside struct init |
| 1003 | try expect(@as(i2, 0) == s.ps.x); | 1006 | try expect(@as(i2, 0) == s.ps.x); |
| 1004 | try expect(@as(i2, 1) == s.ps.y); | 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 | } |