authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-24 19:42:06-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-09-24 19:42:06-07:00
logeb072fa52846c6583b856c8c88d50d65f46b3667
treef1c1f213685f476200562bcc870bc774bd81fa2f
parentdf5f0517b33b5f7bc2a508cf6a0ee62246f02d21
parentc08c0fc6eddf601785abfbc5e5a9ab5c89d7cfbf
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17256 from ziglang/packed-bit-offsets

compiler: packed structs cache bit offsets

4 files changed, 17 insertions(+), 19 deletions(-)

src/InternPool.zig+1-1
......@@ -4195,7 +4195,7 @@ fn extraPackedStructType(ip: *const InternPool, extra_index: u32, inits: bool) K
41954195 .len = fields_len,
41964196 },
41974197 .field_inits = if (inits) .{
4198 .start = type_struct_packed.end + fields_len + fields_len,
4198 .start = type_struct_packed.end + fields_len * 2,
41994199 .len = fields_len,
42004200 } else .{
42014201 .start = 0,
src/Module.zig+4-4
......@@ -6650,10 +6650,10 @@ pub fn structFieldAlignmentExtern(mod: *Module, field_ty: Type) Alignment {
66506650 return ty_abi_align;
66516651}
66526652
6653/// TODO: avoid linear search by storing these in trailing data of packed struct types
6654/// then packedStructFieldByteOffset can be expressed in terms of bits / 8, fixing
6655/// that one too.
6656/// https://github.com/ziglang/zig/issues/17178
6653/// https://github.com/ziglang/zig/issues/17178 explored storing these bit offsets
6654/// into the packed struct InternPool data rather than computing this on the
6655/// fly, however it was found to perform worse when measured on real world
6656/// projects.
66576657pub fn structPackedFieldBitOffset(
66586658 mod: *Module,
66596659 struct_type: InternPool.Key.StructType,
src/Sema.zig+3-2
......@@ -21377,8 +21377,9 @@ fn reifyStruct(
2137721377 }
2137821378
2137921379 var fields_bit_sum: u64 = 0;
21380 for (struct_type.field_types.get(ip)) |field_ty| {
21381 fields_bit_sum += field_ty.toType().bitSize(mod);
21380 for (0..struct_type.field_types.len) |i| {
21381 const field_ty = struct_type.field_types.get(ip)[i].toType();
21382 fields_bit_sum += field_ty.bitSize(mod);
2138221383 }
2138321384
2138421385 if (backing_int_val.optionalValue(mod)) |backing_int_ty_val| {
src/type.zig+9-12
......@@ -3021,27 +3021,24 @@ pub const Type = struct {
30213021 };
30223022 }
30233023
3024 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 {
3024 pub fn packedStructFieldBitOffset(ty: Type, field_index: usize, mod: *Module) u32 {
30253025 const ip = &mod.intern_pool;
30263026 const struct_type = ip.indexToKey(ty.toIntern()).struct_type;
30273027 assert(struct_type.layout == .Packed);
30283028 comptime assert(Type.packed_struct_layout_version == 2);
30293029
3030 var bit_offset: u16 = undefined;
3031 var elem_size_bits: u16 = undefined;
3032 var running_bits: u16 = 0;
3030 var running_bits: u32 = 0;
30333031 for (struct_type.field_types.get(ip), 0..) |field_ty, i| {
3032 if (i == field_index) break;
30343033 if (!field_ty.toType().hasRuntimeBits(mod)) continue;
3035
3036 const field_bits: u16 = @intCast(field_ty.toType().bitSize(mod));
3037 if (i == field_index) {
3038 bit_offset = running_bits;
3039 elem_size_bits = field_bits;
3040 }
3034 const field_bits: u32 = @intCast(field_ty.toType().bitSize(mod));
30413035 running_bits += field_bits;
30423036 }
3043 const byte_offset = bit_offset / 8;
3044 return byte_offset;
3037 return running_bits;
3038 }
3039
3040 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 {
3041 return packedStructFieldBitOffset(ty, field_index, mod) / 8;
30453042 }
30463043
30473044 pub const FieldOffset = struct {