diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index f3898247f306..ae74a3042b34 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2544,18 +2544,9 @@ pub const Object = struct { break :res debug_opaque_type; }, .Struct => res: { - if (zcu.typeToPackedStruct(ty)) |struct_type| { - const backing_int_ty = struct_type.backingIntTypeUnordered(ip); - if (backing_int_ty != .none) { - const info = Type.fromInterned(backing_int_ty).intInfo(zcu); - const builder_name = try o.builder.metadataString(name); - const debug_int_type = switch (info.signedness) { - .signed => try o.builder.debugSignedType(builder_name, ty.abiSize(pt) * 8), - .unsigned => try o.builder.debugUnsignedType(builder_name, ty.abiSize(pt) * 8), - }; - break :res debug_int_type; - } - } + const is_packed = zcu.typeToPackedStruct(ty) != null; + const packed_big_endian = is_packed and o.target.cpu.arch.endian() == .big; + const big_endian_byte_size = if (packed_big_endian) ty.abiSize(pt) else 0; switch (ip.indexToKey(ty.toIntern())) { .anon_struct_type => |tuple| { @@ -2567,10 +2558,31 @@ pub const Object = struct { for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| { if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(pt)) continue; - const field_size = Type.fromInterned(field_ty).abiSize(pt); - const field_align = Type.fromInterned(field_ty).abiAlignment(pt); - const field_offset = field_align.forward(offset); - offset = field_offset + field_size; + const field_size, const field_align, const field_offset = if (is_packed) blk: { + const byte_size = Type.fromInterned(field_ty).abiSize(pt); + const byte_alignment = Type.fromInterned(field_ty).abiAlignment(pt); + const byte_offset = byte_alignment.forward(offset); + offset = byte_offset + byte_size; + break :blk .{ + byte_size * 8, + (byte_alignment.toByteUnits() orelse 0) * 8, + byte_offset * 8, + }; + } else blk: { + const bit_size = Type.fromInterned(field_ty).bitSize(pt); + + const bit_offset = if (packed_big_endian) + (offset % 8) + 8 * (big_endian_byte_size - 1 - (offset / 8)) + else + offset; + + offset += bit_size; + break :blk .{ + bit_size, + 1, + bit_offset, + }; + }; const field_name = if (tuple.names.len != 0) tuple.names.get(ip)[i].toSlice(ip) @@ -2584,9 +2596,9 @@ pub const Object = struct { fwd_ref, 0, try o.lowerDebugType(Type.fromInterned(field_ty), required_by_runtime), - field_size * 8, - (field_align.toByteUnits() orelse 0) * 8, - field_offset * 8, + field_size, + field_align, + field_offset, )); } @@ -2619,17 +2631,39 @@ pub const Object = struct { try fields.ensureUnusedCapacity(gpa, struct_type.field_types.len); comptime assert(struct_layout_version == 2); + var offset: u64 = 0; + var it = struct_type.iterateRuntimeOrder(ip); while (it.next()) |field_index| { const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); if (!field_ty.hasRuntimeBitsIgnoreComptime(pt)) continue; - const field_size = field_ty.abiSize(pt); - const field_align = pt.structFieldAlignment( - struct_type.fieldAlign(ip, field_index), - field_ty, - struct_type.layout, - ); - const field_offset = ty.structFieldOffset(field_index, pt); + + const field_size, const field_align, const field_offset = if (is_packed) blk: { + const byte_alignment = pt.structFieldAlignment( + struct_type.fieldAlign(ip, field_index), + field_ty, + struct_type.layout, + ); + break :blk .{ + field_ty.abiSize(pt) * 8, + (byte_alignment.toByteUnits() orelse 0) * 8, + ty.structFieldOffset(field_index, pt) * 8, + }; + } else blk: { + const bit_size = field_ty.bitSize(pt); + + const bit_offset = if (packed_big_endian) + (offset % 8) + 8 * (big_endian_byte_size - 1 - (offset / 8)) + else + offset; + + offset += bit_size; + break :blk .{ + bit_size, + 1, + bit_offset, + }; + }; const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse try ip.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls); @@ -2640,9 +2674,9 @@ pub const Object = struct { fwd_ref, 0, // Line try o.lowerDebugType(field_ty, required_by_runtime), - field_size * 8, - (field_align.toByteUnits() orelse 0) * 8, - field_offset * 8, + field_size, + field_align, + field_offset, )); }