Skip to content

Commit

Permalink
llvm debug info: represent packed structs as structs instead of integers
Browse files Browse the repository at this point in the history
Fixes an LLVM assertion failure on trying to nest a function into that
int; also just gets us a plain better debugging experience for packed
structs.
  • Loading branch information
tau-dev committed Jul 21, 2024
1 parent 324cb57 commit f65341e
Showing 1 changed file with 63 additions and 29 deletions.
92 changes: 63 additions & 29 deletions src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand All @@ -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)
Expand All @@ -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,
));
}

Expand Down Expand Up @@ -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);
Expand All @@ -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,
));
}

Expand Down

0 comments on commit f65341e

Please sign in to comment.