diff --git a/lib/std/dwarf/AT.zig b/lib/std/dwarf/AT.zig index 3477fd4079..a2a2011a8b 100644 --- a/lib/std/dwarf/AT.zig +++ b/lib/std/dwarf/AT.zig @@ -224,6 +224,8 @@ pub const ZIG_parent = 0x2ccd; pub const ZIG_padding = 0x2cce; pub const ZIG_relative_decl = 0x2cd0; pub const ZIG_decl_line_relative = 0x2cd1; +pub const ZIG_comptime_value = 0x2cd2; +pub const ZIG_comptime_default_value = 0x2cd3; pub const ZIG_sentinel = 0x2ce2; // UPC extension. diff --git a/lib/std/dwarf/TAG.zig b/lib/std/dwarf/TAG.zig index 3e16925ee0..6838c1dd02 100644 --- a/lib/std/dwarf/TAG.zig +++ b/lib/std/dwarf/TAG.zig @@ -119,3 +119,4 @@ pub const PGI_interface_block = 0xA020; // ZIG extensions. pub const ZIG_padding = 0xfdb1; +pub const ZIG_comptime_value = 0xfdb2; diff --git a/src/InternPool.zig b/src/InternPool.zig index 1dbfbb24e1..9dbcc3cef5 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -4704,9 +4704,45 @@ pub const Index = enum(u32) { } comptime { - if (builtin.zig_backend == .stage2_llvm and !builtin.strip_debug_info) { - _ = &dbHelper; - } + if (!builtin.strip_debug_info) switch (builtin.zig_backend) { + .stage2_llvm => _ = &dbHelper, + .stage2_x86_64 => { + for (@typeInfo(Tag).@"enum".fields) |tag| { + if (!@hasField(@TypeOf(Tag.encodings), tag.name)) { + if (false) @compileLog("missing: " ++ @typeName(Tag) ++ ".encodings." ++ tag.name); + continue; + } + const encoding = @field(Tag.encodings, tag.name); + for (@typeInfo(encoding.trailing).@"struct".fields) |field| { + struct { + fn checkConfig(name: []const u8) void { + if (!@hasField(@TypeOf(encoding.config), name)) @compileError("missing field: " ++ @typeName(Tag) ++ ".encodings." ++ tag.name ++ ".config.@\"" ++ name ++ "\""); + const FieldType = @TypeOf(@field(encoding.config, name)); + if (@typeInfo(FieldType) != .enum_literal) @compileError("expected enum literal: " ++ @typeName(Tag) ++ ".encodings." ++ tag.name ++ ".config.@\"" ++ name ++ "\": " ++ @typeName(FieldType)); + } + fn checkField(name: []const u8, Type: type) void { + switch (@typeInfo(Type)) { + .int => {}, + .@"enum" => {}, + .@"struct" => |info| assert(info.layout == .@"packed"), + .optional => |info| { + checkConfig(name ++ ".?"); + checkField(name ++ ".?", info.child); + }, + .pointer => |info| { + assert(info.size == .Slice); + checkConfig(name ++ ".len"); + checkField(name ++ "[0]", info.child); + }, + else => @compileError("unsupported type: " ++ @typeName(Tag) ++ ".encodings." ++ tag.name ++ "." ++ name ++ ": " ++ @typeName(Type)), + } + } + }.checkField("trailing." ++ field.name, field.type); + } + } + }, + else => {}, + }; } }; @@ -5302,6 +5338,39 @@ pub const Tag = enum(u8) { }; } + const encodings = .{ + .type_struct = .{ + .payload = TypeStruct, + .trailing = struct { + captures_len: ?u32, + captures: ?[]CaptureValue, + type_hash: ?u64, + field_types: []Index, + field_inits: ?[]Index, + field_aligns: ?[]Alignment, + field_is_comptime_bits: ?[]u32, + field_index: ?[]LoadedStructType.RuntimeOrder, + field_offset: []u32, + }, + .config = .{ + .@"trailing.captures_len.?" = .@"payload.flags.any_captures", + .@"trailing.captures.?" = .@"payload.flags.any_captures", + .@"trailing.captures.?.len" = .@"trailing.captures_len", + .@"trailing.type_hash.?" = .@"payload.flags.is_reified", + .@"trailing.field_types.len" = .@"payload.fields_len", + .@"trailing.field_inits.?" = .@"payload.flags.any_default_inits", + .@"trailing.field_inits.?.len" = .@"payload.fields_len", + .@"trailing.field_aligns.?" = .@"payload.flags.any_aligned_fields", + .@"trailing.field_aligns.?.len" = .@"payload.fields_len", + .@"trailing.field_is_comptime_bits.?" = .@"payload.flags.any_comptime_fields", + .@"trailing.field_is_comptime_bits.?.len" = .@"(payload.fields_len + 31) / 32", + .@"trailing.field_index.?" = .@"!payload.flags.is_extern", + .@"trailing.field_index.?.len" = .@"!payload.flags.is_extern", + .@"trailing.field_offset.len" = .@"payload.fields_len", + }, + }, + }; + pub const Variable = struct { ty: Index, /// May be `none`. diff --git a/src/Type.zig b/src/Type.zig index dc229fef61..e3056fdd21 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -4126,6 +4126,7 @@ pub const @"anyframe": Type = .{ .ip_index = .anyframe_type }; pub const @"null": Type = .{ .ip_index = .null_type }; pub const @"undefined": Type = .{ .ip_index = .undefined_type }; pub const @"noreturn": Type = .{ .ip_index = .noreturn_type }; +pub const enum_literal: Type = .{ .ip_index = .enum_literal_type }; pub const @"c_char": Type = .{ .ip_index = .c_char_type }; pub const @"c_short": Type = .{ .ip_index = .c_short_type }; diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 6bf311fe7f..4f336083ec 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -6,6 +6,7 @@ address_size: AddressSize, mods: std.AutoArrayHashMapUnmanaged(*Module, ModInfo), types: std.AutoArrayHashMapUnmanaged(InternPool.Index, Entry.Index), +values: std.AutoArrayHashMapUnmanaged(InternPool.Index, Entry.Index), navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Entry.Index), debug_abbrev: DebugAbbrev, @@ -1055,6 +1056,11 @@ pub const Loc = union(enum) { form_tls_address: *const Loc, implicit_value: []const u8, stack_value: *const Loc, + implicit_pointer: struct { + unit: Unit.Index, + entry: Entry.Index, + offset: i65, + }, wasm_ext: union(enum) { local: u32, global: u32, @@ -1193,6 +1199,11 @@ pub const Loc = union(enum) { try value.write(adapter); try writer.writeByte(DW.OP.stack_value); }, + .implicit_pointer => |implicit_pointer| { + try writer.writeByte(DW.OP.implicit_pointer); + try adapter.infoEntry(implicit_pointer.unit, implicit_pointer.entry); + try sleb128(writer, implicit_pointer.offset); + }, .wasm_ext => |wasm_ext| { try writer.writeByte(DW.OP.WASM_location); switch (wasm_ext) { @@ -1386,7 +1397,7 @@ pub const WipNav = struct { debug_info: std.ArrayListUnmanaged(u8), debug_line: std.ArrayListUnmanaged(u8), debug_loclists: std.ArrayListUnmanaged(u8), - pending_types: std.ArrayListUnmanaged(InternPool.Index), + pending_lazy: std.ArrayListUnmanaged(InternPool.Index), pub fn deinit(wip_nav: *WipNav) void { const gpa = wip_nav.dwarf.gpa; @@ -1395,7 +1406,7 @@ pub const WipNav = struct { wip_nav.debug_info.deinit(gpa); wip_nav.debug_line.deinit(gpa); wip_nav.debug_loclists.deinit(gpa); - wip_nav.pending_types.deinit(gpa); + wip_nav.pending_lazy.deinit(gpa); } pub fn genDebugFrame(wip_nav: *WipNav, loc: u32, cfa: Cfa) UpdateError!void { @@ -1420,7 +1431,7 @@ pub const WipNav = struct { }); try wip_nav.strp(name); try wip_nav.refType(ty); - try wip_nav.exprloc(loc); + try wip_nav.infoExprloc(loc); wip_nav.any_children = true; } @@ -1627,33 +1638,39 @@ pub const WipNav = struct { try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), try wip_nav.dwarf.refAbbrevCode(abbrev_code)); } - fn infoSectionOffset(wip_nav: *WipNav, sec: Section.Index, unit: Unit.Index, entry: Entry.Index, off: u32) UpdateError!void { + fn sectionOffset(wip_nav: *WipNav, comptime sec: Section.Index, target_sec: Section.Index, target_unit: Unit.Index, target_entry: Entry.Index, target_off: u32) UpdateError!void { const dwarf = wip_nav.dwarf; const gpa = dwarf.gpa; - const entry_ptr = dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry); - if (sec != .debug_info) { + const entry_ptr = @field(dwarf, @tagName(sec)).section.getUnit(wip_nav.unit).getEntry(wip_nav.entry); + const bytes = &@field(wip_nav, @tagName(sec)); + const source_off: u32 = @intCast(bytes.items.len); + if (target_sec != sec) { try entry_ptr.cross_section_relocs.append(gpa, .{ - .source_off = @intCast(wip_nav.debug_info.items.len), - .target_sec = sec, - .target_unit = unit, - .target_entry = entry.toOptional(), - .target_off = off, + .source_off = source_off, + .target_sec = target_sec, + .target_unit = target_unit, + .target_entry = target_entry.toOptional(), + .target_off = target_off, }); - } else if (unit != wip_nav.unit) { + } else if (target_unit != wip_nav.unit) { try entry_ptr.cross_unit_relocs.append(gpa, .{ - .source_off = @intCast(wip_nav.debug_info.items.len), - .target_unit = unit, - .target_entry = entry.toOptional(), - .target_off = off, + .source_off = source_off, + .target_unit = target_unit, + .target_entry = target_entry.toOptional(), + .target_off = target_off, }); } else { try entry_ptr.cross_entry_relocs.append(gpa, .{ - .source_off = @intCast(wip_nav.debug_info.items.len), - .target_entry = entry.toOptional(), - .target_off = off, + .source_off = source_off, + .target_entry = target_entry.toOptional(), + .target_off = target_off, }); } - try wip_nav.debug_info.appendNTimes(gpa, 0, dwarf.sectionOffsetBytes()); + try bytes.appendNTimes(gpa, 0, dwarf.sectionOffsetBytes()); + } + + fn infoSectionOffset(wip_nav: *WipNav, target_sec: Section.Index, target_unit: Unit.Index, target_entry: Entry.Index, target_off: u32) UpdateError!void { + try wip_nav.sectionOffset(.debug_info, target_sec, target_unit, target_entry, target_off); } fn strp(wip_nav: *WipNav, str: []const u8) UpdateError!void { @@ -1663,7 +1680,15 @@ pub const WipNav = struct { const ExprLocCounter = struct { const Stream = std.io.CountingWriter(std.io.NullWriter); stream: Stream, + section_offset_bytes: u32, address_size: AddressSize, + fn init(dwarf: *Dwarf) ExprLocCounter { + return .{ + .stream = std.io.countingWriter(std.io.null_writer), + .section_offset_bytes = dwarf.sectionOffsetBytes(), + .address_size = dwarf.address_size, + }; + } fn writer(counter: *ExprLocCounter) Stream.Writer { return counter.stream.writer(); } @@ -1673,13 +1698,13 @@ pub const WipNav = struct { fn addrSym(counter: *ExprLocCounter, _: u32) error{}!void { counter.stream.bytes_written += @intFromEnum(counter.address_size); } + fn infoEntry(counter: *ExprLocCounter, _: Unit.Index, _: Entry.Index) error{}!void { + counter.stream.bytes_written += counter.section_offset_bytes; + } }; - fn exprloc(wip_nav: *WipNav, loc: Loc) UpdateError!void { - var counter: ExprLocCounter = .{ - .stream = std.io.countingWriter(std.io.null_writer), - .address_size = wip_nav.dwarf.address_size, - }; + fn infoExprloc(wip_nav: *WipNav, loc: Loc) UpdateError!void { + var counter: ExprLocCounter = .init(wip_nav.dwarf); try loc.write(&counter); const adapter: struct { @@ -1693,6 +1718,9 @@ pub const WipNav = struct { fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { try ctx.wip_nav.infoAddrSym(sym_index, 0); } + fn infoEntry(ctx: @This(), unit: Unit.Index, entry: Entry.Index) UpdateError!void { + try ctx.wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); + } } = .{ .wip_nav = wip_nav }; try uleb128(adapter.writer(), counter.stream.bytes_written); try loc.write(adapter); @@ -1708,10 +1736,7 @@ pub const WipNav = struct { } fn frameExprloc(wip_nav: *WipNav, loc: Loc) UpdateError!void { - var counter: ExprLocCounter = .{ - .stream = std.io.countingWriter(std.io.null_writer), - .address_size = wip_nav.dwarf.address_size, - }; + var counter: ExprLocCounter = .init(wip_nav.dwarf); try loc.write(&counter); const adapter: struct { @@ -1725,6 +1750,9 @@ pub const WipNav = struct { fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { try ctx.wip_nav.frameAddrSym(sym_index, 0); } + fn infoEntry(ctx: @This(), unit: Unit.Index, entry: Entry.Index) UpdateError!void { + try ctx.wip_nav.sectionOffset(.debug_frame, .debug_info, unit, entry, 0); + } } = .{ .wip_nav = wip_nav }; try uleb128(adapter.writer(), counter.stream.bytes_written); try loc.write(adapter); @@ -1739,6 +1767,22 @@ pub const WipNav = struct { try wip_nav.debug_frame.appendNTimes(wip_nav.dwarf.gpa, 0, @intFromEnum(wip_nav.dwarf.address_size)); } + fn getNavEntry(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) UpdateError!struct { Unit.Index, Entry.Index } { + const zcu = wip_nav.pt.zcu; + const ip = &zcu.intern_pool; + const unit = try wip_nav.dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav_index).srcInst(ip).resolveFile(ip)).mod); + const gop = try wip_nav.dwarf.navs.getOrPut(wip_nav.dwarf.gpa, nav_index); + if (gop.found_existing) return .{ unit, gop.value_ptr.* }; + const entry = try wip_nav.dwarf.addCommonEntry(unit); + gop.value_ptr.* = entry; + return .{ unit, entry }; + } + + fn refNav(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) UpdateError!void { + const unit, const entry = try wip_nav.getNavEntry(nav_index); + try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); + } + fn getTypeEntry(wip_nav: *WipNav, ty: Type) UpdateError!struct { Unit.Index, Entry.Index } { const zcu = wip_nav.pt.zcu; const ip = &zcu.intern_pool; @@ -1751,7 +1795,7 @@ pub const WipNav = struct { if (gop.found_existing) return .{ unit, gop.value_ptr.* }; const entry = try wip_nav.dwarf.addCommonEntry(unit); gop.value_ptr.* = entry; - if (maybe_inst_index == null) try wip_nav.pending_types.append(wip_nav.dwarf.gpa, ty.toIntern()); + if (maybe_inst_index == null) try wip_nav.pending_lazy.append(wip_nav.dwarf.gpa, ty.toIntern()); return .{ unit, entry }; } @@ -1760,13 +1804,25 @@ pub const WipNav = struct { try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); } - fn refNav(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) UpdateError!void { + fn getValueEntry(wip_nav: *WipNav, value: Value) UpdateError!struct { Unit.Index, Entry.Index } { const zcu = wip_nav.pt.zcu; const ip = &zcu.intern_pool; - const unit = try wip_nav.dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav_index).srcInst(ip).resolveFile(ip)).mod); - const nav_gop = try wip_nav.dwarf.navs.getOrPut(wip_nav.dwarf.gpa, nav_index); - if (!nav_gop.found_existing) nav_gop.value_ptr.* = try wip_nav.dwarf.addCommonEntry(unit); - try wip_nav.infoSectionOffset(.debug_info, unit, nav_gop.value_ptr.*, 0); + const ty = value.typeOf(zcu); + if (std.debug.runtime_safety) assert(ty.comptimeOnly(zcu) and try ty.onePossibleValue(wip_nav.pt) == null); + if (ty.toIntern() == .type_type) return wip_nav.getTypeEntry(value.toType()); + if (ip.isFunctionType(ty.toIntern())) return wip_nav.getNavEntry(zcu.funcInfo(value.toIntern()).owner_nav); + const gop = try wip_nav.dwarf.values.getOrPut(wip_nav.dwarf.gpa, value.toIntern()); + const unit: Unit.Index = .main; + if (gop.found_existing) return .{ unit, gop.value_ptr.* }; + const entry = try wip_nav.dwarf.addCommonEntry(unit); + gop.value_ptr.* = entry; + try wip_nav.pending_lazy.append(wip_nav.dwarf.gpa, value.toIntern()); + return .{ unit, entry }; + } + + fn refValue(wip_nav: *WipNav, value: Value) UpdateError!void { + const unit, const entry = try wip_nav.getValueEntry(value); + try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); } fn refForward(wip_nav: *WipNav) std.mem.Allocator.Error!u32 { @@ -1809,73 +1865,81 @@ pub const WipNav = struct { } } + const AbbrevCodeForForm = struct { + sdata: AbbrevCode, + udata: AbbrevCode, + block: AbbrevCode, + }; + + fn bigIntConstValue( + wip_nav: *WipNav, + abbrev_code: AbbrevCodeForForm, + ty: Type, + big_int: std.math.big.int.Const, + ) UpdateError!void { + const zcu = wip_nav.pt.zcu; + const diw = wip_nav.debug_info.writer(wip_nav.dwarf.gpa); + const signedness = switch (ty.toIntern()) { + .comptime_int_type, .comptime_float_type => .signed, + else => ty.intInfo(zcu).signedness, + }; + const bits = @max(1, big_int.bitCountTwosCompForSignedness(signedness)); + if (bits <= 64) { + try wip_nav.abbrevCode(switch (signedness) { + .signed => abbrev_code.sdata, + .unsigned => abbrev_code.udata, + }); + try wip_nav.debug_info.ensureUnusedCapacity(wip_nav.dwarf.gpa, std.math.divCeil(usize, bits, 7) catch unreachable); + var bit: usize = 0; + var carry: u1 = 1; + while (bit < bits) { + const limb_bits = @typeInfo(std.math.big.Limb).int.bits; + const limb_index = bit / limb_bits; + const limb_shift: std.math.Log2Int(std.math.big.Limb) = @intCast(bit % limb_bits); + const low_abs_part: u7 = @truncate(big_int.limbs[limb_index] >> limb_shift); + const abs_part = if (limb_shift > limb_bits - 7 and limb_index + 1 < big_int.limbs.len) abs_part: { + const high_abs_part: u7 = @truncate(big_int.limbs[limb_index + 1] << -%limb_shift); + break :abs_part high_abs_part | low_abs_part; + } else low_abs_part; + const twos_comp_part = if (big_int.positive) abs_part else twos_comp_part: { + const twos_comp_part, carry = @addWithOverflow(~abs_part, carry); + break :twos_comp_part twos_comp_part; + }; + bit += 7; + wip_nav.debug_info.appendAssumeCapacity(@as(u8, if (bit < bits) 0x80 else 0x00) | twos_comp_part); + } + } else { + try wip_nav.abbrevCode(abbrev_code.block); + const bytes = @max(ty.abiSize(zcu), std.math.divCeil(usize, bits, 8) catch unreachable); + try uleb128(diw, bytes); + big_int.writeTwosComplement( + try wip_nav.debug_info.addManyAsSlice(wip_nav.dwarf.gpa, @intCast(bytes)), + wip_nav.dwarf.endian, + ); + } + } + fn enumConstValue( wip_nav: *WipNav, loaded_enum: InternPool.LoadedEnumType, - abbrev_code: struct { - sdata: AbbrevCode, - udata: AbbrevCode, - block: AbbrevCode, - }, + abbrev_code: AbbrevCodeForForm, field_index: usize, ) UpdateError!void { const zcu = wip_nav.pt.zcu; const ip = &zcu.intern_pool; - const diw = wip_nav.debug_info.writer(wip_nav.dwarf.gpa); - const signedness = switch (loaded_enum.tag_ty) { - .comptime_int_type => .signed, - else => Type.fromInterned(loaded_enum.tag_ty).intInfo(zcu).signedness, - }; - if (loaded_enum.values.len > 0) { - var big_int_space: Value.BigIntSpace = undefined; - const big_int = ip.indexToKey(loaded_enum.values.get(ip)[field_index]).int.storage.toBigInt(&big_int_space); - const bits = @max(1, big_int.bitCountTwosCompForSignedness(signedness)); - if (bits <= 64) { - try wip_nav.abbrevCode(switch (signedness) { - .signed => abbrev_code.sdata, - .unsigned => abbrev_code.udata, - }); - try wip_nav.debug_info.ensureUnusedCapacity(wip_nav.dwarf.gpa, std.math.divCeil(usize, bits, 7) catch unreachable); - var bit: usize = 0; - var carry: u1 = 1; - while (bit < bits) : (bit += 7) { - const limb_bits = @typeInfo(std.math.big.Limb).int.bits; - const limb_index = bit / limb_bits; - const limb_shift: std.math.Log2Int(std.math.big.Limb) = @intCast(bit % limb_bits); - const low_abs_part: u7 = @truncate(big_int.limbs[limb_index] >> limb_shift); - const abs_part = if (limb_shift > limb_bits - 7 and limb_index + 1 < big_int.limbs.len) abs_part: { - const high_abs_part: u7 = @truncate(big_int.limbs[limb_index + 1] << -%limb_shift); - break :abs_part high_abs_part | low_abs_part; - } else low_abs_part; - const twos_comp_part = if (big_int.positive) abs_part else twos_comp_part: { - const twos_comp_part, carry = @addWithOverflow(~abs_part, carry); - break :twos_comp_part twos_comp_part; - }; - wip_nav.debug_info.appendAssumeCapacity(@as(u8, if (bit + 7 < bits) 0x80 else 0x00) | twos_comp_part); - } - } else { - try wip_nav.abbrevCode(abbrev_code.block); - const bytes = Type.fromInterned(loaded_enum.tag_ty).abiSize(zcu); - try uleb128(diw, bytes); - big_int.writeTwosComplement( - try wip_nav.debug_info.addManyAsSlice(wip_nav.dwarf.gpa, @intCast(bytes)), - wip_nav.dwarf.endian, - ); - } - } else switch (signedness) { - .signed => { - try wip_nav.abbrevCode(abbrev_code.sdata); - try sleb128(diw, field_index); - }, - .unsigned => { - try wip_nav.abbrevCode(abbrev_code.udata); - try uleb128(diw, field_index); - }, - } + var big_int_space: Value.BigIntSpace = undefined; + try wip_nav.bigIntConstValue(abbrev_code, .fromInterned(loaded_enum.tag_ty), if (loaded_enum.values.len > 0) + Value.fromInterned(loaded_enum.values.get(ip)[field_index]).toBigInt(&big_int_space, zcu) + else + std.math.big.int.Mutable.init(&big_int_space.limbs, field_index).toConst()); } - fn flush(wip_nav: *WipNav, src_loc: Zcu.LazySrcLoc) UpdateError!void { - while (wip_nav.pending_types.popOrNull()) |ty| try wip_nav.dwarf.updateType(wip_nav.pt, src_loc, ty, &wip_nav.pending_types); + fn updateLazy(wip_nav: *WipNav, src_loc: Zcu.LazySrcLoc) UpdateError!void { + const ip = &wip_nav.pt.zcu.intern_pool; + while (wip_nav.pending_lazy.popOrNull()) |val| switch (ip.typeOf(val)) { + .type_type => try wip_nav.dwarf.updateLazyType(wip_nav.pt, src_loc, val, &wip_nav.pending_lazy), + else => try wip_nav.dwarf.updateLazyValue(wip_nav.pt, src_loc, val, &wip_nav.pending_lazy), + }; } }; @@ -1904,6 +1968,7 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf { .mods = .{}, .types = .{}, + .values = .{}, .navs = .{}, .debug_abbrev = .{ .section = Section.init }, @@ -2075,6 +2140,7 @@ pub fn deinit(dwarf: *Dwarf) void { for (dwarf.mods.values()) |*mod_info| mod_info.deinit(gpa); dwarf.mods.deinit(gpa); dwarf.types.deinit(gpa); + dwarf.values.deinit(gpa); dwarf.navs.deinit(gpa); dwarf.debug_abbrev.section.deinit(gpa); dwarf.debug_aranges.section.deinit(gpa); @@ -2186,7 +2252,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In .debug_info = .{}, .debug_line = .{}, .debug_loclists = .{}, - .pending_types = .{}, + .pending_lazy = .{}, }; errdefer wip_nav.deinit(); @@ -2223,7 +2289,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.abbrevCode(.decl_var); - try wip_nav.refType(Type.fromInterned(parent_type)); + try wip_nav.refType(.fromInterned(parent_type)); assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); try uleb128(diw, loc.column + 1); @@ -2232,7 +2298,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In try wip_nav.strp(nav.fqn.toSlice(ip)); const nav_ty = nav_val.typeOf(zcu); const nav_ty_reloc_index = try wip_nav.refForward(); - try wip_nav.exprloc(.{ .addr = .{ .sym = sym_index } }); + try wip_nav.infoExprloc(.{ .addr = .{ .sym = sym_index } }); try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse nav_ty.abiAlignment(zcu).toByteUnits().?); try diw.writeByte(@intFromBool(false)); @@ -2272,17 +2338,17 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.abbrevCode(.decl_var); - try wip_nav.refType(Type.fromInterned(parent_type)); + try wip_nav.refType(.fromInterned(parent_type)); assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); try uleb128(diw, loc.column + 1); try diw.writeByte(accessibility); try wip_nav.strp(nav.name.toSlice(ip)); try wip_nav.strp(nav.fqn.toSlice(ip)); - const ty = Type.fromInterned(variable.ty); + const ty: Type = .fromInterned(variable.ty); try wip_nav.refType(ty); const addr: Loc = .{ .addr = .{ .sym = sym_index } }; - try wip_nav.exprloc(if (variable.is_threadlocal) .{ .form_tls_address = &addr } else addr); + try wip_nav.infoExprloc(if (variable.is_threadlocal) .{ .form_tls_address = &addr } else addr); try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse ty.abiAlignment(zcu).toByteUnits().?); try diw.writeByte(@intFromBool(false)); @@ -2364,14 +2430,14 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.abbrevCode(.decl_func); - try wip_nav.refType(Type.fromInterned(parent_type)); + try wip_nav.refType(.fromInterned(parent_type)); assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); try uleb128(diw, loc.column + 1); try diw.writeByte(accessibility); try wip_nav.strp(nav.name.toSlice(ip)); try wip_nav.strp(nav.fqn.toSlice(ip)); - try wip_nav.refType(Type.fromInterned(func_type.return_type)); + try wip_nav.refType(.fromInterned(func_type.return_type)); try wip_nav.infoAddrSym(sym_index, 0); wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len); try diw.writeInt(u32, 0, dwarf.endian); @@ -2525,7 +2591,7 @@ pub fn finishWipNav( } try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.items); - try wip_nav.flush(zcu.navSrcLoc(nav_index)); + try wip_nav.updateLazy(zcu.navSrcLoc(nav_index)); } pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateError!void { @@ -2586,7 +2652,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool .debug_info = .{}, .debug_line = .{}, .debug_loclists = .{}, - .pending_types = .{}, + .pending_lazy = .{}, }; defer wip_nav.deinit(); @@ -2648,7 +2714,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool switch (loaded_struct.layout) { .auto, .@"extern" => { try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .decl_namespace_struct else .decl_struct); - try wip_nav.refType(Type.fromInterned(parent_type)); + try wip_nav.refType(.fromInterned(parent_type)); assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); try uleb128(diw, loc.column + 1); @@ -2661,43 +2727,65 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool const is_comptime = loaded_struct.fieldIsComptime(ip, field_index); const field_init = loaded_struct.fieldInit(ip, field_index); assert(!(is_comptime and field_init == .none)); + const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); + const has_runtime_bits, const has_comptime_state = switch (field_init) { + .none => .{ false, false }, + else => .{ + field_type.hasRuntimeBits(zcu), + field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null, + }, + }; try wip_nav.abbrevCode(if (is_comptime) - .struct_field_comptime + if (has_runtime_bits and has_comptime_state) + .struct_field_comptime_runtime_bits_comptime_state + else if (has_comptime_state) + .struct_field_comptime_comptime_state + else if (has_runtime_bits) + .struct_field_comptime_runtime_bits + else + .struct_field_comptime else if (field_init != .none) - .struct_field_default + if (has_runtime_bits and has_comptime_state) + .struct_field_default_runtime_bits_comptime_state + else if (has_comptime_state) + .struct_field_default_comptime_state + else if (has_runtime_bits) + .struct_field_default_runtime_bits + else + .struct_field_default else .struct_field); if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| try wip_nav.strp(field_name.toSlice(ip)) else { - const field_name = try std.fmt.allocPrint(dwarf.gpa, "{d}", .{field_index}); - defer dwarf.gpa.free(field_name); + var field_name_buf: [std.fmt.count("{d}", .{std.math.maxInt(u32)})]u8 = undefined; + const field_name = std.fmt.bufPrint(&field_name_buf, "{d}", .{field_index}) catch unreachable; try wip_nav.strp(field_name); } - const field_type = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); if (!is_comptime) { try uleb128(diw, loaded_struct.offsets.get(ip)[field_index]); try uleb128(diw, loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse field_type.abiAlignment(zcu).toByteUnits().?); } - if (field_init != .none) try wip_nav.blockValue(nav_src_loc, Value.fromInterned(field_init)); + if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, .fromInterned(field_init)); + if (has_comptime_state) try wip_nav.refValue(.fromInterned(field_init)); } try uleb128(diw, @intFromEnum(AbbrevCode.null)); } }, .@"packed" => { try wip_nav.abbrevCode(.decl_packed_struct); - try wip_nav.refType(Type.fromInterned(parent_type)); + try wip_nav.refType(.fromInterned(parent_type)); assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); try uleb128(diw, loc.column + 1); try diw.writeByte(accessibility); try wip_nav.strp(nav.name.toSlice(ip)); - try wip_nav.refType(Type.fromInterned(loaded_struct.backingIntTypeUnordered(ip))); + try wip_nav.refType(.fromInterned(loaded_struct.backingIntTypeUnordered(ip))); var field_bit_offset: u16 = 0; for (0..loaded_struct.field_types.len) |field_index| { try wip_nav.abbrevCode(.packed_struct_field); try wip_nav.strp(loaded_struct.fieldName(ip, field_index).unwrap().?.toSlice(ip)); - const field_type = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); + const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); try uleb128(diw, field_bit_offset); field_bit_offset += @intCast(field_type.bitSize(zcu)); @@ -2745,13 +2833,13 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool wip_nav.entry = nav_gop.value_ptr.*; const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.abbrevCode(if (loaded_enum.names.len > 0) .decl_enum else .decl_empty_enum); - try wip_nav.refType(Type.fromInterned(parent_type)); + try wip_nav.refType(.fromInterned(parent_type)); assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); try uleb128(diw, loc.column + 1); try diw.writeByte(accessibility); try wip_nav.strp(nav.name.toSlice(ip)); - try wip_nav.refType(Type.fromInterned(loaded_enum.tag_ty)); + try wip_nav.refType(.fromInterned(loaded_enum.tag_ty)); for (0..loaded_enum.names.len) |field_index| { try wip_nav.enumConstValue(loaded_enum, .{ .sdata = .signed_enum_field, @@ -2800,7 +2888,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool wip_nav.entry = nav_gop.value_ptr.*; const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.abbrevCode(.decl_union); - try wip_nav.refType(Type.fromInterned(parent_type)); + try wip_nav.refType(.fromInterned(parent_type)); assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); try uleb128(diw, loc.column + 1); @@ -2821,7 +2909,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("tag"); - try wip_nav.refType(Type.fromInterned(loaded_union.enum_tag_ty)); + try wip_nav.refType(.fromInterned(loaded_union.enum_tag_ty)); try uleb128(diw, union_layout.tagOffset()); for (0..loaded_union.field_types.len) |field_index| { @@ -2833,7 +2921,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool { try wip_nav.abbrevCode(.struct_field); try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); - const field_type = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); + const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); try uleb128(diw, union_layout.payloadOffset()); try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse @@ -2846,7 +2934,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool } else for (0..loaded_union.field_types.len) |field_index| { try wip_nav.abbrevCode(.untagged_union_field); try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); - const field_type = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); + const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse field_type.abiAlignment(zcu).toByteUnits().?); @@ -2891,7 +2979,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool wip_nav.entry = nav_gop.value_ptr.*; const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.abbrevCode(.decl_namespace_struct); - try wip_nav.refType(Type.fromInterned(parent_type)); + try wip_nav.refType(.fromInterned(parent_type)); assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); try uleb128(diw, loc.column + 1); @@ -2947,17 +3035,17 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool .decl_func_generic else .decl_empty_func_generic); - try wip_nav.refType(Type.fromInterned(parent_type)); + try wip_nav.refType(.fromInterned(parent_type)); assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); try uleb128(diw, loc.column + 1); try diw.writeByte(accessibility); try wip_nav.strp(nav.name.toSlice(ip)); - try wip_nav.refType(Type.fromInterned(func_type.return_type)); + try wip_nav.refType(.fromInterned(func_type.return_type)); if (func_type.param_types.len > 0 or func_type.is_var_args) { for (0..func_type.param_types.len) |param_index| { try wip_nav.abbrevCode(.func_type_param); - try wip_nav.refType(Type.fromInterned(func_type.param_types.get(ip)[param_index])); + try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index])); } if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args); try uleb128(diw, @intFromEnum(AbbrevCode.null)); @@ -2979,7 +3067,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool .decl_alias => { const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.abbrevCode(.decl_alias); - try wip_nav.refType(Type.fromInterned(parent_type)); + try wip_nav.refType(.fromInterned(parent_type)); assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); try uleb128(diw, loc.column + 1); @@ -2990,7 +3078,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool .decl_var => { const diw = wip_nav.debug_info.writer(dwarf.gpa); try wip_nav.abbrevCode(.decl_var); - try wip_nav.refType(Type.fromInterned(parent_type)); + try wip_nav.refType(.fromInterned(parent_type)); assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); try uleb128(diw, loc.column + 1); @@ -3006,42 +3094,52 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool }, .decl_const => { const diw = wip_nav.debug_info.writer(dwarf.gpa); - try wip_nav.abbrevCode(.decl_const); - try wip_nav.refType(Type.fromInterned(parent_type)); + const nav_ty = nav_val.typeOf(zcu); + const has_runtime_bits = nav_ty.hasRuntimeBits(zcu); + const has_comptime_state = nav_ty.comptimeOnly(zcu) and try nav_ty.onePossibleValue(pt) == null; + try wip_nav.abbrevCode(if (has_runtime_bits and has_comptime_state) + .decl_const_runtime_bits_comptime_state + else if (has_comptime_state) + .decl_const_comptime_state + else if (has_runtime_bits) + .decl_const_runtime_bits + else + .decl_const); + try wip_nav.refType(.fromInterned(parent_type)); assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf)); try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian); try uleb128(diw, loc.column + 1); try diw.writeByte(accessibility); try wip_nav.strp(nav.name.toSlice(ip)); try wip_nav.strp(nav.fqn.toSlice(ip)); - const nav_ty = nav_val.typeOf(zcu); const nav_ty_reloc_index = try wip_nav.refForward(); - try wip_nav.blockValue(nav_src_loc, nav_val); try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse nav_ty.abiAlignment(zcu).toByteUnits().?); try diw.writeByte(@intFromBool(false)); + if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, nav_val); + if (has_comptime_state) try wip_nav.refValue(nav_val); wip_nav.finishForward(nav_ty_reloc_index); try wip_nav.abbrevCode(.is_const); try wip_nav.refType(nav_ty); }, } try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); - try wip_nav.flush(nav_src_loc); + try wip_nav.updateLazy(nav_src_loc); } -fn updateType( +fn updateLazyType( dwarf: *Dwarf, pt: Zcu.PerThread, src_loc: Zcu.LazySrcLoc, type_index: InternPool.Index, - pending_types: *std.ArrayListUnmanaged(InternPool.Index), + pending_lazy: *std.ArrayListUnmanaged(InternPool.Index), ) UpdateError!void { const zcu = pt.zcu; const ip = &zcu.intern_pool; - const ty = Type.fromInterned(type_index); + const ty: Type = .fromInterned(type_index); switch (type_index) { - .generic_poison_type => log.debug("updateType({s})", .{"anytype"}), - else => log.debug("updateType({})", .{ty.fmt(pt)}), + .generic_poison_type => log.debug("updateLazyType({s})", .{"anytype"}), + else => log.debug("updateLazyType({})", .{ty.fmt(pt)}), } var wip_nav: WipNav = .{ @@ -3059,11 +3157,11 @@ fn updateType( .debug_info = .{}, .debug_line = .{}, .debug_loclists = .{}, - .pending_types = pending_types.*, + .pending_lazy = pending_lazy.*, }; defer { - pending_types.* = wip_nav.pending_types; - wip_nav.pending_types = .{}; + pending_lazy.* = wip_nav.pending_lazy; + wip_nav.pending_lazy = .{}; wip_nav.deinit(); } const diw = wip_nav.debug_info.writer(dwarf.gpa); @@ -3086,13 +3184,10 @@ fn updateType( }, .ptr_type => |ptr_type| switch (ptr_type.flags.size) { .One, .Many, .C => { - const ptr_child_type = Type.fromInterned(ptr_type.child); + const ptr_child_type: Type = .fromInterned(ptr_type.child); try wip_nav.abbrevCode(if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type); try wip_nav.strp(name); - if (ptr_type.sentinel != .none) try wip_nav.blockValue( - src_loc, - Value.fromInterned(ptr_type.sentinel), - ); + if (ptr_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(ptr_type.sentinel)); try uleb128(diw, ptr_type.flags.alignment.toByteUnits() orelse ptr_child_type.abiAlignment(zcu).toByteUnits().?); try diw.writeByte(@intFromEnum(ptr_type.flags.address_space)); @@ -3128,37 +3223,34 @@ fn updateType( try uleb128(diw, 0); try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("len"); - const len_field_type = Type.usize; + const len_field_type: Type = .usize; try wip_nav.refType(len_field_type); try uleb128(diw, len_field_type.abiAlignment(zcu).forward(ptr_field_type.abiSize(zcu))); try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, }, .array_type => |array_type| { - const array_child_type = Type.fromInterned(array_type.child); + const array_child_type: Type = .fromInterned(array_type.child); try wip_nav.abbrevCode(if (array_type.sentinel == .none) .array_type else .array_sentinel_type); try wip_nav.strp(name); - if (array_type.sentinel != .none) try wip_nav.blockValue( - src_loc, - Value.fromInterned(array_type.sentinel), - ); + if (array_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(array_type.sentinel)); try wip_nav.refType(array_child_type); try wip_nav.abbrevCode(.array_index); - try wip_nav.refType(Type.usize); + try wip_nav.refType(.usize); try uleb128(diw, array_type.len); try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .vector_type => |vector_type| { try wip_nav.abbrevCode(.vector_type); try wip_nav.strp(name); - try wip_nav.refType(Type.fromInterned(vector_type.child)); + try wip_nav.refType(.fromInterned(vector_type.child)); try wip_nav.abbrevCode(.array_index); - try wip_nav.refType(Type.usize); + try wip_nav.refType(.usize); try uleb128(diw, vector_type.len); try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, .opt_type => |opt_child_type_index| { - const opt_child_type = Type.fromInterned(opt_child_type_index); + const opt_child_type: Type = .fromInterned(opt_child_type_index); try wip_nav.abbrevCode(.union_type); try wip_nav.strp(name); try uleb128(diw, ty.abiSize(zcu)); @@ -3166,7 +3258,7 @@ fn updateType( if (opt_child_type.isNoReturn(zcu)) { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("null"); - try wip_nav.refType(Type.null); + try wip_nav.refType(.null); try uleb128(diw, 0); } else { try wip_nav.abbrevCode(.tagged_union); @@ -3189,21 +3281,21 @@ fn updateType( }; switch (repr) { .unpacked => { - try wip_nav.refType(Type.bool); + try wip_nav.refType(.bool); try uleb128(diw, if (opt_child_type.hasRuntimeBits(zcu)) opt_child_type.abiSize(zcu) else 0); }, .error_set => { - try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{ + try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{ .signedness = .unsigned, .bits = zcu.errorSetBits(), } }))); try uleb128(diw, 0); }, .pointer => { - try wip_nav.refType(Type.usize); + try wip_nav.refType(.usize); try uleb128(diw, 0); }, } @@ -3213,7 +3305,7 @@ fn updateType( { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("null"); - try wip_nav.refType(Type.null); + try wip_nav.refType(.null); try uleb128(diw, 0); } try uleb128(diw, @intFromEnum(AbbrevCode.null)); @@ -3233,8 +3325,8 @@ fn updateType( }, .anyframe_type => unreachable, .error_union_type => |error_union_type| { - const error_union_error_set_type = Type.fromInterned(error_union_type.error_set_type); - const error_union_payload_type = Type.fromInterned(error_union_type.payload_type); + const error_union_error_set_type: Type = .fromInterned(error_union_type.error_set_type); + const error_union_payload_type: Type = .fromInterned(error_union_type.payload_type); const error_union_error_set_offset, const error_union_payload_offset = switch (error_union_type.payload_type) { .generic_poison_type => .{ 0, 0 }, else => .{ @@ -3265,7 +3357,7 @@ fn updateType( { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("is_error"); - try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{ + try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{ .signedness = .unsigned, .bits = zcu.errorSetBits(), } }))); @@ -3363,24 +3455,39 @@ fn updateType( var field_byte_offset: u64 = 0; for (0..tuple_type.types.len) |field_index| { const comptime_value = tuple_type.values.get(ip)[field_index]; - try wip_nav.abbrevCode(if (comptime_value != .none) .struct_field_comptime else .struct_field); + const field_type: Type = .fromInterned(tuple_type.types.get(ip)[field_index]); + const has_runtime_bits, const has_comptime_state = switch (comptime_value) { + .none => .{ false, false }, + else => .{ + field_type.hasRuntimeBits(zcu), + field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null, + }, + }; + try wip_nav.abbrevCode(if (has_runtime_bits and has_comptime_state) + .struct_field_comptime_runtime_bits_comptime_state + else if (has_comptime_state) + .struct_field_comptime_comptime_state + else if (has_runtime_bits) + .struct_field_comptime_runtime_bits + else if (comptime_value != .none) + .struct_field_comptime + else + .struct_field); { - var name_buf: [32]u8 = undefined; - const field_name = std.fmt.bufPrint(&name_buf, "{d}", .{field_index}) catch unreachable; + var field_name_buf: [std.fmt.count("{d}", .{std.math.maxInt(u32)})]u8 = undefined; + const field_name = std.fmt.bufPrint(&field_name_buf, "{d}", .{field_index}) catch unreachable; try wip_nav.strp(field_name); } - const field_type = Type.fromInterned(tuple_type.types.get(ip)[field_index]); try wip_nav.refType(field_type); - if (comptime_value != .none) try wip_nav.blockValue( - src_loc, - Value.fromInterned(comptime_value), - ) else { + if (comptime_value == .none) { const field_align = field_type.abiAlignment(zcu); field_byte_offset = field_align.forward(field_byte_offset); try uleb128(diw, field_byte_offset); try uleb128(diw, field_type.abiAlignment(zcu).toByteUnits().?); field_byte_offset += field_type.abiSize(zcu); } + if (has_runtime_bits) try wip_nav.blockValue(src_loc, .fromInterned(comptime_value)); + if (has_comptime_state) try wip_nav.refValue(.fromInterned(comptime_value)); } try uleb128(diw, @intFromEnum(AbbrevCode.null)); }, @@ -3388,7 +3495,7 @@ fn updateType( const loaded_enum = ip.loadEnumType(type_index); try wip_nav.abbrevCode(if (loaded_enum.names.len > 0) .enum_type else .empty_enum_type); try wip_nav.strp(name); - try wip_nav.refType(Type.fromInterned(loaded_enum.tag_ty)); + try wip_nav.refType(.fromInterned(loaded_enum.tag_ty)); for (0..loaded_enum.names.len) |field_index| { try wip_nav.enumConstValue(loaded_enum, .{ .sdata = .signed_enum_field, @@ -3469,10 +3576,10 @@ fn updateType( }; }; try diw.writeByte(@intFromEnum(cc)); - try wip_nav.refType(Type.fromInterned(func_type.return_type)); + try wip_nav.refType(.fromInterned(func_type.return_type)); for (0..func_type.param_types.len) |param_index| { try wip_nav.abbrevCode(.func_type_param); - try wip_nav.refType(Type.fromInterned(func_type.param_types.get(ip)[param_index])); + try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index])); } if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args); if (!is_nullary) try uleb128(diw, @intFromEnum(AbbrevCode.null)); @@ -3480,7 +3587,7 @@ fn updateType( .error_set_type => |error_set_type| { try wip_nav.abbrevCode(if (error_set_type.names.len > 0) .enum_type else .empty_enum_type); try wip_nav.strp(name); - try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{ + try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{ .signedness = .unsigned, .bits = zcu.errorSetBits(), } }))); @@ -3495,7 +3602,7 @@ fn updateType( .inferred_error_set_type => |func| { try wip_nav.abbrevCode(.inferred_error_set_type); try wip_nav.strp(name); - try wip_nav.refType(Type.fromInterned(switch (ip.funcIesResolvedUnordered(func)) { + try wip_nav.refType(.fromInterned(switch (ip.funcIesResolvedUnordered(func)) { .none => .anyerror_type, else => |ies| ies, })); @@ -3526,10 +3633,378 @@ fn updateType( try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); } +fn updateLazyValue( + dwarf: *Dwarf, + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + value_index: InternPool.Index, + pending_lazy: *std.ArrayListUnmanaged(InternPool.Index), +) UpdateError!void { + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + log.debug("updateLazyValue({})", .{Value.fromInterned(value_index).fmtValue(pt)}); + var wip_nav: WipNav = .{ + .dwarf = dwarf, + .pt = pt, + .unit = .main, + .entry = dwarf.values.get(value_index).?, + .any_children = false, + .func = .none, + .func_sym_index = undefined, + .func_high_pc = undefined, + .blocks = undefined, + .cfi = undefined, + .debug_frame = .{}, + .debug_info = .{}, + .debug_line = .{}, + .debug_loclists = .{}, + .pending_lazy = pending_lazy.*, + }; + defer { + pending_lazy.* = wip_nav.pending_lazy; + wip_nav.pending_lazy = .{}; + wip_nav.deinit(); + } + const diw = wip_nav.debug_info.writer(dwarf.gpa); + var big_int_space: Value.BigIntSpace = undefined; + switch (ip.indexToKey(value_index)) { + .int_type, + .ptr_type, + .array_type, + .vector_type, + .opt_type, + .anyframe_type, + .error_union_type, + .simple_type, + .struct_type, + .tuple_type, + .union_type, + .opaque_type, + .enum_type, + .func_type, + .error_set_type, + .inferred_error_set_type, + => unreachable, // already handled + .undef => |ty| { + try wip_nav.abbrevCode(.aggregate_comptime_value); + try wip_nav.refType(.fromInterned(ty)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); + }, + .simple_value => unreachable, // opv state + .variable, .@"extern" => unreachable, // not a value + .func => unreachable, // already handled + .int => |int| { + try wip_nav.bigIntConstValue(.{ + .sdata = .sdata_comptime_value, + .udata = .udata_comptime_value, + .block = .block_comptime_value, + }, .fromInterned(int.ty), Value.fromInterned(value_index).toBigInt(&big_int_space, zcu)); + try wip_nav.refType(.fromInterned(int.ty)); + }, + .err => |err| { + try wip_nav.abbrevCode(.udata_comptime_value); + try wip_nav.refType(.fromInterned(err.ty)); + try uleb128(diw, try pt.getErrorValue(err.name)); + }, + .error_union => |error_union| { + try wip_nav.abbrevCode(.aggregate_comptime_value); + const err_abi_size = std.math.divCeil(u17, zcu.errorSetBits(), 8) catch unreachable; + const err_value = switch (error_union.val) { + .err_name => |err_name| try pt.getErrorValue(err_name), + .payload => 0, + }; + { + try wip_nav.abbrevCode(.comptime_value_field_runtime_bits); + try wip_nav.strp("is_error"); + try uleb128(diw, err_abi_size); + dwarf.writeInt(try wip_nav.debug_info.addManyAsSlice(dwarf.gpa, err_abi_size), err_value); + } + payload_field: switch (error_union.val) { + .err_name => {}, + .payload => |payload_val| { + const payload_type: Type = .fromInterned(ip.typeOf(payload_val)); + const has_runtime_bits = payload_type.hasRuntimeBits(zcu); + const has_comptime_state = payload_type.comptimeOnly(zcu) and try payload_type.onePossibleValue(pt) == null; + try wip_nav.abbrevCode(if (has_comptime_state) + .comptime_value_field_comptime_state + else if (has_runtime_bits) + .comptime_value_field_runtime_bits + else + break :payload_field); + try wip_nav.strp("value"); + if (has_comptime_state) + try wip_nav.refValue(.fromInterned(payload_val)) + else + try wip_nav.blockValue(src_loc, .fromInterned(payload_val)); + }, + } + { + try wip_nav.abbrevCode(.comptime_value_field_runtime_bits); + try wip_nav.strp("error"); + try uleb128(diw, err_abi_size); + dwarf.writeInt(try wip_nav.debug_info.addManyAsSlice(dwarf.gpa, err_abi_size), err_value); + } + switch (error_union.val) { + .err_name => {}, + .payload => |payload| { + _ = payload; + try wip_nav.abbrevCode(.aggregate_comptime_value); + }, + } + try wip_nav.refType(.fromInterned(error_union.ty)); + try uleb128(diw, @intFromEnum(AbbrevCode.null)); + }, + .enum_literal => |enum_literal| { + try wip_nav.abbrevCode(.string_comptime_value); + try wip_nav.strp(enum_literal.toSlice(ip)); + try wip_nav.refType(.enum_literal); + }, + .enum_tag => |enum_tag| { + const int = ip.indexToKey(enum_tag.int).int; + try wip_nav.bigIntConstValue(.{ + .sdata = .sdata_comptime_value, + .udata = .udata_comptime_value, + .block = .block_comptime_value, + }, .fromInterned(int.ty), Value.fromInterned(value_index).toBigInt(&big_int_space, zcu)); + try wip_nav.refType(.fromInterned(enum_tag.ty)); + }, + .empty_enum_value => unreachable, + .float => |float| { + switch (float.storage) { + .f16 => |f16_val| { + try wip_nav.abbrevCode(.data2_comptime_value); + try diw.writeInt(u16, @bitCast(f16_val), dwarf.endian); + }, + .f32 => |f32_val| { + try wip_nav.abbrevCode(.data4_comptime_value); + try diw.writeInt(u32, @bitCast(f32_val), dwarf.endian); + }, + .f64 => |f64_val| { + try wip_nav.abbrevCode(.data8_comptime_value); + try diw.writeInt(u64, @bitCast(f64_val), dwarf.endian); + }, + .f80 => |f80_val| { + try wip_nav.abbrevCode(.block_comptime_value); + try uleb128(diw, @divExact(80, 8)); + try diw.writeInt(u80, @bitCast(f80_val), dwarf.endian); + }, + .f128 => |f128_val| { + try wip_nav.abbrevCode(.data16_comptime_value); + try diw.writeInt(u128, @bitCast(f128_val), dwarf.endian); + }, + } + try wip_nav.refType(.fromInterned(float.ty)); + }, + .ptr => |ptr| { + location: { + var base_addr = ptr.base_addr; + var byte_offset = ptr.byte_offset; + const base_unit, const base_entry = while (true) { + const base_ptr = base_ptr: switch (base_addr) { + .nav => |nav_index| break try wip_nav.getNavEntry(nav_index), + .comptime_alloc, .comptime_field => unreachable, + .uav => |uav| { + const uav_ty: Type = .fromInterned(ip.typeOf(uav.val)); + if (try uav_ty.onePossibleValue(pt)) |_| { + try wip_nav.abbrevCode(.udata_comptime_value); + try uleb128(diw, ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment.toByteUnits() orelse + uav_ty.abiAlignment(zcu).toByteUnits().?); + break :location; + } else break try wip_nav.getValueEntry(.fromInterned(uav.val)); + }, + .int => { + try wip_nav.abbrevCode(.udata_comptime_value); + try uleb128(diw, byte_offset); + break :location; + }, + .eu_payload => |eu_ptr| { + const base_ptr = ip.indexToKey(eu_ptr).ptr; + byte_offset += codegen.errUnionPayloadOffset(.fromInterned(ip.indexToKey( + ip.indexToKey(base_ptr.ty).ptr_type.child, + ).error_union_type.payload_type), zcu); + break :base_ptr base_ptr; + }, + .opt_payload => |opt_ptr| ip.indexToKey(opt_ptr).ptr, + .field => unreachable, + .arr_elem => unreachable, + }; + base_addr = base_ptr.base_addr; + byte_offset += base_ptr.byte_offset; + }; + try wip_nav.abbrevCode(.location_comptime_value); + try wip_nav.infoExprloc(.{ .implicit_pointer = .{ + .unit = base_unit, + .entry = base_entry, + .offset = byte_offset, + } }); + } + try wip_nav.refType(.fromInterned(ptr.ty)); + }, + .slice => |slice| { + try wip_nav.abbrevCode(.aggregate_comptime_value); + try wip_nav.refType(.fromInterned(slice.ty)); + { + try wip_nav.abbrevCode(.comptime_value_field_comptime_state); + try wip_nav.strp("ptr"); + try wip_nav.refValue(.fromInterned(slice.ptr)); + } + { + try wip_nav.abbrevCode(.comptime_value_field_runtime_bits); + try wip_nav.strp("len"); + try wip_nav.blockValue(src_loc, .fromInterned(slice.len)); + } + try uleb128(diw, @intFromEnum(AbbrevCode.null)); + }, + .opt => |opt| { + const child_type: Type = .fromInterned(ip.indexToKey(opt.ty).opt_type); + try wip_nav.abbrevCode(.aggregate_comptime_value); + try wip_nav.refType(.fromInterned(opt.ty)); + { + try wip_nav.abbrevCode(.comptime_value_field_runtime_bits); + try wip_nav.strp("has_value"); + if (Type.fromInterned(opt.ty).optionalReprIsPayload(zcu)) { + try wip_nav.blockValue(src_loc, .fromInterned(opt.val)); + } else { + try uleb128(diw, 1); + try diw.writeByte(@intFromBool(opt.val != .none)); + } + } + if (opt.val != .none) child_field: { + const has_runtime_bits = child_type.hasRuntimeBits(zcu); + const has_comptime_state = child_type.comptimeOnly(zcu) and try child_type.onePossibleValue(pt) == null; + try wip_nav.abbrevCode(if (has_comptime_state) + .comptime_value_field_comptime_state + else if (has_runtime_bits) + .comptime_value_field_runtime_bits + else + break :child_field); + try wip_nav.strp("?"); + if (has_comptime_state) + try wip_nav.refValue(.fromInterned(opt.val)) + else + try wip_nav.blockValue(src_loc, .fromInterned(opt.val)); + } + try uleb128(diw, @intFromEnum(AbbrevCode.null)); + }, + .aggregate => |aggregate| { + try wip_nav.abbrevCode(.aggregate_comptime_value); + try wip_nav.refType(.fromInterned(aggregate.ty)); + switch (ip.indexToKey(aggregate.ty)) { + .struct_type => { + const loaded_struct_type = ip.loadStructType(aggregate.ty); + assert(loaded_struct_type.layout == .auto); + for (0..loaded_struct_type.field_types.len) |field_index| { + if (loaded_struct_type.fieldIsComptime(ip, field_index)) continue; + const field_type: Type = .fromInterned(loaded_struct_type.field_types.get(ip)[field_index]); + const has_runtime_bits = field_type.hasRuntimeBits(zcu); + const has_comptime_state = field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null; + try wip_nav.abbrevCode(if (has_comptime_state) + .comptime_value_field_comptime_state + else if (has_runtime_bits) + .comptime_value_field_runtime_bits + else + continue); + if (loaded_struct_type.fieldName(ip, field_index).unwrap()) |field_name| try wip_nav.strp(field_name.toSlice(ip)) else { + var field_name_buf: [std.fmt.count("{d}", .{std.math.maxInt(u32)})]u8 = undefined; + const field_name = std.fmt.bufPrint(&field_name_buf, "{d}", .{field_index}) catch unreachable; + try wip_nav.strp(field_name); + } + const field_value: Value = .fromInterned(switch (aggregate.storage) { + .bytes => unreachable, + .elems => |elems| elems[field_index], + .repeated_elem => |repeated_elem| repeated_elem, + }); + if (has_comptime_state) + try wip_nav.refValue(field_value) + else + try wip_nav.blockValue(src_loc, field_value); + } + }, + .tuple_type => |tuple_type| for (0..tuple_type.types.len) |field_index| { + if (tuple_type.values.get(ip)[field_index] != .none) continue; + const field_type: Type = .fromInterned(tuple_type.types.get(ip)[field_index]); + const has_runtime_bits = field_type.hasRuntimeBits(zcu); + const has_comptime_state = field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null; + try wip_nav.abbrevCode(if (has_comptime_state) + .comptime_value_field_comptime_state + else if (has_runtime_bits) + .comptime_value_field_runtime_bits + else + continue); + { + var field_name_buf: [std.fmt.count("{d}", .{std.math.maxInt(u32)})]u8 = undefined; + const field_name = std.fmt.bufPrint(&field_name_buf, "{d}", .{field_index}) catch unreachable; + try wip_nav.strp(field_name); + } + const field_value: Value = .fromInterned(switch (aggregate.storage) { + .bytes => unreachable, + .elems => |elems| elems[field_index], + .repeated_elem => |repeated_elem| repeated_elem, + }); + if (has_comptime_state) + try wip_nav.refValue(field_value) + else + try wip_nav.blockValue(src_loc, field_value); + }, + inline .array_type, .vector_type => |sequence_type| { + const child_type: Type = .fromInterned(sequence_type.child); + const has_runtime_bits = child_type.hasRuntimeBits(zcu); + const has_comptime_state = child_type.comptimeOnly(zcu) and try child_type.onePossibleValue(pt) == null; + for (switch (aggregate.storage) { + .bytes => unreachable, + .elems => |elems| elems, + .repeated_elem => |*repeated_elem| repeated_elem[0..1], + }) |elem| { + try wip_nav.abbrevCode(if (has_comptime_state) + .comptime_value_elem_comptime_state + else if (has_runtime_bits) + .comptime_value_elem_runtime_bits + else + break); + if (has_comptime_state) + try wip_nav.refValue(.fromInterned(elem)) + else + try wip_nav.blockValue(src_loc, .fromInterned(elem)); + } + }, + else => unreachable, + } + try uleb128(diw, @intFromEnum(AbbrevCode.null)); + }, + .un => |un| { + try wip_nav.abbrevCode(.aggregate_comptime_value); + try wip_nav.refType(.fromInterned(un.ty)); + field: { + const loaded_union_type = ip.loadUnionType(un.ty); + assert(loaded_union_type.flagsUnordered(ip).layout == .auto); + const field_index = zcu.unionTagFieldIndex(loaded_union_type, Value.fromInterned(un.tag)).?; + const field_ty: Type = .fromInterned(loaded_union_type.field_types.get(ip)[field_index]); + const field_name = loaded_union_type.loadTagType(ip).names.get(ip)[field_index]; + const has_runtime_bits = field_ty.hasRuntimeBits(zcu); + const has_comptime_state = field_ty.comptimeOnly(zcu) and try field_ty.onePossibleValue(pt) == null; + try wip_nav.abbrevCode(if (has_comptime_state) + .comptime_value_field_comptime_state + else if (has_runtime_bits) + .comptime_value_field_runtime_bits + else + break :field); + try wip_nav.strp(field_name.toSlice(ip)); + if (has_comptime_state) + try wip_nav.refValue(.fromInterned(un.val)) + else + try wip_nav.blockValue(src_loc, .fromInterned(un.val)); + } + try uleb128(diw, @intFromEnum(AbbrevCode.null)); + }, + .memoized_call => unreachable, // not a value + } + try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); +} + pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternPool.Index) UpdateError!void { const zcu = pt.zcu; const ip = &zcu.intern_pool; - const ty = Type.fromInterned(type_index); + const ty: Type = .fromInterned(type_index); const ty_src_loc = ty.srcLoc(zcu); log.debug("updateContainerType({}({d}))", .{ ty.fmt(pt), @intFromEnum(type_index) }); @@ -3554,7 +4029,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP .debug_info = .{}, .debug_line = .{}, .debug_loclists = .{}, - .pending_types = .{}, + .pending_lazy = .{}, }; defer wip_nav.deinit(); @@ -3572,31 +4047,53 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP const is_comptime = loaded_struct.fieldIsComptime(ip, field_index); const field_init = loaded_struct.fieldInit(ip, field_index); assert(!(is_comptime and field_init == .none)); + const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); + const has_runtime_bits, const has_comptime_state = switch (field_init) { + .none => .{ false, false }, + else => .{ + field_type.hasRuntimeBits(zcu), + field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null, + }, + }; try wip_nav.abbrevCode(if (is_comptime) - .struct_field_comptime + if (has_runtime_bits and has_comptime_state) + .struct_field_comptime_runtime_bits_comptime_state + else if (has_comptime_state) + .struct_field_comptime_comptime_state + else if (has_runtime_bits) + .struct_field_comptime_runtime_bits + else + .struct_field_comptime else if (field_init != .none) - .struct_field_default + if (has_runtime_bits and has_comptime_state) + .struct_field_default_runtime_bits_comptime_state + else if (has_comptime_state) + .struct_field_default_comptime_state + else if (has_runtime_bits) + .struct_field_default_runtime_bits + else + .struct_field_default else .struct_field); if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| try wip_nav.strp(field_name.toSlice(ip)) else { - const field_name = try std.fmt.allocPrint(dwarf.gpa, "{d}", .{field_index}); - defer dwarf.gpa.free(field_name); + var field_name_buf: [std.fmt.count("{d}", .{std.math.maxInt(u32)})]u8 = undefined; + const field_name = std.fmt.bufPrint(&field_name_buf, "{d}", .{field_index}) catch unreachable; try wip_nav.strp(field_name); } - const field_type = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); if (!is_comptime) { try uleb128(diw, loaded_struct.offsets.get(ip)[field_index]); try uleb128(diw, loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse field_type.abiAlignment(zcu).toByteUnits().?); } - if (field_init != .none) try wip_nav.blockValue(ty_src_loc, Value.fromInterned(field_init)); + if (has_runtime_bits) try wip_nav.blockValue(ty_src_loc, .fromInterned(field_init)); + if (has_comptime_state) try wip_nav.refValue(.fromInterned(field_init)); } try uleb128(diw, @intFromEnum(AbbrevCode.null)); } try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); - try wip_nav.flush(ty_src_loc); + try wip_nav.updateLazy(ty_src_loc); } else { { // Note that changes to ZIR instruction tracking only need to update this code @@ -3637,7 +4134,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP .debug_info = .{}, .debug_line = .{}, .debug_loclists = .{}, - .pending_types = .{}, + .pending_lazy = .{}, }; defer wip_nav.deinit(); const diw = wip_nav.debug_info.writer(dwarf.gpa); @@ -3658,25 +4155,47 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP const is_comptime = loaded_struct.fieldIsComptime(ip, field_index); const field_init = loaded_struct.fieldInit(ip, field_index); assert(!(is_comptime and field_init == .none)); + const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); + const has_runtime_bits, const has_comptime_state = switch (field_init) { + .none => .{ false, false }, + else => .{ + field_type.hasRuntimeBits(zcu), + field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null, + }, + }; try wip_nav.abbrevCode(if (is_comptime) - .struct_field_comptime + if (has_runtime_bits and has_comptime_state) + .struct_field_comptime_runtime_bits_comptime_state + else if (has_comptime_state) + .struct_field_comptime_comptime_state + else if (has_runtime_bits) + .struct_field_comptime_runtime_bits + else + .struct_field_comptime else if (field_init != .none) - .struct_field_default + if (has_runtime_bits and has_comptime_state) + .struct_field_default_runtime_bits_comptime_state + else if (has_comptime_state) + .struct_field_default_comptime_state + else if (has_runtime_bits) + .struct_field_default_runtime_bits + else + .struct_field_default else .struct_field); if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| try wip_nav.strp(field_name.toSlice(ip)) else { - const field_name = try std.fmt.allocPrint(dwarf.gpa, "{d}", .{field_index}); - defer dwarf.gpa.free(field_name); + var field_name_buf: [std.fmt.count("{d}", .{std.math.maxInt(u32)})]u8 = undefined; + const field_name = std.fmt.bufPrint(&field_name_buf, "{d}", .{field_index}) catch unreachable; try wip_nav.strp(field_name); } - const field_type = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); if (!is_comptime) { try uleb128(diw, loaded_struct.offsets.get(ip)[field_index]); try uleb128(diw, loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse field_type.abiAlignment(zcu).toByteUnits().?); } - if (field_init != .none) try wip_nav.blockValue(ty_src_loc, Value.fromInterned(field_init)); + if (has_runtime_bits) try wip_nav.blockValue(ty_src_loc, .fromInterned(field_init)); + if (has_comptime_state) try wip_nav.refValue(.fromInterned(field_init)); } try uleb128(diw, @intFromEnum(AbbrevCode.null)); } @@ -3684,12 +4203,12 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP .@"packed" => { try wip_nav.abbrevCode(if (loaded_struct.field_types.len > 0) .packed_struct_type else .empty_packed_struct_type); try wip_nav.strp(name); - try wip_nav.refType(Type.fromInterned(loaded_struct.backingIntTypeUnordered(ip))); + try wip_nav.refType(.fromInterned(loaded_struct.backingIntTypeUnordered(ip))); var field_bit_offset: u16 = 0; for (0..loaded_struct.field_types.len) |field_index| { try wip_nav.abbrevCode(.packed_struct_field); try wip_nav.strp(loaded_struct.fieldName(ip, field_index).unwrap().?.toSlice(ip)); - const field_type = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); + const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); try uleb128(diw, field_bit_offset); field_bit_offset += @intCast(field_type.bitSize(zcu)); @@ -3702,7 +4221,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP const loaded_enum = ip.loadEnumType(type_index); try wip_nav.abbrevCode(if (loaded_enum.names.len > 0) .enum_type else .empty_enum_type); try wip_nav.strp(name); - try wip_nav.refType(Type.fromInterned(loaded_enum.tag_ty)); + try wip_nav.refType(.fromInterned(loaded_enum.tag_ty)); for (0..loaded_enum.names.len) |field_index| { try wip_nav.enumConstValue(loaded_enum, .{ .sdata = .signed_enum_field, @@ -3732,7 +4251,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("tag"); - try wip_nav.refType(Type.fromInterned(loaded_union.enum_tag_ty)); + try wip_nav.refType(.fromInterned(loaded_union.enum_tag_ty)); try uleb128(diw, union_layout.tagOffset()); for (0..loaded_union.field_types.len) |field_index| { @@ -3744,7 +4263,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP { try wip_nav.abbrevCode(.struct_field); try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); - const field_type = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); + const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); try uleb128(diw, union_layout.payloadOffset()); try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse @@ -3757,7 +4276,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP } else for (0..loaded_union.field_types.len) |field_index| { try wip_nav.abbrevCode(.untagged_union_field); try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); - const field_type = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); + const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse field_type.abiAlignment(zcu).toByteUnits().?); @@ -3773,7 +4292,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP } try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.items); - try wip_nav.flush(ty_src_loc); + try wip_nav.updateLazy(ty_src_loc); } } @@ -3840,14 +4359,14 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { .debug_info = .{}, .debug_line = .{}, .debug_loclists = .{}, - .pending_types = .{}, + .pending_lazy = .{}, }; defer wip_nav.deinit(); const diw = wip_nav.debug_info.writer(dwarf.gpa); const global_error_set_names = ip.global_error_set.getNamesFromMainThread(); try wip_nav.abbrevCode(if (global_error_set_names.len > 0) .enum_type else .empty_enum_type); try wip_nav.strp("anyerror"); - try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{ + try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{ .signedness = .unsigned, .bits = zcu.errorSetBits(), } }))); @@ -3858,7 +4377,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { } if (global_error_set_names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null)); try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); - try wip_nav.flush(.unneeded); + try wip_nav.updateLazy(.unneeded); } { @@ -4244,6 +4763,9 @@ const AbbrevCode = enum { decl_union, decl_var, decl_const, + decl_const_runtime_bits, + decl_const_comptime_state, + decl_const_runtime_bits_comptime_state, decl_func, decl_empty_func, decl_func_generic, @@ -4259,7 +4781,13 @@ const AbbrevCode = enum { generated_field, struct_field, struct_field_default, + struct_field_default_runtime_bits, + struct_field_default_comptime_state, + struct_field_default_runtime_bits_comptime_state, struct_field_comptime, + struct_field_comptime_runtime_bits, + struct_field_comptime_comptime_state, + struct_field_comptime_runtime_bits_comptime_state, packed_struct_field, untagged_union_field, tagged_union, @@ -4296,6 +4824,20 @@ const AbbrevCode = enum { inlined_func, local_arg, local_var, + data2_comptime_value, + data4_comptime_value, + data8_comptime_value, + data16_comptime_value, + sdata_comptime_value, + udata_comptime_value, + block_comptime_value, + string_comptime_value, + location_comptime_value, + aggregate_comptime_value, + comptime_value_field_runtime_bits, + comptime_value_field_comptime_state, + comptime_value_elem_runtime_bits, + comptime_value_elem_comptime_state, const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_empty_func_generic)); @@ -4387,11 +4929,41 @@ const AbbrevCode = enum { .attrs = decl_abbrev_common_attrs ++ .{ .{ .linkage_name, .strp }, .{ .type, .ref_addr }, - .{ .const_value, .block }, .{ .alignment, .udata }, .{ .external, .flag }, }, }, + .decl_const_runtime_bits = .{ + .tag = .constant, + .attrs = decl_abbrev_common_attrs ++ .{ + .{ .linkage_name, .strp }, + .{ .type, .ref_addr }, + .{ .alignment, .udata }, + .{ .external, .flag }, + .{ .const_value, .block }, + }, + }, + .decl_const_comptime_state = .{ + .tag = .constant, + .attrs = decl_abbrev_common_attrs ++ .{ + .{ .linkage_name, .strp }, + .{ .type, .ref_addr }, + .{ .alignment, .udata }, + .{ .external, .flag }, + .{ .ZIG_comptime_value, .ref_addr }, + }, + }, + .decl_const_runtime_bits_comptime_state = .{ + .tag = .constant, + .attrs = decl_abbrev_common_attrs ++ .{ + .{ .linkage_name, .strp }, + .{ .type, .ref_addr }, + .{ .alignment, .udata }, + .{ .external, .flag }, + .{ .const_value, .block }, + .{ .ZIG_comptime_value, .ref_addr }, + }, + }, .decl_func = .{ .tag = .subprogram, .children = true, @@ -4509,6 +5081,15 @@ const AbbrevCode = enum { }, }, .struct_field_default = .{ + .tag = .member, + .attrs = &.{ + .{ .name, .strp }, + .{ .type, .ref_addr }, + .{ .data_member_location, .udata }, + .{ .alignment, .udata }, + }, + }, + .struct_field_default_runtime_bits = .{ .tag = .member, .attrs = &.{ .{ .name, .strp }, @@ -4518,7 +5099,36 @@ const AbbrevCode = enum { .{ .default_value, .block }, }, }, + .struct_field_default_comptime_state = .{ + .tag = .member, + .attrs = &.{ + .{ .name, .strp }, + .{ .type, .ref_addr }, + .{ .data_member_location, .udata }, + .{ .alignment, .udata }, + .{ .ZIG_comptime_default_value, .ref_addr }, + }, + }, + .struct_field_default_runtime_bits_comptime_state = .{ + .tag = .member, + .attrs = &.{ + .{ .name, .strp }, + .{ .type, .ref_addr }, + .{ .data_member_location, .udata }, + .{ .alignment, .udata }, + .{ .default_value, .block }, + .{ .ZIG_comptime_default_value, .ref_addr }, + }, + }, .struct_field_comptime = .{ + .tag = .member, + .attrs = &.{ + .{ .const_expr, .flag_present }, + .{ .name, .strp }, + .{ .type, .ref_addr }, + }, + }, + .struct_field_comptime_runtime_bits = .{ .tag = .member, .attrs = &.{ .{ .const_expr, .flag_present }, @@ -4527,6 +5137,25 @@ const AbbrevCode = enum { .{ .const_value, .block }, }, }, + .struct_field_comptime_comptime_state = .{ + .tag = .member, + .attrs = &.{ + .{ .const_expr, .flag_present }, + .{ .name, .strp }, + .{ .type, .ref_addr }, + .{ .ZIG_comptime_value, .ref_addr }, + }, + }, + .struct_field_comptime_runtime_bits_comptime_state = .{ + .tag = .member, + .attrs = &.{ + .{ .const_expr, .flag_present }, + .{ .name, .strp }, + .{ .type, .ref_addr }, + .{ .const_value, .block }, + .{ .ZIG_comptime_value, .ref_addr }, + }, + }, .packed_struct_field = .{ .tag = .member, .attrs = &.{ @@ -4804,6 +5433,102 @@ const AbbrevCode = enum { .{ .location, .exprloc }, }, }, + .data2_comptime_value = .{ + .tag = .ZIG_comptime_value, + .attrs = &.{ + .{ .const_value, .data2 }, + .{ .type, .ref_addr }, + }, + }, + .data4_comptime_value = .{ + .tag = .ZIG_comptime_value, + .attrs = &.{ + .{ .const_value, .data4 }, + .{ .type, .ref_addr }, + }, + }, + .data8_comptime_value = .{ + .tag = .ZIG_comptime_value, + .attrs = &.{ + .{ .const_value, .data8 }, + .{ .type, .ref_addr }, + }, + }, + .data16_comptime_value = .{ + .tag = .ZIG_comptime_value, + .attrs = &.{ + .{ .const_value, .data16 }, + .{ .type, .ref_addr }, + }, + }, + .sdata_comptime_value = .{ + .tag = .ZIG_comptime_value, + .attrs = &.{ + .{ .const_value, .sdata }, + .{ .type, .ref_addr }, + }, + }, + .udata_comptime_value = .{ + .tag = .ZIG_comptime_value, + .attrs = &.{ + .{ .const_value, .udata }, + .{ .type, .ref_addr }, + }, + }, + .block_comptime_value = .{ + .tag = .ZIG_comptime_value, + .attrs = &.{ + .{ .const_value, .block }, + .{ .type, .ref_addr }, + }, + }, + .string_comptime_value = .{ + .tag = .ZIG_comptime_value, + .attrs = &.{ + .{ .const_value, .strp }, + .{ .type, .ref_addr }, + }, + }, + .location_comptime_value = .{ + .tag = .ZIG_comptime_value, + .attrs = &.{ + .{ .location, .exprloc }, + .{ .type, .ref_addr }, + }, + }, + .aggregate_comptime_value = .{ + .tag = .ZIG_comptime_value, + .children = true, + .attrs = &.{ + .{ .type, .ref_addr }, + }, + }, + .comptime_value_field_runtime_bits = .{ + .tag = .member, + .attrs = &.{ + .{ .name, .strp }, + .{ .const_value, .block }, + }, + }, + .comptime_value_field_comptime_state = .{ + .tag = .member, + .attrs = &.{ + .{ .name, .strp }, + .{ .ZIG_comptime_value, .ref_addr }, + }, + }, + .comptime_value_elem_runtime_bits = .{ + .tag = .member, + .attrs = &.{ + .{ .const_value, .block }, + }, + }, + .comptime_value_elem_comptime_state = .{ + .tag = .member, + .attrs = &.{ + .{ .ZIG_comptime_value, .ref_addr }, + }, + }, .null = undefined, }); };