Commit f303c3943f

Andrew Kelley <andrew@ziglang.org>
2024-07-21 11:44:58
Revert "Merge pull request #20380 from tau-dev/master"
This reverts commit 397be0c9cc8156d38d1487a4c80210007033cbd0, reversing changes made to 18d412ab2fb7bda92f7bfbdf732849bbcd066c33. Caused test failures in master branch.
1 parent d484269
Changed files (5)
lib
src
test
cases
lib/std/debug.zig
@@ -2459,24 +2459,13 @@ pub const ModuleDebugInfo = switch (native_os) {
                 module,
                 relocated_address - coff_section.virtual_address,
             ) orelse "???";
-            // While DWARF gets us just the function's own name, the PDB
-            // stores it qualified with its namespace by the C++ `::`
-            // operator. We can strip that for consistency; the
-            // SymbolInfo will contain the line number, which is a more
-            // language-neutral way of distinguishing same-named symbols
-            // anyway.
-            const symbol_simple_name = if (mem.indexOf(u8, symbol_name, "::")) |cpp_namespace|
-                symbol_name[cpp_namespace + 2 ..]
-            else
-                symbol_name;
-
             const opt_line_info = try self.pdb.?.getLineNumberInfo(
                 module,
                 relocated_address - coff_section.virtual_address,
             );
 
             return SymbolInfo{
-                .symbol_name = symbol_simple_name,
+                .symbol_name = symbol_name,
                 .compile_unit_name = obj_basename,
                 .line_info = opt_line_info,
             };
