Commit 8c0628d0e2

Jacob Young <jacobly0@users.noreply.github.com>
2024-12-16 21:11:15
Dwarf: include comptime-only values in debug info
1 parent 5af7404
Changed files (5)
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.
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;
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 {
         }
     }
 
-    fn enumConstValue(
+    const AbbrevCodeForForm = struct {
+        sdata: AbbrevCode,
+        udata: AbbrevCode,
+        block: AbbrevCode,
+    };
+
+    fn bigIntConstValue(
         wip_nav: *WipNav,
-        loaded_enum: InternPool.LoadedEnumType,
-        abbrev_code: struct {
-            sdata: AbbrevCode,
-            udata: AbbrevCode,
-            block: AbbrevCode,
-        },
-        field_index: usize,
+        abbrev_code: AbbrevCodeForForm,
+        ty: Type,
+        big_int: std.math.big.int.Const,
     ) 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,
+        const signedness = switch (ty.toIntern()) {
+            .comptime_int_type, .comptime_float_type => .signed,
+            else => 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,
-                );
+        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 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);
-            },
+        } 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 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 enumConstValue(
+        wip_nav: *WipNav,
+        loaded_enum: InternPool.LoadedEnumType,
+        abbrev_code: AbbrevCodeForForm,
+        field_index: usize,
+    ) UpdateError!void {
+        const zcu = wip_nav.pt.zcu;
+        const ip = &zcu.intern_pool;
+        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 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,9 +4929,39 @@ const AbbrevCode = enum {
             .attrs = decl_abbrev_common_attrs ++ .{
                 .{ .linkage_name, .strp },
                 .{ .type, .ref_addr },
+                .{ .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 = .{
@@ -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,13 +5099,61 @@ 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 },
+                .{ .name, .strp },
+                .{ .type, .ref_addr },
+                .{ .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 = .{
@@ -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,
     });
 };
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`.
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 };