authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-02-13 11:48:56+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-10 10:26:12+00:00
log2b8feabb8f2b3a3c96d2d8e74393e0c8dfa17390
tree2860038efbf658a07a8b305205bf3e92e7aa6260
parent6402e119e8d21403cbafc4a6c8ca353b894592ba
signaturelock-open Commit is signed but in an unrecognized format.

llvm: some more improvements to debug info

Most importantly, adds support for `DW_TAG_typedef` to `llvm.Builder`, and uses it to define error sets and optional pointers/errors. Also deletes some random dead code I found.

2 files changed, 142 insertions(+), 173 deletions(-)

lib/std/zig/llvm/Builder.zig+58
...@@ -8021,6 +8021,7 @@ pub const Metadata = packed struct(u32) {...@@ -8021,6 +8021,7 @@ pub const Metadata = packed struct(u32) {
8021 composite_vector_type,8021 composite_vector_type,
8022 derived_pointer_type,8022 derived_pointer_type,
8023 derived_member_type,8023 derived_member_type,
8024 derived_typedef_type,
8024 subroutine_type,8025 subroutine_type,
8025 enumerator_unsigned,8026 enumerator_unsigned,
8026 enumerator_signed_positive,8027 enumerator_signed_positive,
...@@ -8064,6 +8065,7 @@ pub const Metadata = packed struct(u32) {...@@ -8064,6 +8065,7 @@ pub const Metadata = packed struct(u32) {
8064 .composite_vector_type,8065 .composite_vector_type,
8065 .derived_pointer_type,8066 .derived_pointer_type,
8066 .derived_member_type,8067 .derived_member_type,
8068 .derived_typedef_type,
8067 .subroutine_type,8069 .subroutine_type,
8068 .enumerator_unsigned,8070 .enumerator_unsigned,
8069 .enumerator_signed_positive,8071 .enumerator_signed_positive,
...@@ -10463,15 +10465,18 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -10463,15 +10465,18 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
10463 },10465 },
10464 .derived_pointer_type,10466 .derived_pointer_type,
10465 .derived_member_type,10467 .derived_member_type,
10468 .derived_typedef_type,
10466 => |kind| {10469 => |kind| {
10467 const extra = self.metadataExtraData(Metadata.DerivedType, metadata_item.data);10470 const extra = self.metadataExtraData(Metadata.DerivedType, metadata_item.data);
10468 try metadata_formatter.specialized(.@"!", .DIDerivedType, .{10471 try metadata_formatter.specialized(.@"!", .DIDerivedType, .{
10469 .tag = @as(enum {10472 .tag = @as(enum {
10470 DW_TAG_pointer_type,10473 DW_TAG_pointer_type,
10471 DW_TAG_member,10474 DW_TAG_member,
10475 DW_TAG_typedef,
10472 }, switch (kind) {10476 }, switch (kind) {
10473 .derived_pointer_type => .DW_TAG_pointer_type,10477 .derived_pointer_type => .DW_TAG_pointer_type,
10474 .derived_member_type => .DW_TAG_member,10478 .derived_member_type => .DW_TAG_member,
10479 .derived_typedef_type => .DW_TAG_typedef,
10475 else => unreachable,10480 else => unreachable,
10476 }),10481 }),
10477 .name = extra.name,10482 .name = extra.name,
...@@ -12360,6 +12365,30 @@ pub fn debugMemberType(...@@ -12360,6 +12365,30 @@ pub fn debugMemberType(
12360 );12365 );
12361}12366}
1236212367
12368pub fn debugTypedefType(
12369 self: *Builder,
12370 name: ?Metadata.String,
12371 file: ?Metadata,
12372 scope: ?Metadata,
12373 line: u32,
12374 underlying_type: ?Metadata,
12375 size_in_bits: u64,
12376 align_in_bits: u64,
12377 offset_in_bits: u64,
12378) Allocator.Error!Metadata {
12379 try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0);
12380 return self.debugTypedefTypeAssumeCapacity(
12381 name,
12382 file,
12383 scope,
12384 line,
12385 underlying_type,
12386 size_in_bits,
12387 align_in_bits,
12388 offset_in_bits,
12389 );
12390}
12391
12363pub fn debugSubroutineType(self: *Builder, types_tuple: ?Metadata) Allocator.Error!Metadata {12392pub fn debugSubroutineType(self: *Builder, types_tuple: ?Metadata) Allocator.Error!Metadata {
12364 try self.ensureUnusedMetadataCapacity(1, Metadata.SubroutineType, 0);12393 try self.ensureUnusedMetadataCapacity(1, Metadata.SubroutineType, 0);
12365 return self.debugSubroutineTypeAssumeCapacity(types_tuple);12394 return self.debugSubroutineTypeAssumeCapacity(types_tuple);
...@@ -12875,6 +12904,33 @@ fn debugMemberTypeAssumeCapacity(...@@ -12875,6 +12904,33 @@ fn debugMemberTypeAssumeCapacity(
12875 });12904 });
12876}12905}
1287712906
12907fn debugTypedefTypeAssumeCapacity(
12908 self: *Builder,
12909 name: ?Metadata.String,
12910 file: ?Metadata,
12911 scope: ?Metadata,
12912 line: u32,
12913 underlying_type: ?Metadata,
12914 size_in_bits: u64,
12915 align_in_bits: u64,
12916 offset_in_bits: u64,
12917) Metadata {
12918 assert(!self.strip);
12919 return self.metadataSimpleAssumeCapacity(.derived_typedef_type, Metadata.DerivedType{
12920 .name = .wrap(name),
12921 .file = .wrap(file),
12922 .scope = .wrap(scope),
12923 .line = line,
12924 .underlying_type = .wrap(underlying_type),
12925 .size_in_bits_lo = @truncate(size_in_bits),
12926 .size_in_bits_hi = @truncate(size_in_bits >> 32),
12927 .align_in_bits_lo = @truncate(align_in_bits),
12928 .align_in_bits_hi = @truncate(align_in_bits >> 32),
12929 .offset_in_bits_lo = @truncate(offset_in_bits),
12930 .offset_in_bits_hi = @truncate(offset_in_bits >> 32),
12931 });
12932}
12933
12878fn debugSubroutineTypeAssumeCapacity(self: *Builder, types_tuple: ?Metadata) Metadata {12934fn debugSubroutineTypeAssumeCapacity(self: *Builder, types_tuple: ?Metadata) Metadata {
12879 assert(!self.strip);12935 assert(!self.strip);
12880 return self.metadataSimpleAssumeCapacity(.subroutine_type, Metadata.SubroutineType{12936 return self.metadataSimpleAssumeCapacity(.subroutine_type, Metadata.SubroutineType{
...@@ -14223,12 +14279,14 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco...@@ -14223,12 +14279,14 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco
14223 },14279 },
14224 .derived_pointer_type,14280 .derived_pointer_type,
14225 .derived_member_type,14281 .derived_member_type,
14282 .derived_typedef_type,
14226 => |kind| {14283 => |kind| {
14227 const extra = self.metadataExtraData(Metadata.DerivedType, data);14284 const extra = self.metadataExtraData(Metadata.DerivedType, data);
14228 try metadata_block.writeAbbrevAdapted(MetadataBlock.DerivedType{14285 try metadata_block.writeAbbrevAdapted(MetadataBlock.DerivedType{
14229 .tag = switch (kind) {14286 .tag = switch (kind) {
14230 .derived_pointer_type => DW.TAG.pointer_type,14287 .derived_pointer_type => DW.TAG.pointer_type,
14231 .derived_member_type => DW.TAG.member,14288 .derived_member_type => DW.TAG.member,
14289 .derived_typedef_type => DW.TAG.typedef,
14232 else => unreachable,14290 else => unreachable,
14233 },14291 },
14234 .name = extra.name,14292 .name = extra.name,
src/codegen/llvm.zig+84-173
...@@ -1914,6 +1914,15 @@ pub const Object = struct {...@@ -1914,6 +1914,15 @@ pub const Object = struct {
19141914
1915 const name = try o.builder.metadataStringFmt("{f}", .{ty.fmt(pt)});1915 const name = try o.builder.metadataStringFmt("{f}", .{ty.fmt(pt)});
19161916
1917 // lldb cannot handle non-byte-sized types, so in the logic below, bit sizes are padded up.
1918 // For instance, `bool` is considered to be 8 bits, and `u60` is considered to be 64 bits.
1919
1920 // I tried using variants (DW_TAG_variant_part + DW_TAG_variant) to encode error unions,
1921 // tagged unions, etc; this would have told debuggers which field was active, which could
1922 // improve UX significantly. GDB handles this perfectly fine, but unfortunately, LLDB has no
1923 // handling for variants at all, and will never print fields in them, so I opted not to use
1924 // them for now.
1925
1917 switch (ty.zigTypeTag(zcu)) {1926 switch (ty.zigTypeTag(zcu)) {
1918 .void,1927 .void,
1919 .noreturn,1928 .noreturn,
...@@ -1925,23 +1934,19 @@ pub const Object = struct {...@@ -1925,23 +1934,19 @@ pub const Object = struct {
1925 .enum_literal,1934 .enum_literal,
1926 => return o.builder.debugSignedType(name, 0),1935 => return o.builder.debugSignedType(name, 0),
19271936
1937 .float => return o.builder.debugFloatType(name, ty.floatBits(target)),
1938
1939 .bool => return o.builder.debugBoolType(name, 8),
1940
1928 .int => {1941 .int => {
1929 const info = ty.intInfo(zcu);1942 const info = ty.intInfo(zcu);
1930 const bits = ty.abiSize(zcu) * 8; // lldb cannot handle non-byte sized types1943 const bits = ty.abiSize(zcu) * 8;
1931 return switch (info.signedness) {1944 return switch (info.signedness) {
1932 .signed => try o.builder.debugSignedType(name, bits),1945 .signed => try o.builder.debugSignedType(name, bits),
1933 .unsigned => try o.builder.debugUnsignedType(name, bits),1946 .unsigned => try o.builder.debugUnsignedType(name, bits),
1934 };1947 };
1935 },1948 },
1936 .float => {1949
1937 return o.builder.debugFloatType(name, ty.floatBits(target));
1938 },
1939 .bool => {
1940 return o.builder.debugBoolType(
1941 name,
1942 8, // lldb cannot handle non-byte sized types
1943 );
1944 },
1945 .pointer => {1950 .pointer => {
1946 const ptr_size = Type.ptrAbiSize(zcu.getTarget());1951 const ptr_size = Type.ptrAbiSize(zcu.getTarget());
1947 const ptr_align = Type.ptrAbiAlignment(zcu.getTarget());1952 const ptr_align = Type.ptrAbiAlignment(zcu.getTarget());
...@@ -1949,20 +1954,20 @@ pub const Object = struct {...@@ -1949,20 +1954,20 @@ pub const Object = struct {
1949 if (ty.isSlice(zcu)) {1954 if (ty.isSlice(zcu)) {
1950 const debug_ptr_type = try o.builder.debugMemberType(1955 const debug_ptr_type = try o.builder.debugMemberType(
1951 try o.builder.metadataString("ptr"),1956 try o.builder.metadataString("ptr"),
1952 null, // File1957 null, // file
1953 ty_fwd_ref,1958 ty_fwd_ref,
1954 0, // Line1959 0, // line
1955 try o.getDebugType(pt, ty.slicePtrFieldType(zcu)),1960 try o.getDebugType(pt, ty.slicePtrFieldType(zcu)),
1956 ptr_size * 8,1961 ptr_size * 8,
1957 ptr_align.toByteUnits().? * 8,1962 ptr_align.toByteUnits().? * 8,
1958 0, // Offset1963 0, // offset
1959 );1964 );
19601965
1961 const debug_len_type = try o.builder.debugMemberType(1966 const debug_len_type = try o.builder.debugMemberType(
1962 try o.builder.metadataString("len"),1967 try o.builder.metadataString("len"),
1963 null, // File1968 null, // file
1964 ty_fwd_ref,1969 ty_fwd_ref,
1965 0, // Line1970 0, // line
1966 try o.getDebugType(pt, .usize),1971 try o.getDebugType(pt, .usize),
1967 ptr_size * 8,1972 ptr_size * 8,
1968 ptr_align.toByteUnits().? * 8,1973 ptr_align.toByteUnits().? * 8,
...@@ -1971,10 +1976,10 @@ pub const Object = struct {...@@ -1971,10 +1976,10 @@ pub const Object = struct {
19711976
1972 return o.builder.debugStructType(1977 return o.builder.debugStructType(
1973 name,1978 name,
1974 null, // File1979 null, // file
1975 o.debug_compile_unit.unwrap().?, // Scope1980 o.debug_compile_unit.unwrap().?, // scope
1976 0, // Line1981 0, // line
1977 null, // Underlying type1982 null, // underlying type
1978 ptr_size * 2 * 8,1983 ptr_size * 2 * 8,
1979 ptr_align.toByteUnits().? * 8,1984 ptr_align.toByteUnits().? * 8,
1980 try o.builder.metadataTuple(&.{1985 try o.builder.metadataTuple(&.{
...@@ -1986,36 +1991,34 @@ pub const Object = struct {...@@ -1986,36 +1991,34 @@ pub const Object = struct {
19861991
1987 return o.builder.debugPointerType(1992 return o.builder.debugPointerType(
1988 name,1993 name,
1989 null, // File1994 null, // file
1990 null, // Scope1995 o.debug_compile_unit.unwrap().?, // scope
1991 0, // Line1996 0, // line
1992 try o.getDebugType(pt, ty.childType(zcu)),1997 try o.getDebugType(pt, ty.childType(zcu)),
1993 ptr_size * 8,1998 ptr_size * 8,
1994 ptr_align.toByteUnits().? * 8,1999 ptr_align.toByteUnits().? * 8,
1995 0, // Offset2000 0, // offset
1996 );
1997 },
1998 .array => {
1999 return o.builder.debugArrayType(
2000 null, // Name
2001 null, // File
2002 null, // Scope
2003 0, // Line
2004 try o.getDebugType(pt, ty.childType(zcu)),
2005 ty.abiSize(zcu) * 8,
2006 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
2007 try o.builder.metadataTuple(&.{
2008 try o.builder.debugSubrange(
2009 try o.builder.metadataConstant(try o.builder.intConst(.i64, 0)),
2010 try o.builder.metadataConstant(try o.builder.intConst(.i64, ty.arrayLen(zcu))),
2011 ),
2012 }),
2013 );2001 );
2014 },2002 },
2003 .array => return o.builder.debugArrayType(
2004 name,
2005 null, // file
2006 o.debug_compile_unit.unwrap().?, // scope
2007 0, // line
2008 try o.getDebugType(pt, ty.childType(zcu)),
2009 ty.abiSize(zcu) * 8,
2010 ty.abiAlignment(zcu).toByteUnits().? * 8,
2011 try o.builder.metadataTuple(&.{
2012 try o.builder.debugSubrange(
2013 try o.builder.metadataConstant(try o.builder.intConst(.i64, 0)),
2014 try o.builder.metadataConstant(try o.builder.intConst(.i64, ty.arrayLen(zcu))),
2015 ),
2016 }),
2017 ),
2015 .vector => {2018 .vector => {
2016 const elem_ty = ty.childType(zcu);2019 const elem_ty = ty.childType(zcu);
2017 // Vector elements cannot be padded since that would make2020 // Vector elements cannot be padded since that would make
2018 // @bitSizOf(elem) * len > @bitSizOf(vec).2021 // @bitSizeOf(elem) * len > @bitSizOf(vec).
2019 // Neither gdb nor lldb seem to be able to display non-byte sized2022 // Neither gdb nor lldb seem to be able to display non-byte sized
2020 // vectors properly.2023 // vectors properly.
2021 const debug_elem_type = switch (elem_ty.zigTypeTag(zcu)) {2024 const debug_elem_type = switch (elem_ty.zigTypeTag(zcu)) {
...@@ -2027,18 +2030,19 @@ pub const Object = struct {...@@ -2027,18 +2030,19 @@ pub const Object = struct {
2027 };2030 };
2028 },2031 },
2029 .bool => try o.builder.debugBoolType(try o.builder.metadataString("bool"), 1),2032 .bool => try o.builder.debugBoolType(try o.builder.metadataString("bool"), 1),
2033 // We don't pad pointers or floats, so we can lower those normally.
2030 .pointer, .optional, .float => try o.getDebugType(pt, elem_ty),2034 .pointer, .optional, .float => try o.getDebugType(pt, elem_ty),
2031 else => unreachable,2035 else => unreachable,
2032 };2036 };
20332037
2034 return o.builder.debugVectorType(2038 return o.builder.debugVectorType(
2035 null, // Name2039 name,
2036 null, // File2040 null, // file
2037 null, // Scope2041 o.debug_compile_unit.unwrap().?, // scope
2038 0, // Line2042 0, // line
2039 debug_elem_type,2043 debug_elem_type,
2040 ty.abiSize(zcu) * 8,2044 ty.abiSize(zcu) * 8,
2041 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,2045 ty.abiAlignment(zcu).toByteUnits().? * 8,
2042 try o.builder.metadataTuple(&.{2046 try o.builder.metadataTuple(&.{
2043 try o.builder.debugSubrange(2047 try o.builder.debugSubrange(
2044 try o.builder.metadataConstant(try o.builder.intConst(.i64, 0)),2048 try o.builder.metadataConstant(try o.builder.intConst(.i64, 0)),
...@@ -2050,26 +2054,15 @@ pub const Object = struct {...@@ -2050,26 +2054,15 @@ pub const Object = struct {
2050 .optional => {2054 .optional => {
2051 const payload_ty = ty.optionalChild(zcu);2055 const payload_ty = ty.optionalChild(zcu);
2052 if (ty.optionalReprIsPayload(zcu)) {2056 if (ty.optionalReprIsPayload(zcu)) {
2053 // MLUGG TODO: these should use DW_TAG_typedef instead, but std.zig.llvm.Builder currently lacks support for those.2057 return o.builder.debugTypedefType(
2054 const payload_member = try o.builder.debugMemberType(
2055 try o.builder.metadataString("payload"),
2056 null, // file
2057 ty_fwd_ref,
2058 0, // line
2059 try o.getDebugType(pt, .anyerror),
2060 ty.abiSize(zcu) * 8,
2061 ty.abiAlignment(zcu).toByteUnits().? * 8,
2062 0, // offset
2063 );
2064 return o.builder.debugStructType(
2065 name,2058 name,
2066 null, // file2059 null, // file
2067 o.debug_compile_unit.unwrap().?, // scope2060 o.debug_compile_unit.unwrap().?, // scope
2068 0, // line2061 0, // line
2069 null, // underlying type2062 try o.getDebugType(pt, payload_ty),
2070 ty.abiSize(zcu) * 8,2063 ty.abiSize(zcu) * 8,
2071 ty.abiAlignment(zcu).toByteUnits().? * 8,2064 ty.abiAlignment(zcu).toByteUnits().? * 8,
2072 try o.builder.metadataTuple(&.{payload_member}),2065 0, // offset
2073 );2066 );
2074 }2067 }
20752068
...@@ -2083,7 +2076,7 @@ pub const Object = struct {...@@ -2083,7 +2076,7 @@ pub const Object = struct {
2083 const debug_payload_type = try o.builder.debugMemberType(2076 const debug_payload_type = try o.builder.debugMemberType(
2084 try o.builder.metadataString("payload"),2077 try o.builder.metadataString("payload"),
2085 null, // file2078 null, // file
2086 ty_fwd_ref,2079 ty_fwd_ref, // scope
2087 0, // line2080 0, // line
2088 try o.getDebugType(pt, payload_ty),2081 try o.getDebugType(pt, payload_ty),
2089 payload_size * 8,2082 payload_size * 8,
...@@ -2104,12 +2097,12 @@ pub const Object = struct {...@@ -2104,12 +2097,12 @@ pub const Object = struct {
21042097
2105 return o.builder.debugStructType(2098 return o.builder.debugStructType(
2106 name,2099 name,
2107 null, // File2100 null, // file
2108 o.debug_compile_unit.unwrap().?, // Scope2101 o.debug_compile_unit.unwrap().?, // scope
2109 0, // Line2102 0, // line
2110 null, // Underlying type2103 null, // underlying type
2111 ty.abiSize(zcu) * 8,2104 ty.abiSize(zcu) * 8,
2112 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,2105 ty.abiAlignment(zcu).toByteUnits().? * 8,
2113 try o.builder.metadataTuple(&.{2106 try o.builder.metadataTuple(&.{
2114 debug_payload_type,2107 debug_payload_type,
2115 debug_some_type,2108 debug_some_type,
...@@ -2125,30 +2118,29 @@ pub const Object = struct {...@@ -2125,30 +2118,29 @@ pub const Object = struct {
2125 const payload_size = payload_ty.abiSize(zcu);2118 const payload_size = payload_ty.abiSize(zcu);
2126 const payload_align = payload_ty.abiAlignment(zcu);2119 const payload_align = payload_ty.abiAlignment(zcu);
21272120
2128 const error_index: u1, const payload_index: u1, const error_offset: u64, const payload_offset: u64 = fields: {2121 const error_offset: u64, const payload_offset: u64 = offsets: {
2129 if (error_align.compare(.gt, payload_align)) {2122 if (error_align.compare(.gt, payload_align)) {
2130 break :fields .{ 0, 1, 0, payload_align.forward(error_size) };2123 break :offsets .{ 0, payload_align.forward(error_size) };
2131 } else {2124 } else {
2132 break :fields .{ 1, 0, error_align.forward(payload_size), 0 };2125 break :offsets .{ error_align.forward(payload_size), 0 };
2133 }2126 }
2134 };2127 };
21352128
2136 var fields: [2]Builder.Metadata = undefined;2129 const error_field = try o.builder.debugMemberType(
2137 fields[error_index] = try o.builder.debugMemberType(
2138 try o.builder.metadataString("error"),2130 try o.builder.metadataString("error"),
2139 null, // File2131 null, // file
2140 ty_fwd_ref,2132 ty_fwd_ref,
2141 0, // Line2133 0, // line
2142 try o.getDebugType(pt, error_ty),2134 try o.getDebugType(pt, error_ty),
2143 error_size * 8,2135 error_size * 8,
2144 error_align.toByteUnits().? * 8,2136 error_align.toByteUnits().? * 8,
2145 error_offset * 8,2137 error_offset * 8,
2146 );2138 );
2147 fields[payload_index] = try o.builder.debugMemberType(2139 const payload_field = try o.builder.debugMemberType(
2148 try o.builder.metadataString("payload"),2140 try o.builder.metadataString("payload"),
2149 null, // File2141 null, // file
2150 ty_fwd_ref,2142 ty_fwd_ref, // scope
2151 0, // Line2143 0, // line
2152 try o.getDebugType(pt, payload_ty),2144 try o.getDebugType(pt, payload_ty),
2153 payload_size * 8,2145 payload_size * 8,
2154 payload_align.toByteUnits().? * 8,2146 payload_align.toByteUnits().? * 8,
...@@ -2163,32 +2155,21 @@ pub const Object = struct {...@@ -2163,32 +2155,21 @@ pub const Object = struct {
2163 null, // Underlying type2155 null, // Underlying type
2164 ty.abiSize(zcu) * 8,2156 ty.abiSize(zcu) * 8,
2165 ty.abiAlignment(zcu).toByteUnits().? * 8,2157 ty.abiAlignment(zcu).toByteUnits().? * 8,
2166 try o.builder.metadataTuple(&fields),2158 try o.builder.metadataTuple(&.{ error_field, payload_field }),
2167 );2159 );
2168 },2160 },
2169 .error_set => {2161 .error_set => {
2170 assert(ty.toIntern() != .anyerror_type); // handled specially in `updateConst`; will be populated by `emit` instead2162 assert(ty.toIntern() != .anyerror_type); // handled specially in `updateConst`; will be populated by `emit` instead
2171 // Error sets are just named wrappers around `anyerror`.2163 // Error sets are just named wrappers around `anyerror`.
2172 // MLUGG TODO: these should use DW_TAG_typedef instead, but std.zig.llvm.Builder currently lacks support for those.2164 return o.builder.debugTypedefType(
2173 const anyerror_member = try o.builder.debugMemberType(
2174 try o.builder.metadataString("error"),
2175 null, // file
2176 ty_fwd_ref,
2177 0, // line
2178 try o.getDebugType(pt, .anyerror),
2179 ty.abiSize(zcu) * 8,
2180 ty.abiAlignment(zcu).toByteUnits().? * 8,
2181 0, // offset
2182 );
2183 return o.builder.debugStructType(
2184 name,2165 name,
2185 null, // file2166 null, // file
2186 o.debug_compile_unit.unwrap().?, // scope2167 o.debug_compile_unit.unwrap().?, // scope
2187 0, // line2168 0, // line
2188 null, // underlying type2169 try o.getDebugType(pt, .anyerror),
2189 ty.abiSize(zcu) * 8,2170 ty.abiSize(zcu) * 8,
2190 ty.abiAlignment(zcu).toByteUnits().? * 8,2171 ty.abiAlignment(zcu).toByteUnits().? * 8,
2191 try o.builder.metadataTuple(&.{anyerror_member}),2172 0, // offset
2192 );2173 );
2193 },2174 },
2194 .@"fn" => {2175 .@"fn" => {
...@@ -2570,14 +2551,22 @@ pub const Object = struct {...@@ -2570,14 +2551,22 @@ pub const Object = struct {
2570 const error_set_bits = zcu.errorSetBits();2551 const error_set_bits = zcu.errorSetBits();
2571 const error_names = ip.global_error_set.getNamesFromMainThread();2552 const error_names = ip.global_error_set.getNamesFromMainThread();
25722553
2573 const enumerators = try gpa.alloc(Builder.Metadata, error_names.len);2554 const enumerators = try gpa.alloc(Builder.Metadata, error_names.len + 1);
2574 defer gpa.free(enumerators);2555 defer gpa.free(enumerators);
25752556
2576 for (enumerators, error_names, 1..) |*out, error_name, error_value| {2557 // The value 0 means "no error" in optionals and error unions.
2558 enumerators[0] = try o.builder.debugEnumerator(
2559 try o.builder.metadataString("null"),
2560 true, // unsigned,
2561 error_set_bits,
2562 .{ .limbs = &.{0}, .positive = true }, // zero
2563 );
2564
2565 for (enumerators[1..], error_names, 1..) |*out, error_name, error_value| {
2577 var space: Value.BigIntSpace = undefined;2566 var space: Value.BigIntSpace = undefined;
2578 var bigint: std.math.big.int.Mutable = .init(&space.limbs, error_value);2567 var bigint: std.math.big.int.Mutable = .init(&space.limbs, error_value);
2579 out.* = try o.builder.debugEnumerator(2568 out.* = try o.builder.debugEnumerator(
2580 try o.builder.metadataString(error_name.toSlice(ip)),2569 try o.builder.metadataStringFmt("error.{f}", .{error_name.fmtId(ip)}),
2581 true, // unsigned2570 true, // unsigned
2582 error_set_bits,2571 error_set_bits,
2583 bigint.toConst(),2572 bigint.toConst(),
...@@ -3452,84 +3441,6 @@ pub const Object = struct {...@@ -3452,84 +3441,6 @@ pub const Object = struct {
3452 );3441 );
3453 }3442 }
34543443
3455 fn lowerValueToInt(o: *Object, pt: Zcu.PerThread, llvm_int_ty: Builder.Type, arg_val: InternPool.Index) Error!Builder.Constant {
3456 const zcu = pt.zcu;
3457 const ip = &zcu.intern_pool;
3458 const target = zcu.getTarget();
3459
3460 const val = Value.fromInterned(arg_val);
3461 const val_key = ip.indexToKey(val.toIntern());
3462
3463 if (val.isUndef(zcu)) return o.builder.undefConst(llvm_int_ty);
3464
3465 const ty = Type.fromInterned(val_key.typeOf());
3466 switch (val_key) {
3467 .@"extern" => |@"extern"| {
3468 const function_index = try o.resolveLlvmFunction(pt, @"extern".owner_nav);
3469 const ptr = function_index.ptrConst(&o.builder).global.toConst();
3470 return o.builder.convConst(ptr, llvm_int_ty);
3471 },
3472 .func => |func| {
3473 const function_index = try o.resolveLlvmFunction(pt, func.owner_nav);
3474 const ptr = function_index.ptrConst(&o.builder).global.toConst();
3475 return o.builder.convConst(ptr, llvm_int_ty);
3476 },
3477 .ptr => return o.builder.convConst(try o.lowerPtr(pt, arg_val, 0), llvm_int_ty),
3478 .aggregate => switch (ip.indexToKey(ty.toIntern())) {
3479 .struct_type, .vector_type => {},
3480 else => unreachable,
3481 },
3482 .un => |un| {
3483 const layout = ty.unionGetLayout(zcu);
3484 if (layout.payload_size == 0) return o.lowerValue(pt, un.tag);
3485
3486 const union_obj = zcu.typeToUnion(ty).?;
3487 const container_layout = union_obj.layout;
3488
3489 assert(container_layout == .@"packed");
3490
3491 var need_unnamed = false;
3492 if (un.tag == .none) {
3493 assert(layout.tag_size == 0);
3494 const union_val = try o.lowerValueToInt(pt, llvm_int_ty, un.val);
3495
3496 need_unnamed = true;
3497 return union_val;
3498 }
3499 const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?;
3500 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
3501 if (!field_ty.hasRuntimeBits(zcu)) return o.builder.intConst(llvm_int_ty, 0);
3502 return o.lowerValueToInt(pt, llvm_int_ty, un.val);
3503 },
3504 .simple_value => |simple_value| switch (simple_value) {
3505 .false, .true => {},
3506 else => unreachable,
3507 },
3508 .int,
3509 .float,
3510 .enum_tag,
3511 => {},
3512 .opt => {}, // pointer like optional expected
3513 else => unreachable,
3514 }
3515 var stack = std.heap.stackFallback(32, o.gpa);
3516 const allocator = stack.get();
3517
3518 const bits: usize = @intCast(ty.bitSize(zcu));
3519
3520 const buffer = try allocator.alloc(u8, (bits + 7) / 8);
3521 defer allocator.free(buffer);
3522 const limbs = try allocator.alloc(std.math.big.Limb, std.math.big.int.calcTwosCompLimbCount(bits));
3523 defer allocator.free(limbs);
3524
3525 val.writeToPackedMemory(pt, buffer, 0) catch unreachable;
3526
3527 var big: std.math.big.int.Mutable = .init(limbs, 0);
3528 big.readTwosComplement(buffer, bits, target.cpu.arch.endian(), .unsigned);
3529
3530 return o.builder.bigIntConst(llvm_int_ty, big.toConst());
3531 }
3532
3533 fn lowerValue(o: *Object, pt: Zcu.PerThread, arg_val: InternPool.Index) Error!Builder.Constant {3444 fn lowerValue(o: *Object, pt: Zcu.PerThread, arg_val: InternPool.Index) Error!Builder.Constant {
3534 const zcu = pt.zcu;3445 const zcu = pt.zcu;
3535 const ip = &zcu.intern_pool;3446 const ip = &zcu.intern_pool;