src/codegen/llvm/Builder.zig
@@ -7651,8 +7651,6 @@ pub const Metadata = enum(u32) {
         composite_vector_type,
         derived_pointer_type,
         derived_member_type,
-        derived_typedef,
-        imported_declaration,
         subroutine_type,
         enumerator_unsigned,
         enumerator_signed_positive,
@@ -7698,8 +7696,6 @@ pub const Metadata = enum(u32) {
                 .composite_vector_type,
                 .derived_pointer_type,
                 .derived_member_type,
-                .derived_typedef,
-                .imported_declaration,
                 .subroutine_type,
                 .enumerator_unsigned,
                 .enumerator_signed_positive,
@@ -7816,7 +7812,6 @@ pub const Metadata = enum(u32) {
         producer: MetadataString,
         enums: Metadata,
         globals: Metadata,
-        imports: Metadata,
     };
 
     pub const Subprogram = struct {
@@ -7865,7 +7860,6 @@ pub const Metadata = enum(u32) {
             }
         };
 
-        scope: Metadata,
         file: Metadata,
         name: MetadataString,
         linkage_name: MetadataString,
@@ -7911,10 +7905,6 @@ pub const Metadata = enum(u32) {
         align_in_bits_lo: u32,
         align_in_bits_hi: u32,
         fields_tuple: Metadata,
-        flags: packed struct(u32) {
-            is_byref: bool,
-            pad: u31 = 0,
-        },
 
         pub fn bitSize(self: CompositeType) u64 {
             return @as(u64, self.size_in_bits_hi) << 32 | self.size_in_bits_lo;
@@ -7948,14 +7938,6 @@ pub const Metadata = enum(u32) {
         }
     };
 
-    pub const ImportedEntity = struct {
-        name: MetadataString,
-        file: Metadata,
-        scope: Metadata,
-        line: u32,
-        entity: Metadata,
-    };
-
     pub const SubroutineType = struct {
         types_tuple: Metadata,
     };
@@ -8008,6 +7990,10 @@ pub const Metadata = enum(u32) {
     };
 
     pub const GlobalVar = struct {
+        pub const Options = struct {
+            local: bool,
+        };
+
         name: MetadataString,
         linkage_name: MetadataString,
         file: Metadata,
@@ -8238,7 +8224,6 @@ pub const Metadata = enum(u32) {
                 DIBasicType,
                 DICompositeType,
                 DIDerivedType,
-                DIImportedEntity,
                 DISubroutineType,
                 DIEnumerator,
                 DISubrange,
@@ -9976,7 +9961,7 @@ pub fn printUnbuffered(
                         .enums = extra.enums,
                         .retainedTypes = null,
                         .globals = extra.globals,
-                        .imports = extra.imports,
+                        .imports = null,
                         .macros = null,
                         .dwoId = null,
                         .splitDebugInlining = false,
@@ -10000,7 +9985,7 @@ pub fn printUnbuffered(
                     try metadata_formatter.specialized(.@"distinct !", .DISubprogram, .{
                         .name = extra.name,
                         .linkageName = extra.linkage_name,
-                        .scope = extra.scope,
+                        .scope = extra.file,
                         .file = extra.file,
                         .line = extra.line,
                         .type = extra.ty,
@@ -10094,8 +10079,8 @@ pub fn printUnbuffered(
                             else => extra.name,
                         },
                         .scope = extra.scope,
-                        .file = extra.file,
-                        .line = extra.line,
+                        .file = null,
+                        .line = null,
                         .baseType = extra.underlying_type,
                         .size = extra.bitSize(),
                         .@"align" = extra.bitAlign(),
@@ -10116,18 +10101,15 @@ pub fn printUnbuffered(
                 },
                 .derived_pointer_type,
                 .derived_member_type,
-                .derived_typedef,
                 => |kind| {
                     const extra = self.metadataExtraData(Metadata.DerivedType, metadata_item.data);
                     try metadata_formatter.specialized(.@"!", .DIDerivedType, .{
                         .tag = @as(enum {
                             DW_TAG_pointer_type,
                             DW_TAG_member,
-                            DW_TAG_typedef,
                         }, switch (kind) {
                             .derived_pointer_type => .DW_TAG_pointer_type,
                             .derived_member_type => .DW_TAG_member,
-                            .derived_typedef => .DW_TAG_typedef,
                             else => unreachable,
                         }),
                         .name = switch (extra.name) {
@@ -10150,22 +10132,6 @@ pub fn printUnbuffered(
                         .annotations = null,
                     }, writer);
                 },
-                .imported_declaration => {
-                    const extra = self.metadataExtraData(Metadata.ImportedEntity, metadata_item.data);
-
-                    try metadata_formatter.specialized(.@"!", .DIImportedEntity, .{
-                        .tag = .DW_TAG_imported_declaration,
-                        .scope = extra.scope,
-                        .entity = extra.entity,
-                        .file = extra.file,
-                        .line = extra.line,
-                        .name = switch (extra.name) {
-                            .none => null,
-                            else => extra.name,
-                        },
-                        .elements = null,
-                    }, writer);
-                },
                 .subroutine_type => {
                     const extra = self.metadataExtraData(Metadata.SubroutineType, metadata_item.data);
                     try metadata_formatter.specialized(.@"!", .DISubroutineType, .{
@@ -10289,7 +10255,11 @@ pub fn printUnbuffered(
                         .file = extra.file,
                         .line = extra.line,
                         .type = extra.ty,
-                        .isLocal = kind != .global_var,
+                        .isLocal = switch (kind) {
+                            .global_var => false,
+                            .@"global_var local" => true,
+                            else => unreachable,
+                        },
                         .isDefinition = true,
                         .declaration = null,
                         .templateParams = null,
@@ -11642,17 +11612,7 @@ fn addMetadataExtraAssumeCapacity(self: *Builder, extra: anytype) Metadata.Item.
             u32 => value,
             MetadataString, Metadata, Variable.Index, Value => @intFromEnum(value),
             Metadata.DIFlags => @bitCast(value),
-            else => blk: {
-                switch (@typeInfo(field.type)) {
-                    .Struct => |s| {
-                        if (s.backing_integer == u32)
-                            break :blk @bitCast(value);
-                        @compileLog(s.layout, s.backing_integer);
-                    },
-                    else => {},
-                }
-                @compileError("bad field type: " ++ @typeName(field.type));
-            },
+            else => @compileError("bad field type: " ++ @typeName(field.type)),
         });
     }
     return result;
@@ -11691,7 +11651,7 @@ fn metadataExtraDataTrail(
             u32 => value,
             MetadataString, Metadata, Variable.Index, Value => @enumFromInt(value),
             Metadata.DIFlags => @bitCast(value),
-            else => @bitCast(value),
+            else => @compileError("bad field type: " ++ @typeName(field.type)),
         };
     return .{
         .data = result,
@@ -11780,17 +11740,15 @@ pub fn debugCompileUnit(
     producer: MetadataString,
     enums: Metadata,
     globals: Metadata,
-    imports: Metadata,
     options: Metadata.CompileUnit.Options,
 ) Allocator.Error!Metadata {
     try self.ensureUnusedMetadataCapacity(1, Metadata.CompileUnit, 0);
-    return self.debugCompileUnitAssumeCapacity(file, producer, enums, globals, imports, options);
+    return self.debugCompileUnitAssumeCapacity(file, producer, enums, globals, options);
 }
 
 pub fn debugSubprogram(
     self: *Builder,
     file: Metadata,
-    scope: Metadata,
     name: MetadataString,
     linkage_name: MetadataString,
     line: u32,
@@ -11802,7 +11760,6 @@ pub fn debugSubprogram(
     try self.ensureUnusedMetadataCapacity(1, Metadata.Subprogram, 0);
     return self.debugSubprogramAssumeCapacity(
         file,
-        scope,
         name,
         linkage_name,
         line,
@@ -11858,7 +11815,6 @@ pub fn debugStructType(
     size_in_bits: u64,
     align_in_bits: u64,
     fields_tuple: Metadata,
-    is_byref: bool,
 ) Allocator.Error!Metadata {
     try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0);
     return self.debugStructTypeAssumeCapacity(
@@ -11870,7 +11826,6 @@ pub fn debugStructType(
         size_in_bits,
         align_in_bits,
         fields_tuple,
-        is_byref,
     );
 }
 
@@ -11884,7 +11839,6 @@ pub fn debugUnionType(
     size_in_bits: u64,
     align_in_bits: u64,
     fields_tuple: Metadata,
-    is_byref: bool,
 ) Allocator.Error!Metadata {
     try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0);
     return self.debugUnionTypeAssumeCapacity(
@@ -11896,7 +11850,6 @@ pub fn debugUnionType(
         size_in_bits,
         align_in_bits,
         fields_tuple,
-        is_byref,
     );
 }
 
@@ -12020,53 +11973,6 @@ pub fn debugMemberType(
     );
 }
 
-pub fn debugTypedef(
-    self: *Builder,
-    name: MetadataString,
-    file: Metadata,
-    scope: Metadata,
-    line: u32,
-    underlying_type: Metadata,
-    align_in_bits: u64,
-) Allocator.Error!Metadata {
-    try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0);
-
-    assert(!self.strip);
-    return self.metadataSimpleAssumeCapacity(.derived_typedef, Metadata.DerivedType{
-        .name = name,
-        .file = file,
-        .scope = scope,
-        .line = line,
-        .underlying_type = underlying_type,
-        .size_in_bits_lo = 0,
-        .size_in_bits_hi = 0,
-        .align_in_bits_lo = @truncate(align_in_bits),
-        .align_in_bits_hi = @truncate(align_in_bits >> 32),
-        .offset_in_bits_lo = 0,
-        .offset_in_bits_hi = 0,
-    });
-}
-
-pub fn debugImportDeclaration(
-    self: *Builder,
-    name: MetadataString,
-    file: Metadata,
-    scope: Metadata,
-    line: u32,
-    entity: Metadata,
-) Allocator.Error!Metadata {
-    try self.ensureUnusedMetadataCapacity(1, Metadata.ImportedEntity, 0);
-
-    assert(!self.strip);
-    return self.metadataSimpleAssumeCapacity(.imported_declaration, Metadata.ImportedEntity{
-        .name = name,
-        .file = file,
-        .scope = scope,
-        .line = line,
-        .entity = entity,
-    });
-}
-
 pub fn debugSubroutineType(
     self: *Builder,
     types_tuple: Metadata,
@@ -12157,7 +12063,7 @@ pub fn debugGlobalVar(
     line: u32,
     ty: Metadata,
     variable: Variable.Index,
-    internal: bool,
+    options: Metadata.GlobalVar.Options,
 ) Allocator.Error!Metadata {
     try self.ensureUnusedMetadataCapacity(1, Metadata.GlobalVar, 0);
     return self.debugGlobalVarAssumeCapacity(
@@ -12168,7 +12074,7 @@ pub fn debugGlobalVar(
         line,
         ty,
         variable,
-        internal,
+        options,
     );
 }
 
@@ -12301,7 +12207,6 @@ pub fn debugCompileUnitAssumeCapacity(
     producer: MetadataString,
     enums: Metadata,
     globals: Metadata,
-    imports: Metadata,
     options: Metadata.CompileUnit.Options,
 ) Metadata {
     assert(!self.strip);
@@ -12312,7 +12217,6 @@ pub fn debugCompileUnitAssumeCapacity(
             .producer = producer,
             .enums = enums,
             .globals = globals,
-            .imports = imports,
         },
     );
 }
@@ -12320,7 +12224,6 @@ pub fn debugCompileUnitAssumeCapacity(
 fn debugSubprogramAssumeCapacity(
     self: *Builder,
     file: Metadata,
-    scope: Metadata,
     name: MetadataString,
     linkage_name: MetadataString,
     line: u32,
@@ -12334,7 +12237,6 @@ fn debugSubprogramAssumeCapacity(
         @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2)));
     return self.metadataDistinctAssumeCapacity(tag, Metadata.Subprogram{
         .file = file,
-        .scope = scope,
         .name = name,
         .linkage_name = linkage_name,
         .line = line,
@@ -12418,7 +12320,6 @@ fn debugStructTypeAssumeCapacity(
     size_in_bits: u64,
     align_in_bits: u64,
     fields_tuple: Metadata,
-    is_byref: bool,
 ) Metadata {
     assert(!self.strip);
     return self.debugCompositeTypeAssumeCapacity(
@@ -12431,7 +12332,6 @@ fn debugStructTypeAssumeCapacity(
         size_in_bits,
         align_in_bits,
         fields_tuple,
-        is_byref,
     );
 }
 
@@ -12445,7 +12345,6 @@ fn debugUnionTypeAssumeCapacity(
     size_in_bits: u64,
     align_in_bits: u64,
     fields_tuple: Metadata,
-    is_byref: bool,
 ) Metadata {
     assert(!self.strip);
     return self.debugCompositeTypeAssumeCapacity(
@@ -12458,7 +12357,6 @@ fn debugUnionTypeAssumeCapacity(
         size_in_bits,
         align_in_bits,
         fields_tuple,
-        is_byref,
     );
 }
 
@@ -12484,7 +12382,6 @@ fn debugEnumerationTypeAssumeCapacity(
         size_in_bits,
         align_in_bits,
         fields_tuple,
-        false, // is_byref
     );
 }
 
@@ -12510,7 +12407,6 @@ fn debugArrayTypeAssumeCapacity(
         size_in_bits,
         align_in_bits,
         fields_tuple,
-        size_in_bits > 0, // is_byref
     );
 }
 
@@ -12536,7 +12432,6 @@ fn debugVectorTypeAssumeCapacity(
         size_in_bits,
         align_in_bits,
         fields_tuple,
-        false,
     );
 }
 
@@ -12551,7 +12446,6 @@ fn debugCompositeTypeAssumeCapacity(
     size_in_bits: u64,
     align_in_bits: u64,
     fields_tuple: Metadata,
-    is_byref: bool,
 ) Metadata {
     assert(!self.strip);
     return self.metadataSimpleAssumeCapacity(tag, Metadata.CompositeType{
@@ -12565,7 +12459,6 @@ fn debugCompositeTypeAssumeCapacity(
         .align_in_bits_lo = @truncate(align_in_bits),
         .align_in_bits_hi = @truncate(align_in_bits >> 32),
         .fields_tuple = fields_tuple,
-        .flags = .{ .is_byref = is_byref },
     });
 }
 
@@ -12876,11 +12769,11 @@ fn debugGlobalVarAssumeCapacity(
     line: u32,
     ty: Metadata,
     variable: Variable.Index,
-    internal: bool,
+    options: Metadata.GlobalVar.Options,
 ) Metadata {
     assert(!self.strip);
     return self.metadataDistinctAssumeCapacity(
-        if (internal) .@"global_var local" else .global_var,
+        if (options.local) .@"global_var local" else .global_var,
         Metadata.GlobalVar{
             .name = name,
             .linkage_name = linkage_name,
@@ -13911,7 +13804,6 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
                             },
                             .enums = extra.enums,
                             .globals = extra.globals,
-                            .imports = extra.imports,
                         }, metadata_adapter);
                     },
                     .subprogram,
@@ -13926,7 +13818,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
                         const extra = self.metadataExtraData(Metadata.Subprogram, data);
 
                         try metadata_block.writeAbbrevAdapted(MetadataBlock.Subprogram{
-                            .scope = extra.scope,
+                            .scope = extra.file,
                             .name = extra.name,
                             .linkage_name = extra.linkage_name,
                             .file = extra.file,
@@ -14000,24 +13892,18 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
                             .underlying_type = extra.underlying_type,
                             .size_in_bits = extra.bitSize(),
                             .align_in_bits = extra.bitAlign(),
-                            .flags = .{
-                                .Vector = kind == .composite_vector_type,
-                                .EnumClass = kind == .composite_enumeration_type,
-                                .TypePassbyReference = extra.flags.is_byref,
-                            },
+                            .flags = if (kind == .composite_vector_type) .{ .Vector = true } else .{},
                             .elements = extra.fields_tuple,
                         }, metadata_adapter);
                     },
                     .derived_pointer_type,
                     .derived_member_type,
-                    .derived_typedef,
                     => |kind| {
                         const extra = self.metadataExtraData(Metadata.DerivedType, data);
                         try metadata_block.writeAbbrevAdapted(MetadataBlock.DerivedType{
                             .tag = switch (kind) {
                                 .derived_pointer_type => DW.TAG.pointer_type,
                                 .derived_member_type => DW.TAG.member,
-                                .derived_typedef => DW.TAG.typedef,
                                 else => unreachable,
                             },
                             .name = extra.name,
@@ -14028,20 +13914,6 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
                             .size_in_bits = extra.bitSize(),
                             .align_in_bits = extra.bitAlign(),
                             .offset_in_bits = extra.bitOffset(),
-                            .flags = .{
-                                .StaticMember = false,
-                            },
-                        }, metadata_adapter);
-                    },
-                    .imported_declaration => {
-                        const extra = self.metadataExtraData(Metadata.ImportedEntity, data);
-                        try metadata_block.writeAbbrevAdapted(MetadataBlock.ImportedEntity{
-                            .tag = DW.TAG.imported_declaration,
-                            .scope = extra.scope,
-                            .entity = extra.entity,
-                            .line = extra.line,
-                            .name = extra.name,
-                            .file = extra.file,
                         }, metadata_adapter);
                     },
                     .subroutine_type => {
src/codegen/llvm/ir.zig
@@ -649,7 +649,6 @@ pub const MetadataBlock = struct {
         BasicType,
         CompositeType,
         DerivedType,
-        ImportedEntity,
         SubroutineType,
         Enumerator,
         Subrange,
@@ -695,7 +694,7 @@ pub const MetadataBlock = struct {
         pub const ops = [_]AbbrevOp{
             .{ .literal = 20 },
             .{ .literal = 1 }, // is distinct
-            .{ .literal = std.dwarf.LANG.C_plus_plus_11 }, // source language
+            .{ .literal = std.dwarf.LANG.C99 }, // source language
             MetadataAbbrev, // file
             MetadataAbbrev, // producer
             .{ .fixed = 1 }, // isOptimized
@@ -707,7 +706,7 @@ pub const MetadataBlock = struct {
             .{ .literal = 0 }, // retained types
             .{ .literal = 0 }, // subprograms
             MetadataAbbrev, // globals
-            MetadataAbbrev, // imported entities
+            .{ .literal = 0 }, // imported entities
             .{ .literal = 0 }, // DWO ID
             .{ .literal = 0 }, // macros
             .{ .literal = 0 }, // split debug inlining
@@ -723,7 +722,6 @@ pub const MetadataBlock = struct {
         is_optimized: bool,
         enums: Builder.Metadata,
         globals: Builder.Metadata,
-        imports: Builder.Metadata,
     };
 
     pub const Subprogram = struct {
@@ -865,7 +863,7 @@ pub const MetadataBlock = struct {
             .{ .vbr = 6 }, // size in bits
             .{ .vbr = 6 }, // align in bits
             .{ .vbr = 6 }, // offset in bits
-            .{ .fixed = 32 }, // flags
+            .{ .literal = 0 }, // flags
             .{ .literal = 0 }, // extra data
         };
 
@@ -878,28 +876,6 @@ pub const MetadataBlock = struct {
         size_in_bits: u64,
         align_in_bits: u64,
         offset_in_bits: u64,
-        flags: Builder.Metadata.DIFlags,
-    };
-
-    pub const ImportedEntity = struct {
-        pub const ops = [_]AbbrevOp{
-            .{ .literal = 31 },
-            .{ .literal = 0 }, // is distinct
-            .{ .fixed = 32 }, // tag
-            MetadataAbbrev, // scope
-            MetadataAbbrev, // entity
-            LineAbbrev, // line
-            MetadataAbbrev, // name
-            MetadataAbbrev, // file
-            .{ .literal = 0 }, // elements
-        };
-
-        tag: u32,
-        scope: Builder.Metadata,
-        entity: Builder.Metadata,
-        line: u32,
-        name: Builder.MetadataString,
-        file: Builder.Metadata,
     };
 
     pub const SubroutineType = struct {
src/codegen/llvm.zig
@@ -806,17 +806,14 @@ pub const Object = struct {
 
     debug_enums_fwd_ref: Builder.Metadata,
     debug_globals_fwd_ref: Builder.Metadata,
-    debug_imports_fwd_ref: Builder.Metadata,
 
     debug_enums: std.ArrayListUnmanaged(Builder.Metadata),
     debug_globals: std.ArrayListUnmanaged(Builder.Metadata),
-    debug_imports: std.ArrayListUnmanaged(Builder.Metadata),
 
     debug_file_map: std.AutoHashMapUnmanaged(*const Zcu.File, Builder.Metadata),
     debug_type_map: std.AutoHashMapUnmanaged(Type, Builder.Metadata),
 
-    // The value says whether this namespace's type is runtime-required.
-    debug_unresolved_namespace_scopes: std.AutoArrayHashMapUnmanaged(Type, bool),
+    debug_unresolved_namespace_scopes: std.AutoArrayHashMapUnmanaged(InternPool.NamespaceIndex, Builder.Metadata),
 
     target: std.Target,
     /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function,
@@ -881,7 +878,7 @@ pub const Object = struct {
 
         builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }});
 
-        const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref, const debug_imports_fwd_ref =
+        const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref =
             if (!builder.strip)
         debug_info: {
             // We fully resolve all paths at this point to avoid lack of
@@ -913,7 +910,6 @@ pub const Object = struct {
 
             const debug_enums_fwd_ref = try builder.debugForwardReference();
             const debug_globals_fwd_ref = try builder.debugForwardReference();
-            const debug_imports_fwd_ref = try builder.debugForwardReference();
 
             const debug_compile_unit = try builder.debugCompileUnit(
                 debug_file,
@@ -926,7 +922,6 @@ pub const Object = struct {
                 }),
                 debug_enums_fwd_ref,
                 debug_globals_fwd_ref,
-                debug_imports_fwd_ref,
                 .{ .optimized = comp.root_mod.optimize_mode != .Debug },
             );
 
@@ -982,8 +977,8 @@ pub const Object = struct {
             }
 
             try builder.debugNamed(try builder.metadataString("llvm.dbg.cu"), &.{debug_compile_unit});
-            break :debug_info .{ debug_compile_unit, debug_enums_fwd_ref, debug_globals_fwd_ref, debug_imports_fwd_ref };
-        } else .{.none} ** 4;
+            break :debug_info .{ debug_compile_unit, debug_enums_fwd_ref, debug_globals_fwd_ref };
+        } else .{.none} ** 3;
 
         const obj = try arena.create(Object);
         obj.* = .{
@@ -996,10 +991,8 @@ pub const Object = struct {
             .debug_compile_unit = debug_compile_unit,
             .debug_enums_fwd_ref = debug_enums_fwd_ref,
             .debug_globals_fwd_ref = debug_globals_fwd_ref,
-            .debug_imports_fwd_ref = debug_imports_fwd_ref,
             .debug_enums = .{},
             .debug_globals = .{},
-            .debug_imports = .{},
             .debug_file_map = .{},
             .debug_type_map = .{},
             .debug_unresolved_namespace_scopes = .{},
@@ -1141,7 +1134,18 @@ pub const Object = struct {
             try self.genModuleLevelAssembly();
 
             if (!self.builder.strip) {
-                try self.genNamespaces();
+                {
+                    var i: usize = 0;
+                    while (i < self.debug_unresolved_namespace_scopes.count()) : (i += 1) {
+                        const namespace_index = self.debug_unresolved_namespace_scopes.keys()[i];
+                        const fwd_ref = self.debug_unresolved_namespace_scopes.values()[i];
+
+                        const namespace = zcu.namespacePtr(namespace_index);
+                        const debug_type = try self.lowerDebugType(namespace.getType(zcu));
+
+                        self.builder.debugForwardReferenceSetType(fwd_ref, debug_type);
+                    }
+                }
 
                 self.builder.debugForwardReferenceSetType(
                     self.debug_enums_fwd_ref,
@@ -1152,11 +1156,6 @@ pub const Object = struct {
                     self.debug_globals_fwd_ref,
                     try self.builder.debugTuple(self.debug_globals.items),
                 );
-
-                self.builder.debugForwardReferenceSetType(
-                    self.debug_imports_fwd_ref,
-                    try self.builder.debugTuple(self.debug_imports.items),
-                );
             }
         }
 
@@ -1636,19 +1635,15 @@ pub const Object = struct {
 
         const file, const subprogram = if (!wip.strip) debug_info: {
             const file = try o.getDebugFile(file_scope);
-            const scope = try o.lowerDebugType(zcu.declPtr(namespace.decl_index).val.toType(), false);
 
             const line_number = decl.navSrcLine(zcu) + 1;
             const is_internal_linkage = decl.val.getExternFunc(zcu) == null;
-            const debug_decl_type = try o.lowerDebugType(decl.typeOf(zcu), true);
-            const decl_name = try o.builder.metadataString(decl.name.toSlice(ip));
-            const link_name = try o.builder.metadataStringFromStrtabString(function_index.name(&o.builder));
+            const debug_decl_type = try o.lowerDebugType(decl.typeOf(zcu));
 
             const subprogram = try o.builder.debugSubprogram(
                 file,
-                scope,
-                decl_name,
-                link_name,
+                try o.builder.metadataString(decl.name.toSlice(ip)),
+                try o.builder.metadataStringFromStrtabString(function_index.name(&o.builder)),
                 line_number,
                 line_number + func.lbrace_line,
                 debug_decl_type,
@@ -1665,7 +1660,6 @@ pub const Object = struct {
                 },
                 o.debug_compile_unit,
             );
-
             function_index.setSubprogram(subprogram, &o.builder);
             break :debug_info .{ file, subprogram };
         } else .{.none} ** 2;
@@ -1913,7 +1907,6 @@ pub const Object = struct {
     pub fn lowerDebugType(
         o: *Object,
         ty: Type,
-        required_by_runtime: bool,
     ) Allocator.Error!Builder.Metadata {
         assert(!o.builder.strip);
 
@@ -1923,13 +1916,7 @@ pub const Object = struct {
         const zcu = pt.zcu;
         const ip = &zcu.intern_pool;
 
-        if (o.debug_type_map.get(ty)) |debug_type| {
-            if (required_by_runtime) {
-                if (o.debug_unresolved_namespace_scopes.getEntry(ty)) |entry|
-                    entry.value_ptr.* = true;
-            }
-            return debug_type;
-        }
+        if (o.debug_type_map.get(ty)) |debug_type| return debug_type;
 
         switch (ty.zigTypeTag(zcu)) {
             .Void,
@@ -1944,9 +1931,10 @@ pub const Object = struct {
             },
             .Int => {
                 const info = ty.intInfo(zcu);
-                const int_name = try o.allocTypeName(ty);
-                defer gpa.free(int_name);
-                const builder_name = try o.builder.metadataString(int_name);
+                assert(info.bits != 0);
+                const name = try o.allocTypeName(ty);
+                defer gpa.free(name);
+                const builder_name = try o.builder.metadataString(name);
                 const debug_bits = ty.abiSize(pt) * 8; // lldb cannot handle non-byte sized types
                 const debug_int_type = switch (info.signedness) {
                     .signed => try o.builder.debugSignedType(builder_name, debug_bits),
@@ -1955,12 +1943,68 @@ pub const Object = struct {
                 try o.debug_type_map.put(gpa, ty, debug_int_type);
                 return debug_int_type;
             },
+            .Enum => {
+                const owner_decl_index = ty.getOwnerDecl(zcu);
+                const owner_decl = zcu.declPtr(owner_decl_index);
+
+                if (!ty.hasRuntimeBitsIgnoreComptime(pt)) {
+                    const debug_enum_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
+                    try o.debug_type_map.put(gpa, ty, debug_enum_type);
+                    return debug_enum_type;
+                }
+
+                const enum_type = ip.loadEnumType(ty.toIntern());
+
+                const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len);
+                defer gpa.free(enumerators);
+
+                const int_ty = Type.fromInterned(enum_type.tag_ty);
+                const int_info = ty.intInfo(zcu);
+                assert(int_info.bits != 0);
+
+                for (enum_type.names.get(ip), 0..) |field_name_ip, i| {
+                    var bigint_space: Value.BigIntSpace = undefined;
+                    const bigint = if (enum_type.values.len != 0)
+                        Value.fromInterned(enum_type.values.get(ip)[i]).toBigInt(&bigint_space, pt)
+                    else
+                        std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();
+
+                    enumerators[i] = try o.builder.debugEnumerator(
+                        try o.builder.metadataString(field_name_ip.toSlice(ip)),
+                        int_info.signedness == .unsigned,
+                        int_info.bits,
+                        bigint,
+                    );
+                }
+
+                const file_scope = zcu.namespacePtr(owner_decl.src_namespace).fileScope(zcu);
+                const file = try o.getDebugFile(file_scope);
+                const scope = try o.namespaceToDebugScope(owner_decl.src_namespace);
+
+                const name = try o.allocTypeName(ty);
+                defer gpa.free(name);
+
+                const debug_enum_type = try o.builder.debugEnumerationType(
+                    try o.builder.metadataString(name),
+                    file,
+                    scope,
+                    owner_decl.typeSrcLine(zcu) + 1, // Line
+                    try o.lowerDebugType(int_ty),
+                    ty.abiSize(pt) * 8,
+                    (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
+                    try o.builder.debugTuple(enumerators),
+                );
+
+                try o.debug_type_map.put(gpa, ty, debug_enum_type);
+                try o.debug_enums.append(gpa, debug_enum_type);
+                return debug_enum_type;
+            },
             .Float => {
                 const bits = ty.floatBits(target);
-                const float_name = try o.allocTypeName(ty);
-                defer gpa.free(float_name);
+                const name = try o.allocTypeName(ty);
+                defer gpa.free(name);
                 const debug_float_type = try o.builder.debugFloatType(
-                    try o.builder.metadataString(float_name),
+                    try o.builder.metadataString(name),
                     bits,
                 );
                 try o.debug_type_map.put(gpa, ty, debug_float_type);
@@ -2002,7 +2046,7 @@ pub const Object = struct {
                             },
                         },
                     });
-                    const debug_ptr_type = try o.lowerDebugType(bland_ptr_ty, required_by_runtime);
+                    const debug_ptr_type = try o.lowerDebugType(bland_ptr_ty);
                     try o.debug_type_map.put(gpa, ty, debug_ptr_type);
                     return debug_ptr_type;
                 }
@@ -2018,7 +2062,6 @@ pub const Object = struct {
 
                     const name = try o.allocTypeName(ty);
                     defer gpa.free(name);
-
                     const line = 0;
 
                     const ptr_size = ptr_ty.abiSize(pt);
@@ -2033,7 +2076,7 @@ pub const Object = struct {
                         .none, // File
                         debug_fwd_ref,
                         0, // Line
-                        try o.lowerDebugType(ptr_ty, required_by_runtime),
+                        try o.lowerDebugType(ptr_ty),
                         ptr_size * 8,
                         (ptr_align.toByteUnits() orelse 0) * 8,
                         0, // Offset
@@ -2044,7 +2087,7 @@ pub const Object = struct {
                         .none, // File
                         debug_fwd_ref,
                         0, // Line
-                        try o.lowerDebugType(len_ty, required_by_runtime),
+                        try o.lowerDebugType(len_ty),
                         len_size * 8,
                         (len_align.toByteUnits() orelse 0) * 8,
                         len_offset * 8,
@@ -2062,7 +2105,6 @@ pub const Object = struct {
                             debug_ptr_type,
                             debug_len_type,
                         }),
-                        isByRef(ty, pt),
                     );
 
                     o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_slice_type);
@@ -2074,7 +2116,7 @@ pub const Object = struct {
                     return debug_slice_type;
                 }
 
-                const debug_elem_ty = try o.lowerDebugType(Type.fromInterned(ptr_info.child), required_by_runtime);
+                const debug_elem_ty = try o.lowerDebugType(Type.fromInterned(ptr_info.child));
 
                 const name = try o.allocTypeName(ty);
                 defer gpa.free(name);
@@ -2098,13 +2140,41 @@ pub const Object = struct {
 
                 return debug_ptr_type;
             },
+            .Opaque => {
+                if (ty.toIntern() == .anyopaque_type) {
+                    const debug_opaque_type = try o.builder.debugSignedType(
+                        try o.builder.metadataString("anyopaque"),
+                        0,
+                    );
+                    try o.debug_type_map.put(gpa, ty, debug_opaque_type);
+                    return debug_opaque_type;
+                }
+
+                const name = try o.allocTypeName(ty);
+                defer gpa.free(name);
+                const owner_decl_index = ty.getOwnerDecl(zcu);
+                const owner_decl = zcu.declPtr(owner_decl_index);
+                const file_scope = zcu.namespacePtr(owner_decl.src_namespace).fileScope(zcu);
+                const debug_opaque_type = try o.builder.debugStructType(
+                    try o.builder.metadataString(name),
+                    try o.getDebugFile(file_scope),
+                    try o.namespaceToDebugScope(owner_decl.src_namespace),
+                    owner_decl.typeSrcLine(zcu) + 1, // Line
+                    .none, // Underlying type
+                    0, // Size
+                    0, // Align
+                    .none, // Fields
+                );
+                try o.debug_type_map.put(gpa, ty, debug_opaque_type);
+                return debug_opaque_type;
+            },
             .Array => {
                 const debug_array_type = try o.builder.debugArrayType(
                     .none, // Name
                     .none, // File
                     .none, // Scope
                     0, // Line
-                    try o.lowerDebugType(ty.childType(zcu), required_by_runtime),
+                    try o.lowerDebugType(ty.childType(zcu)),
                     ty.abiSize(pt) * 8,
                     (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
                     try o.builder.debugTuple(&.{
@@ -2126,9 +2196,10 @@ pub const Object = struct {
                 const debug_elem_type = switch (elem_ty.zigTypeTag(zcu)) {
                     .Int => blk: {
                         const info = elem_ty.intInfo(zcu);
-                        const vec_name = try o.allocTypeName(ty);
-                        defer gpa.free(vec_name);
-                        const builder_name = try o.builder.metadataString(vec_name);
+                        assert(info.bits != 0);
+                        const name = try o.allocTypeName(ty);
+                        defer gpa.free(name);
+                        const builder_name = try o.builder.metadataString(name);
                         break :blk switch (info.signedness) {
                             .signed => try o.builder.debugSignedType(builder_name, info.bits),
                             .unsigned => try o.builder.debugUnsignedType(builder_name, info.bits),
@@ -2138,7 +2209,7 @@ pub const Object = struct {
                         try o.builder.metadataString("bool"),
                         1,
                     ),
-                    else => try o.lowerDebugType(ty.childType(zcu), required_by_runtime),
+                    else => try o.lowerDebugType(ty.childType(zcu)),
                 };
 
                 const debug_vector_type = try o.builder.debugVectorType(
@@ -2163,7 +2234,6 @@ pub const Object = struct {
             .Optional => {
                 const name = try o.allocTypeName(ty);
                 defer gpa.free(name);
-
                 const child_ty = ty.optionalChild(zcu);
                 if (!child_ty.hasRuntimeBitsIgnoreComptime(pt)) {
                     const debug_bool_type = try o.builder.debugBoolType(
@@ -2180,7 +2250,7 @@ pub const Object = struct {
                 try o.debug_type_map.put(gpa, ty, debug_fwd_ref);
 
                 if (ty.optionalReprIsPayload(zcu)) {
-                    const debug_optional_type = try o.lowerDebugType(child_ty, required_by_runtime);
+                    const debug_optional_type = try o.lowerDebugType(child_ty);
 
                     o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_optional_type);
 
@@ -2203,7 +2273,7 @@ pub const Object = struct {
                     .none, // File
                     debug_fwd_ref,
                     0, // Line
-                    try o.lowerDebugType(child_ty, required_by_runtime),
+                    try o.lowerDebugType(child_ty),
                     payload_size * 8,
                     (payload_align.toByteUnits() orelse 0) * 8,
                     0, // Offset
@@ -2214,7 +2284,7 @@ pub const Object = struct {
                     .none,
                     debug_fwd_ref,
                     0,
-                    try o.lowerDebugType(non_null_ty, required_by_runtime),
+                    try o.lowerDebugType(non_null_ty),
                     non_null_size * 8,
                     (non_null_align.toByteUnits() orelse 0) * 8,
                     non_null_offset * 8,
@@ -2232,7 +2302,6 @@ pub const Object = struct {
                         debug_data_type,
                         debug_some_type,
                     }),
-                    isByRef(ty, pt),
                 );
 
                 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_optional_type);
@@ -2247,7 +2316,7 @@ pub const Object = struct {
                 const payload_ty = ty.errorUnionPayload(zcu);
                 if (!payload_ty.hasRuntimeBitsIgnoreComptime(pt)) {
                     // TODO: Maybe remove?
-                    const debug_error_union_type = try o.lowerDebugType(Type.anyerror, required_by_runtime);
+                    const debug_error_union_type = try o.lowerDebugType(Type.anyerror);
                     try o.debug_type_map.put(gpa, ty, debug_error_union_type);
                     return debug_error_union_type;
                 }
@@ -2284,7 +2353,7 @@ pub const Object = struct {
                     .none, // File
                     debug_fwd_ref,
                     0, // Line
-                    try o.lowerDebugType(Type.anyerror, required_by_runtime),
+                    try o.lowerDebugType(Type.anyerror),
                     error_size * 8,
                     (error_align.toByteUnits() orelse 0) * 8,
                     error_offset * 8,
@@ -2294,7 +2363,7 @@ pub const Object = struct {
                     .none, // File
                     debug_fwd_ref,
                     0, // Line
-                    try o.lowerDebugType(payload_ty, required_by_runtime),
+                    try o.lowerDebugType(payload_ty),
                     payload_size * 8,
                     (payload_align.toByteUnits() orelse 0) * 8,
                     payload_offset * 8,
@@ -2309,7 +2378,6 @@ pub const Object = struct {
                     ty.abiSize(pt) * 8,
                     (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
                     try o.builder.debugTuple(&fields),
-                    isByRef(ty, pt),
                 );
 
                 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_error_union_type);
@@ -2325,483 +2393,383 @@ pub const Object = struct {
                 try o.debug_type_map.put(gpa, ty, debug_error_set);
                 return debug_error_set;
             },
-            .Fn => {
-                const fn_info = zcu.typeToFunc(ty).?;
-
-                var debug_param_types = std.ArrayList(Builder.Metadata).init(gpa);
-                defer debug_param_types.deinit();
-
-                try debug_param_types.ensureUnusedCapacity(3 + fn_info.param_types.len);
-
-                // Return type goes first.
-                if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(pt)) {
-                    const sret = firstParamSRet(fn_info, pt, target);
-                    const ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type);
-                    debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ret_ty, required_by_runtime));
-
-                    if (sret) {
-                        const ptr_ty = try pt.singleMutPtrType(Type.fromInterned(fn_info.return_type));
-                        debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty, required_by_runtime));
-                    }
-                } else {
-                    debug_param_types.appendAssumeCapacity(try o.lowerDebugType(Type.void, required_by_runtime));
-                }
-
-                if (Type.fromInterned(fn_info.return_type).isError(zcu) and
-                    zcu.comp.config.any_error_tracing)
-                {
-                    const ptr_ty = try pt.singleMutPtrType(try o.getStackTraceType());
-                    debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty, required_by_runtime));
-                }
-
-                for (0..fn_info.param_types.len) |i| {
-                    const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[i]);
-                    if (!param_ty.hasRuntimeBitsIgnoreComptime(pt)) continue;
+            .Struct => {
+                const name = try o.allocTypeName(ty);
+                defer gpa.free(name);
 
-                    if (isByRef(param_ty, pt)) {
-                        const ptr_ty = try pt.singleMutPtrType(param_ty);
-                        debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty, required_by_runtime));
-                    } else {
-                        debug_param_types.appendAssumeCapacity(try o.lowerDebugType(param_ty, required_by_runtime));
+                if (zcu.typeToPackedStruct(ty)) |struct_type| {
+                    const backing_int_ty = struct_type.backingIntTypeUnordered(ip);
+                    if (backing_int_ty != .none) {
+                        const info = Type.fromInterned(backing_int_ty).intInfo(zcu);
+                        const builder_name = try o.builder.metadataString(name);
+                        const debug_int_type = switch (info.signedness) {
+                            .signed => try o.builder.debugSignedType(builder_name, ty.abiSize(pt) * 8),
+                            .unsigned => try o.builder.debugUnsignedType(builder_name, ty.abiSize(pt) * 8),
+                        };
+                        try o.debug_type_map.put(gpa, ty, debug_int_type);
+                        return debug_int_type;
                     }
                 }
 
-                const debug_function_type = try o.builder.debugSubroutineType(
-                    try o.builder.debugTuple(debug_param_types.items),
-                );
+                switch (ip.indexToKey(ty.toIntern())) {
+                    .anon_struct_type => |tuple| {
+                        var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
+                        defer fields.deinit(gpa);
+
+                        try fields.ensureUnusedCapacity(gpa, tuple.types.len);
+
+                        comptime assert(struct_layout_version == 2);
+                        var offset: u64 = 0;
+
+                        const debug_fwd_ref = try o.builder.debugForwardReference();
+
+                        for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {
+                            if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(pt)) continue;
+
+                            const field_size = Type.fromInterned(field_ty).abiSize(pt);
+                            const field_align = Type.fromInterned(field_ty).abiAlignment(pt);
+                            const field_offset = field_align.forward(offset);
+                            offset = field_offset + field_size;
+
+                            const field_name = if (tuple.names.len != 0)
+                                tuple.names.get(ip)[i].toSlice(ip)
+                            else
+                                try std.fmt.allocPrintZ(gpa, "{d}", .{i});
+                            defer if (tuple.names.len == 0) gpa.free(field_name);
+
+                            fields.appendAssumeCapacity(try o.builder.debugMemberType(
+                                try o.builder.metadataString(field_name),
+                                .none, // File
+                                debug_fwd_ref,
+                                0,
+                                try o.lowerDebugType(Type.fromInterned(field_ty)),
+                                field_size * 8,
+                                (field_align.toByteUnits() orelse 0) * 8,
+                                field_offset * 8,
+                            ));
+                        }
 
-                try o.debug_type_map.put(gpa, ty, debug_function_type);
-                return debug_function_type;
-            },
-            .ComptimeInt => unreachable,
-            .ComptimeFloat => unreachable,
-            .Type => unreachable,
-            .Undefined => unreachable,
-            .Null => unreachable,
-            .EnumLiteral => unreachable,
+                        const debug_struct_type = try o.builder.debugStructType(
+                            try o.builder.metadataString(name),
+                            .none, // File
+                            o.debug_compile_unit, // Scope
+                            0, // Line
+                            .none, // Underlying type
+                            ty.abiSize(pt) * 8,
+                            (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
+                            try o.builder.debugTuple(fields.items),
+                        );
 
-            .Frame => @panic("TODO implement lowerDebugType for Frame types"),
-            .AnyFrame => @panic("TODO implement lowerDebugType for AnyFrame types"),
-            // These are the types that need a correct scope.
-            .Enum, .Struct, .Union, .Opaque => {},
-        }
-        const fwd_ref = try o.builder.debugForwardReference();
-        try o.debug_type_map.put(gpa, ty, fwd_ref);
-        try o.debug_unresolved_namespace_scopes.put(gpa, ty, required_by_runtime);
+                        o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_struct_type);
 
-        return fwd_ref;
-    }
+                        try o.debug_type_map.put(gpa, ty, debug_struct_type);
+                        return debug_struct_type;
+                    },
+                    .struct_type => {
+                        if (!ip.loadStructType(ty.toIntern()).haveFieldTypes(ip)) {
+                            // This can happen if a struct type makes it all the way to
+                            // flush() without ever being instantiated or referenced (even
+                            // via pointer). The only reason we are hearing about it now is
+                            // that it is being used as a namespace to put other debug types
+                            // into. Therefore we can satisfy this by making an empty namespace,
+                            // rather than changing the frontend to unnecessarily resolve the
+                            // struct field types.
+                            const owner_decl_index = ty.getOwnerDecl(zcu);
+                            const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
+                            try o.debug_type_map.put(gpa, ty, debug_struct_type);
+                            return debug_struct_type;
+                        }
+                    },
+                    else => {},
+                }
 
-    fn genNamespaces(o: *Object) !void {
-        const gpa = o.gpa;
-        const pt = o.pt;
-        const zcu = pt.zcu;
-        const ip = &zcu.intern_pool;
+                if (!ty.hasRuntimeBitsIgnoreComptime(pt)) {
+                    const owner_decl_index = ty.getOwnerDecl(zcu);
+                    const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
+                    try o.debug_type_map.put(gpa, ty, debug_struct_type);
+                    return debug_struct_type;
+                }
 
-        var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
-        defer fields.deinit(gpa);
+                const struct_type = zcu.typeToStruct(ty).?;
 
-        const unresolved = &o.debug_unresolved_namespace_scopes;
-        var unresolved_i: usize = 0;
-        while (unresolved_i < unresolved.count()) : (unresolved_i += 1) {
-            const ty = unresolved.keys()[unresolved_i];
-            const required_by_runtime = unresolved.values()[unresolved_i];
+                var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
+                defer fields.deinit(gpa);
 
-            const owner_decl_index = ty.getOwnerDeclOrNull(zcu);
-            const owner_decl: ?*Zcu.Decl =
-                if (owner_decl_index) |owner| ip.declPtr(owner) else null;
+                try fields.ensureUnusedCapacity(gpa, struct_type.field_types.len);
 
-            const file = if (owner_decl) |owner|
-                try o.getDebugFile(zcu.namespacePtr(owner.src_namespace).fileScope(zcu))
-            else
-                .none;
-            const scope = if (owner_decl) |owner|
-                try o.namespaceToDebugScope(owner.src_namespace)
-            else
-                o.debug_compile_unit;
-            const line = if (owner_decl) |owner| owner.typeSrcLine(zcu) + 1 else 0;
+                const debug_fwd_ref = try o.builder.debugForwardReference();
 
-            const name = if (owner_decl) |owner| owner.name.toSlice(ip) else try o.allocTypeName(ty);
-            defer if (owner_decl == null) gpa.free(name);
+                // Set as forward reference while the type is lowered in case it references itself
+                try o.debug_type_map.put(gpa, ty, debug_fwd_ref);
 
-            const fwd_ref = o.debug_type_map.get(ty).?;
+                comptime assert(struct_layout_version == 2);
+                var it = struct_type.iterateRuntimeOrder(ip);
+                while (it.next()) |field_index| {
+                    const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
+                    if (!field_ty.hasRuntimeBitsIgnoreComptime(pt)) continue;
+                    const field_size = field_ty.abiSize(pt);
+                    const field_align = pt.structFieldAlignment(
+                        struct_type.fieldAlign(ip, field_index),
+                        field_ty,
+                        struct_type.layout,
+                    );
+                    const field_offset = ty.structFieldOffset(field_index, pt);
 
-            fields.clearRetainingCapacity();
+                    const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse
+                        try ip.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
 
-            const ns = if (ty.getNamespace(zcu)) |n| n.unwrap() else null;
-            if (ns) |ns_id| {
-                const namespace = ip.namespacePtr(ns_id);
-                try fields.ensureUnusedCapacity(gpa, namespace.decls.keys().len);
+                    fields.appendAssumeCapacity(try o.builder.debugMemberType(
+                        try o.builder.metadataString(field_name.toSlice(ip)),
+                        .none, // File
+                        debug_fwd_ref,
+                        0, // Line
+                        try o.lowerDebugType(field_ty),
+                        field_size * 8,
+                        (field_align.toByteUnits() orelse 0) * 8,
+                        field_offset * 8,
+                    ));
+                }
 
-                for (namespace.decls.keys()) |decl_id| {
-                    const decl = ip.declPtr(decl_id);
-                    const decl_name = decl.name.toSlice(ip);
+                const debug_struct_type = try o.builder.debugStructType(
+                    try o.builder.metadataString(name),
+                    .none, // File
+                    o.debug_compile_unit, // Scope
+                    0, // Line
+                    .none, // Underlying type
+                    ty.abiSize(pt) * 8,
+                    (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
+                    try o.builder.debugTuple(fields.items),
+                );
 
-                    if (!decl.has_tv) continue;
-                    if (decl.kind != .named) continue;
-                    if (decl.analysis != .complete) continue;
+                o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_struct_type);
 
-                    const decl_line = 0;
+                // Set to real type now that it has been lowered fully
+                const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
+                map_ptr.* = debug_struct_type;
 
-                    if (decl.val.typeOf(zcu).ip_index == .type_type) {
-                        const nested_type = decl.val.toType();
-                        // If this decl is the owner of the type, it will
-                        // already have been declared as a direct child and
-                        // will not need to be typedef'd.
-                        if (nested_type.getOwnerDeclOrNull(zcu)) |owner| {
-                            if (owner == decl_id) continue;
-                        }
+                return debug_struct_type;
+            },
+            .Union => {
+                const owner_decl_index = ty.getOwnerDecl(zcu);
 
-                        switch (nested_type.zigTypeTag(zcu)) {
-                            // We still may want these for a Zig expression
-                            // evaluator in debuggers, but for now they are
-                            // completely useless.
-                            .ComptimeInt, .ComptimeFloat, .Type, .Undefined, .Null, .EnumLiteral => continue,
-                            else => {},
-                        }
+                const name = try o.allocTypeName(ty);
+                defer gpa.free(name);
 
-                        fields.appendAssumeCapacity(try o.builder.debugTypedef(
-                            try o.builder.metadataString(decl_name),
-                            try o.getDebugFile(namespace.fileScope(zcu)),
-                            fwd_ref,
-                            decl_line,
-                            try o.lowerDebugType(nested_type, false),
-                            0, // Align
-                        ));
-                    }
+                const union_type = ip.loadUnionType(ty.toIntern());
+                if (!union_type.haveFieldTypes(ip) or
+                    !ty.hasRuntimeBitsIgnoreComptime(pt) or
+                    !union_type.haveLayout(ip))
+                {
+                    const debug_union_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
+                    try o.debug_type_map.put(gpa, ty, debug_union_type);
+                    return debug_union_type;
                 }
-            }
 
-            if (!required_by_runtime) {
-                const res = try o.makeNamespaceDebugType(owner_decl_index.?, fields.items);
-                o.builder.debugForwardReferenceSetType(fwd_ref, res);
-                continue;
-            }
-
-            const res = switch (ty.zigTypeTag(zcu)) {
-                .Enum => res: {
-                    if (!ty.hasRuntimeBitsIgnoreComptime(pt)) {
-                        break :res try o.makeNamespaceDebugType(owner_decl_index.?, fields.items);
-                    }
-
-                    const enum_type = ip.loadEnumType(ty.toIntern());
-
-                    const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len);
-                    defer gpa.free(enumerators);
+                const layout = pt.getUnionLayout(union_type);
 
-                    const int_ty = Type.fromInterned(enum_type.tag_ty);
-                    const int_info = ty.intInfo(zcu);
-                    assert(int_info.bits != 0);
-
-                    for (enum_type.names.get(ip), 0..) |field_name_ip, i| {
-                        var bigint_space: Value.BigIntSpace = undefined;
-                        const bigint = if (enum_type.values.len != 0)
-                            Value.fromInterned(enum_type.values.get(ip)[i]).toBigInt(&bigint_space, pt)
-                        else
-                            std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();
+                const debug_fwd_ref = try o.builder.debugForwardReference();
 
-                        enumerators[i] = try o.builder.debugEnumerator(
-                            try o.builder.metadataString(field_name_ip.toSlice(ip)),
-                            int_info.signedness == .unsigned,
-                            int_info.bits,
-                            bigint,
-                        );
-                    }
+                // Set as forward reference while the type is lowered in case it references itself
+                try o.debug_type_map.put(gpa, ty, debug_fwd_ref);
 
-                    const debug_enum_type = try o.builder.debugEnumerationType(
+                if (layout.payload_size == 0) {
+                    const debug_union_type = try o.builder.debugStructType(
                         try o.builder.metadataString(name),
-                        file,
-                        scope,
-                        line,
-                        try o.lowerDebugType(int_ty, required_by_runtime),
+                        .none, // File
+                        o.debug_compile_unit, // Scope
+                        0, // Line
+                        .none, // Underlying type
                         ty.abiSize(pt) * 8,
                         (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
-                        try o.builder.debugTuple(enumerators),
+                        try o.builder.debugTuple(
+                            &.{try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty))},
+                        ),
                     );
 
-                    try o.debug_enums.append(gpa, debug_enum_type);
-                    break :res debug_enum_type;
-                },
-                .Opaque => res: {
-                    if (ty.toIntern() == .anyopaque_type) {
-                        break :res try o.builder.debugSignedType(
-                            try o.builder.metadataString("anyopaque"),
-                            0,
-                        );
-                    }
-
-                    const debug_opaque_type = try o.builder.debugStructType(
-                        try o.builder.metadataString(name),
-                        file,
-                        scope,
-                        line,
-                        .none, // Underlying type
-                        0, // Size
-                        0, // Align
-                        .none, // Fields
-                        false, // ByRef
-                    );
-                    break :res debug_opaque_type;
-                },
-                .Struct => res: {
-                    if (zcu.typeToPackedStruct(ty)) |struct_type| {
-                        const backing_int_ty = struct_type.backingIntTypeUnordered(ip);
-                        if (backing_int_ty != .none) {
-                            const info = Type.fromInterned(backing_int_ty).intInfo(zcu);
-                            const builder_name = try o.builder.metadataString(name);
-                            const debug_int_type = switch (info.signedness) {
-                                .signed => try o.builder.debugSignedType(builder_name, ty.abiSize(pt) * 8),
-                                .unsigned => try o.builder.debugUnsignedType(builder_name, ty.abiSize(pt) * 8),
-                            };
-                            break :res debug_int_type;
-                        }
-                    }
+                    // Set to real type now that it has been lowered fully
+                    const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
+                    map_ptr.* = debug_union_type;
 
-                    switch (ip.indexToKey(ty.toIntern())) {
-                        .anon_struct_type => |tuple| {
-                            try fields.ensureUnusedCapacity(gpa, tuple.types.len);
-
-                            comptime assert(struct_layout_version == 2);
-                            var offset: u64 = 0;
-
-                            for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {
-                                if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(pt)) continue;
-
-                                const field_size = Type.fromInterned(field_ty).abiSize(pt);
-                                const field_align = Type.fromInterned(field_ty).abiAlignment(pt);
-                                const field_offset = field_align.forward(offset);
-                                offset = field_offset + field_size;
-
-                                const field_name = if (tuple.names.len != 0)
-                                    tuple.names.get(ip)[i].toSlice(ip)
-                                else
-                                    try std.fmt.allocPrintZ(gpa, "{d}", .{i});
-                                defer if (tuple.names.len == 0) gpa.free(field_name);
-
-                                fields.appendAssumeCapacity(try o.builder.debugMemberType(
-                                    try o.builder.metadataString(field_name),
-                                    .none, // File
-                                    fwd_ref,
-                                    0,
-                                    try o.lowerDebugType(Type.fromInterned(field_ty), required_by_runtime),
-                                    field_size * 8,
-                                    (field_align.toByteUnits() orelse 0) * 8,
-                                    field_offset * 8,
-                                ));
-                            }
+                    return debug_union_type;
+                }
 
-                            const debug_struct_type = try o.builder.debugStructType(
-                                try o.builder.metadataString(name),
-                                file,
-                                scope,
-                                0, // Line
-                                .none, // Underlying type
-                                ty.abiSize(pt) * 8,
-                                (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
-                                try o.builder.debugTuple(fields.items),
-                                isByRef(ty, pt),
-                            );
+                var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
+                defer fields.deinit(gpa);
 
-                            break :res debug_struct_type;
-                        },
-                        else => {},
-                    }
+                try fields.ensureUnusedCapacity(gpa, union_type.loadTagType(ip).names.len);
 
-                    if (!ty.hasRuntimeBitsIgnoreComptime(pt)) {
-                        break :res try o.makeNamespaceDebugType(owner_decl_index.?, fields.items);
-                    }
-                    const struct_type = zcu.typeToStruct(ty).?;
+                const debug_union_fwd_ref = if (layout.tag_size == 0)
+                    debug_fwd_ref
+                else
+                    try o.builder.debugForwardReference();
 
-                    if (!struct_type.haveLayout(ip) or !struct_type.haveFieldTypes(ip)) {
-                        break :res try o.makeNamespaceDebugType(owner_decl_index.?, fields.items);
-                    }
+                const tag_type = union_type.loadTagType(ip);
 
-                    try fields.ensureUnusedCapacity(gpa, struct_type.field_types.len);
+                for (0..tag_type.names.len) |field_index| {
+                    const field_ty = union_type.field_types.get(ip)[field_index];
+                    if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(pt)) continue;
 
-                    comptime assert(struct_layout_version == 2);
-                    var it = struct_type.iterateRuntimeOrder(ip);
-                    while (it.next()) |field_index| {
-                        const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
-                        if (!field_ty.hasRuntimeBitsIgnoreComptime(pt)) continue;
-                        const field_size = field_ty.abiSize(pt);
-                        const field_align = pt.structFieldAlignment(
-                            struct_type.fieldAlign(ip, field_index),
-                            field_ty,
-                            struct_type.layout,
-                        );
-                        const field_offset = ty.structFieldOffset(field_index, pt);
+                    const field_size = Type.fromInterned(field_ty).abiSize(pt);
+                    const field_align: InternPool.Alignment = switch (union_type.flagsUnordered(ip).layout) {
+                        .@"packed" => .none,
+                        .auto, .@"extern" => pt.unionFieldNormalAlignment(union_type, @intCast(field_index)),
+                    };
 
-                        const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse
-                            try ip.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
+                    const field_name = tag_type.names.get(ip)[field_index];
+                    fields.appendAssumeCapacity(try o.builder.debugMemberType(
+                        try o.builder.metadataString(field_name.toSlice(ip)),
+                        .none, // File
+                        debug_union_fwd_ref,
+                        0, // Line
+                        try o.lowerDebugType(Type.fromInterned(field_ty)),
+                        field_size * 8,
+                        (field_align.toByteUnits() orelse 0) * 8,
+                        0, // Offset
+                    ));
+                }
 
-                        fields.appendAssumeCapacity(try o.builder.debugMemberType(
-                            try o.builder.metadataString(field_name.toSlice(ip)),
-                            file,
-                            fwd_ref,
-                            0, // Line
-                            try o.lowerDebugType(field_ty, required_by_runtime),
-                            field_size * 8,
-                            (field_align.toByteUnits() orelse 0) * 8,
-                            field_offset * 8,
-                        ));
-                    }
+                var union_name_buf: ?[:0]const u8 = null;
+                defer if (union_name_buf) |buf| gpa.free(buf);
+                const union_name = if (layout.tag_size == 0) name else name: {
+                    union_name_buf = try std.fmt.allocPrintZ(gpa, "{s}:Payload", .{name});
+                    break :name union_name_buf.?;
+                };
 
-                    const debug_struct_type = try o.builder.debugStructType(
-                        try o.builder.metadataString(name),
-                        file,
-                        scope,
-                        line,
-                        .none, // Underlying type
-                        ty.abiSize(pt) * 8,
-                        (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
-                        try o.builder.debugTuple(fields.items),
-                        isByRef(ty, pt),
-                    );
+                const debug_union_type = try o.builder.debugUnionType(
+                    try o.builder.metadataString(union_name),
+                    .none, // File
+                    o.debug_compile_unit, // Scope
+                    0, // Line
+                    .none, // Underlying type
+                    ty.abiSize(pt) * 8,
+                    (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
+                    try o.builder.debugTuple(fields.items),
+                );
 
-                    break :res debug_struct_type;
-                },
-                .Union => res: {
-                    const union_type = ip.loadUnionType(ty.toIntern());
-                    if (!union_type.haveFieldTypes(ip) or
-                        !ty.hasRuntimeBitsIgnoreComptime(pt) or
-                        !union_type.haveLayout(ip))
-                    {
-                        break :res try o.makeNamespaceDebugType(owner_decl_index.?, fields.items);
-                    }
+                o.builder.debugForwardReferenceSetType(debug_union_fwd_ref, debug_union_type);
 
-                    const layout = pt.getUnionLayout(union_type);
+                if (layout.tag_size == 0) {
+                    // Set to real type now that it has been lowered fully
+                    const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
+                    map_ptr.* = debug_union_type;
 
-                    if (layout.payload_size == 0) {
-                        const debug_union_type = try o.builder.debugStructType(
-                            try o.builder.metadataString(name),
-                            file,
-                            scope,
-                            0, // Line
-                            .none, // Underlying type
-                            ty.abiSize(pt) * 8,
-                            (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
-                            try o.builder.debugTuple(
-                                &.{try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty), required_by_runtime)},
-                            ),
-                            isByRef(ty, pt),
-                        );
+                    return debug_union_type;
+                }
 
-                        break :res debug_union_type;
-                    }
+                var tag_offset: u64 = undefined;
+                var payload_offset: u64 = undefined;
+                if (layout.tag_align.compare(.gte, layout.payload_align)) {
+                    tag_offset = 0;
+                    payload_offset = layout.payload_align.forward(layout.tag_size);
+                } else {
+                    payload_offset = 0;
+                    tag_offset = layout.tag_align.forward(layout.payload_size);
+                }
 
-                    try fields.ensureUnusedCapacity(gpa, union_type.loadTagType(ip).names.len);
+                const debug_tag_type = try o.builder.debugMemberType(
+                    try o.builder.metadataString("tag"),
+                    .none, // File
+                    debug_fwd_ref,
+                    0, // Line
+                    try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty)),
+                    layout.tag_size * 8,
+                    (layout.tag_align.toByteUnits() orelse 0) * 8,
+                    tag_offset * 8,
+                );
 
-                    const debug_union_fwd_ref = if (layout.tag_size == 0)
-                        fwd_ref
-                    else
-                        try o.builder.debugForwardReference();
+                const debug_payload_type = try o.builder.debugMemberType(
+                    try o.builder.metadataString("payload"),
+                    .none, // File
+                    debug_fwd_ref,
+                    0, // Line
+                    debug_union_type,
+                    layout.payload_size * 8,
+                    (layout.payload_align.toByteUnits() orelse 0) * 8,
+                    payload_offset * 8,
+                );
 
-                    const tag_type = union_type.loadTagType(ip);
+                const full_fields: [2]Builder.Metadata =
+                    if (layout.tag_align.compare(.gte, layout.payload_align))
+                    .{ debug_tag_type, debug_payload_type }
+                else
+                    .{ debug_payload_type, debug_tag_type };
 
-                    for (0..tag_type.names.len) |field_index| {
-                        const field_ty = union_type.field_types.get(ip)[field_index];
-                        if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(pt)) continue;
+                const debug_tagged_union_type = try o.builder.debugStructType(
+                    try o.builder.metadataString(name),
+                    .none, // File
+                    o.debug_compile_unit, // Scope
+                    0, // Line
+                    .none, // Underlying type
+                    ty.abiSize(pt) * 8,
+                    (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
+                    try o.builder.debugTuple(&full_fields),
+                );
 
-                        const field_size = Type.fromInterned(field_ty).abiSize(pt);
-                        const field_align: InternPool.Alignment = switch (union_type.flagsUnordered(ip).layout) {
-                            .@"packed" => .none,
-                            .auto, .@"extern" => pt.unionFieldNormalAlignment(union_type, @intCast(field_index)),
-                        };
+                o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_tagged_union_type);
 
-                        const field_name = tag_type.names.get(ip)[field_index];
-                        fields.appendAssumeCapacity(try o.builder.debugMemberType(
-                            try o.builder.metadataString(field_name.toSlice(ip)),
-                            file,
-                            debug_union_fwd_ref,
-                            0, // Line
-                            try o.lowerDebugType(Type.fromInterned(field_ty), required_by_runtime),
-                            field_size * 8,
-                            (field_align.toByteUnits() orelse 0) * 8,
-                            0, // Offset
-                        ));
-                    }
+                // Set to real type now that it has been lowered fully
+                const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
+                map_ptr.* = debug_tagged_union_type;
 
-                    var union_name_buf: ?[:0]const u8 = null;
-                    defer if (union_name_buf) |buf| gpa.free(buf);
-                    const union_name = if (layout.tag_size == 0) name else name: {
-                        union_name_buf = try std.fmt.allocPrintZ(gpa, "{s}:Payload", .{name});
-                        break :name union_name_buf.?;
-                    };
+                return debug_tagged_union_type;
+            },
+            .Fn => {
+                const fn_info = zcu.typeToFunc(ty).?;
 
-                    const debug_union_type = try o.builder.debugUnionType(
-                        try o.builder.metadataString(union_name),
-                        file,
-                        scope,
-                        line,
-                        .none, // Underlying type
-                        ty.abiSize(pt) * 8,
-                        (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
-                        try o.builder.debugTuple(fields.items),
-                        isByRef(ty, pt),
-                    );
+                var debug_param_types = std.ArrayList(Builder.Metadata).init(gpa);
+                defer debug_param_types.deinit();
 
-                    if (layout.tag_size == 0) {
-                        break :res debug_union_type;
-                    }
+                try debug_param_types.ensureUnusedCapacity(3 + fn_info.param_types.len);
 
-                    o.builder.debugForwardReferenceSetType(debug_union_fwd_ref, debug_union_type);
+                // Return type goes first.
+                if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(pt)) {
+                    const sret = firstParamSRet(fn_info, pt, target);
+                    const ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type);
+                    debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ret_ty));
 
-                    var tag_offset: u64 = undefined;
-                    var payload_offset: u64 = undefined;
-                    if (layout.tag_align.compare(.gte, layout.payload_align)) {
-                        tag_offset = 0;
-                        payload_offset = layout.payload_align.forward(layout.tag_size);
-                    } else {
-                        payload_offset = 0;
-                        tag_offset = layout.tag_align.forward(layout.payload_size);
+                    if (sret) {
+                        const ptr_ty = try pt.singleMutPtrType(Type.fromInterned(fn_info.return_type));
+                        debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty));
                     }
+                } else {
+                    debug_param_types.appendAssumeCapacity(try o.lowerDebugType(Type.void));
+                }
 
-                    const debug_tag_type = try o.builder.debugMemberType(
-                        try o.builder.metadataString("tag"),
-                        file, // File
-                        fwd_ref,
-                        0, // Line
-                        try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty), required_by_runtime),
-                        layout.tag_size * 8,
-                        (layout.tag_align.toByteUnits() orelse 0) * 8,
-                        tag_offset * 8,
-                    );
+                if (Type.fromInterned(fn_info.return_type).isError(zcu) and
+                    zcu.comp.config.any_error_tracing)
+                {
+                    const ptr_ty = try pt.singleMutPtrType(try o.getStackTraceType());
+                    debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty));
+                }
 
-                    const debug_payload_type = try o.builder.debugMemberType(
-                        try o.builder.metadataString("payload"),
-                        file,
-                        fwd_ref,
-                        0, // Line
-                        debug_union_type,
-                        layout.payload_size * 8,
-                        (layout.payload_align.toByteUnits() orelse 0) * 8,
-                        payload_offset * 8,
-                    );
+                for (0..fn_info.param_types.len) |i| {
+                    const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[i]);
+                    if (!param_ty.hasRuntimeBitsIgnoreComptime(pt)) continue;
 
-                    const full_fields: [2]Builder.Metadata =
-                        if (layout.tag_align.compare(.gte, layout.payload_align))
-                        .{ debug_tag_type, debug_payload_type }
-                    else
-                        .{ debug_payload_type, debug_tag_type };
+                    if (isByRef(param_ty, pt)) {
+                        const ptr_ty = try pt.singleMutPtrType(param_ty);
+                        debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty));
+                    } else {
+                        debug_param_types.appendAssumeCapacity(try o.lowerDebugType(param_ty));
+                    }
+                }
 
-                    const debug_tagged_union_type = try o.builder.debugStructType(
-                        try o.builder.metadataString(name),
-                        file, // File
-                        scope,
-                        line,
-                        .none, // Underlying type
-                        ty.abiSize(pt) * 8,
-                        (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
-                        try o.builder.debugTuple(&full_fields),
-                        isByRef(ty, pt),
-                    );
+                const debug_function_type = try o.builder.debugSubroutineType(
+                    try o.builder.debugTuple(debug_param_types.items),
+                );
 
-                    break :res debug_tagged_union_type;
-                },
-                else => unreachable, // Handled above.
-            };
+                try o.debug_type_map.put(gpa, ty, debug_function_type);
+                return debug_function_type;
+            },
+            .ComptimeInt => unreachable,
+            .ComptimeFloat => unreachable,
+            .Type => unreachable,
+            .Undefined => unreachable,
+            .Null => unreachable,
+            .EnumLiteral => unreachable,
 
-            o.builder.debugForwardReferenceSetType(fwd_ref, res);
+            .Frame => @panic("TODO implement lowerDebugType for Frame types"),
+            .AnyFrame => @panic("TODO implement lowerDebugType for AnyFrame types"),
         }
     }
 
@@ -2811,10 +2779,14 @@ pub const Object = struct {
         const file_scope = namespace.fileScope(zcu);
         if (namespace.parent == .none) return try o.getDebugFile(file_scope);
 
-        return o.lowerDebugType(zcu.declPtr(namespace.decl_index).val.toType(), false);
+        const gop = try o.debug_unresolved_namespace_scopes.getOrPut(o.gpa, namespace_index);
+
+        if (!gop.found_existing) gop.value_ptr.* = try o.builder.debugForwardReference();
+
+        return gop.value_ptr.*;
     }
 
-    fn makeNamespaceDebugType(o: *Object, decl_index: InternPool.DeclIndex, fields: []const Builder.Metadata) !Builder.Metadata {
+    fn makeEmptyNamespaceDebugType(o: *Object, decl_index: InternPool.DeclIndex) !Builder.Metadata {
         const zcu = o.pt.zcu;
         const decl = zcu.declPtr(decl_index);
         const file_scope = zcu.namespacePtr(decl.src_namespace).fileScope(zcu);
@@ -2826,8 +2798,7 @@ pub const Object = struct {
             .none,
             0,
             0,
-            if (fields.len == 0) .none else try o.builder.debugTuple(fields),
-            false, // is_byref
+            .none,
         );
     }
 
@@ -4741,33 +4712,16 @@ pub const DeclGen = struct {
             if (!owner_mod.strip) {
                 const debug_file = try o.getDebugFile(file_scope);
 
-                const linkage_name = try o.builder.metadataStringFromStrtabString(variable_index.name(&o.builder));
-                const is_internal_linkage = !decl.isExtern(zcu);
-
-                const ty = try o.lowerDebugType(decl.typeOf(zcu), true);
                 const debug_global_var = try o.builder.debugGlobalVar(
-                    linkage_name,
-                    linkage_name,
-                    debug_file,
-                    debug_file,
+                    try o.builder.metadataString(decl.name.toSlice(ip)), // Name
+                    try o.builder.metadataStringFromStrtabString(variable_index.name(&o.builder)), // Linkage name
+                    debug_file, // File
+                    debug_file, // Scope
                     line_number,
-                    ty,
+                    try o.lowerDebugType(decl.typeOf(zcu)),
                     variable_index,
-                    is_internal_linkage,
+                    .{ .local = !decl.isExtern(zcu) },
                 );
-                if (is_internal_linkage) {
-                    const name = try o.builder.metadataString(decl.name.toSlice(ip));
-                    const debug_scope = try o.namespaceToDebugScope(decl.src_namespace);
-
-                    const import = try o.builder.debugImportDeclaration(
-                        name,
-                        debug_file,
-                        debug_scope,
-                        line_number,
-                        debug_global_var,
-                    );
-                    try o.debug_imports.append(o.gpa, import);
-                }
 
                 const debug_expression = try o.builder.debugExpression(&.{});
 
@@ -5218,12 +5172,11 @@ pub const FuncGen = struct {
 
             self.scope = try o.builder.debugSubprogram(
                 self.file,
-                self.file, // TODO Get the correct scope into here—self.scope is the function's *inner* scope.
                 try o.builder.metadataString(decl.name.toSlice(&zcu.intern_pool)),
                 try o.builder.metadataString(decl.fqn.toSlice(&zcu.intern_pool)),
                 line_number,
                 line_number + func.lbrace_line,
-                try o.lowerDebugType(fn_ty, true),
+                try o.lowerDebugType(fn_ty),
                 .{
                     .di_flags = .{ .StaticMember = true },
                     .sp_flags = .{
@@ -6773,7 +6726,7 @@ pub const FuncGen = struct {
             self.file,
             self.scope,
             self.prev_dbg_line,
-            try o.lowerDebugType(ptr_ty.childType(mod), true),
+            try o.lowerDebugType(ptr_ty.childType(mod)),
         );
 
         _ = try self.wip.callIntrinsic(
@@ -6806,7 +6759,7 @@ pub const FuncGen = struct {
             self.file,
             self.scope,
             self.prev_dbg_line,
-            try o.lowerDebugType(operand_ty, true),
+            try o.lowerDebugType(operand_ty),
         );
 
         const pt = o.pt;
@@ -8920,7 +8873,7 @@ pub const FuncGen = struct {
             self.file,
             self.scope,
             lbrace_line,
-            try o.lowerDebugType(inst_ty, true),
+            try o.lowerDebugType(inst_ty),
             @intCast(self.arg_index),
         );
 
test/cases/llvm/debug_types.zig
@@ -1,23 +0,0 @@
-const Ty = struct {
-	pub const A = void;
-	pub const B = @Vector(2, u0);
-	pub const C = u0;
-	pub const D = enum (u0) {};
-	pub const E = type;
-	pub const F = 1;
-	pub const G = 1.0;
-	pub const H = undefined;
-	pub const I = null;
-	pub const J = .foo;
-};
-pub fn main() void {
-	inline for (@typeInfo(Ty).Struct.decls) |d|{
-		_ = @field(Ty, d.name);
-	}
-}
-
-// compile
-// output_mode=Exe
-// backend=llvm
-// target=x86_64-linux,x86_64-macos
-//
\ No newline at end of file