diff --git a/src/InternPool.zig b/src/InternPool.zig index eef46c1917..141e48972c 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -527,6 +527,11 @@ pub const Key = union(enum) { return false; } + pub fn clearLayoutWip(s: @This(), ip: *InternPool) void { + if (s.layout == .Packed) return; + s.flagsPtr(ip).layout_wip = false; + } + pub fn setFullyResolved(s: @This(), ip: *InternPool) bool { if (s.layout == .Packed) return true; const flags_ptr = s.flagsPtr(ip); @@ -612,6 +617,7 @@ pub const Key = union(enum) { }; /// Iterates over non-comptime fields in the order they are laid out in memory at runtime. + /// May or may not include zero-bit fields. /// Asserts the struct is not packed. pub fn iterateRuntimeOrder(s: @This(), ip: *InternPool) RuntimeOrderIterator { assert(s.layout != .Packed); diff --git a/src/Sema.zig b/src/Sema.zig index 1e4f6dea28..1eea36ec51 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -34293,6 +34293,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { ); return sema.failWithOwnedErrorMsg(null, msg); } + defer struct_type.clearLayoutWip(ip); const aligns = try sema.arena.alloc(Alignment, struct_type.field_types.len); const sizes = try sema.arena.alloc(u64, struct_type.field_types.len); @@ -34300,6 +34301,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { for (aligns, sizes, 0..) |*field_align, *field_size, i| { const field_ty = struct_type.field_types.get(ip)[i].toType(); if (struct_type.fieldIsComptime(ip, i) or !(try sema.typeHasRuntimeBits(field_ty))) { + struct_type.offsets.get(ip)[i] = 0; field_size.* = 0; field_align.* = .none; continue; @@ -34379,6 +34381,9 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { var offset: u64 = 0; var big_align: Alignment = .@"1"; while (it.next()) |i| { + const field_ty = struct_type.field_types.get(ip)[i].toType(); + // Type query definitely valid as we performed it earlier + if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; big_align = big_align.max(aligns[i]); offsets[i] = @intCast(aligns[i].forward(offset)); offset = offsets[i] + sizes[i]; @@ -34832,7 +34837,7 @@ fn resolveTypeFieldsStruct( ); return sema.failWithOwnedErrorMsg(null, msg); } - errdefer struct_type.clearTypesWip(ip); + defer struct_type.clearTypesWip(ip); try semaStructFields(mod, sema.arena, struct_type); } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 3ffe77e305..ebcdb82887 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2504,6 +2504,7 @@ pub const Object = struct { var it = struct_type.iterateRuntimeOrder(ip); while (it.next()) |field_index| { const field_ty = field_types[field_index].toType(); + if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; const field_size = field_ty.abiSize(mod); const field_align = mod.structFieldAlignment( struct_type.fieldAlign(ip, field_index), @@ -3306,6 +3307,7 @@ pub const Object = struct { var it = struct_type.iterateRuntimeOrder(ip); while (it.next()) |field_index| { const field_ty = struct_type.field_types.get(ip)[field_index].toType(); + if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; const field_align = mod.structFieldAlignment( struct_type.fieldAlign(ip, field_index), field_ty, @@ -4016,10 +4018,11 @@ pub const Object = struct { var need_unnamed = false; var field_it = struct_type.iterateRuntimeOrder(ip); while (field_it.next()) |field_index| { - const field_ty = struct_type.field_types.get(ip)[field_index]; + const field_ty = struct_type.field_types.get(ip)[field_index].toType(); + if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; const field_align = mod.structFieldAlignment( struct_type.fieldAlign(ip, field_index), - field_ty.toType(), + field_ty, struct_type.layout, ); big_align = big_align.max(field_align); @@ -4045,7 +4048,7 @@ pub const Object = struct { need_unnamed = true; llvm_index += 1; - offset += field_ty.toType().abiSize(mod); + offset += field_ty.abiSize(mod); } { const prev_offset = offset; diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 70654662b4..2beef48595 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -351,25 +351,41 @@ pub const DeclState = struct { break :blk; } - for ( - struct_type.field_names.get(ip), - struct_type.field_types.get(ip), - struct_type.offsets.get(ip), - ) |field_name_ip, field_ty, field_off| { - if (!field_ty.toType().hasRuntimeBits(mod)) continue; - const field_name = ip.stringToSlice(field_name_ip); - // DW.AT.member - try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2); - dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_member)); - // DW.AT.name, DW.FORM.string - dbg_info_buffer.appendSliceAssumeCapacity(field_name); - dbg_info_buffer.appendAssumeCapacity(0); - // DW.AT.type, DW.FORM.ref4 - var index = dbg_info_buffer.items.len; - try dbg_info_buffer.resize(index + 4); - try self.addTypeRelocGlobal(atom_index, field_ty.toType(), @intCast(index)); - // DW.AT.data_member_location, DW.FORM.udata - try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); + if (struct_type.isTuple(ip)) { + for (struct_type.field_types.get(ip), struct_type.offsets.get(ip), 0..) |field_ty, field_off, field_index| { + if (!field_ty.toType().hasRuntimeBits(mod)) continue; + // DW.AT.member + try dbg_info_buffer.append(@intFromEnum(AbbrevKind.struct_member)); + // DW.AT.name, DW.FORM.string + try dbg_info_buffer.writer().print("{d}\x00", .{field_index}); + // DW.AT.type, DW.FORM.ref4 + var index = dbg_info_buffer.items.len; + try dbg_info_buffer.resize(index + 4); + try self.addTypeRelocGlobal(atom_index, field_ty.toType(), @as(u32, @intCast(index))); + // DW.AT.data_member_location, DW.FORM.udata + try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); + } + } else { + for ( + struct_type.field_names.get(ip), + struct_type.field_types.get(ip), + struct_type.offsets.get(ip), + ) |field_name_ip, field_ty, field_off| { + if (!field_ty.toType().hasRuntimeBits(mod)) continue; + const field_name = ip.stringToSlice(field_name_ip); + // DW.AT.member + try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2); + dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_member)); + // DW.AT.name, DW.FORM.string + dbg_info_buffer.appendSliceAssumeCapacity(field_name); + dbg_info_buffer.appendAssumeCapacity(0); + // DW.AT.type, DW.FORM.ref4 + var index = dbg_info_buffer.items.len; + try dbg_info_buffer.resize(index + 4); + try self.addTypeRelocGlobal(atom_index, field_ty.toType(), @intCast(index)); + // DW.AT.data_member_location, DW.FORM.udata + try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); + } } }, else => unreachable,