| ... | ... | @@ -7640,7 +7640,6 @@ pub const Metadata = enum(u32) { |
| 7640 | 7640 | pub fn isInline(tag: Tag) bool { |
| 7641 | 7641 | return switch (tag) { |
| 7642 | 7642 | .none, |
| 7643 | | .tuple, |
| 7644 | 7643 | .expression, |
| 7645 | 7644 | .constant, |
| 7646 | 7645 | => true, |
| ... | ... | @@ -7673,6 +7672,7 @@ pub const Metadata = enum(u32) { |
| 7673 | 7672 | .enumerator_signed_positive, |
| 7674 | 7673 | .enumerator_signed_negative, |
| 7675 | 7674 | .subrange, |
| 7675 | .tuple, |
| 7676 | 7676 | .module_flag, |
| 7677 | 7677 | .local_var, |
| 7678 | 7678 | .parameter, |
| ... | ... | @@ -7988,58 +7988,31 @@ pub const Metadata = enum(u32) { |
| 7988 | 7988 | need_comma: bool, |
| 7989 | 7989 | map: std.AutoArrayHashMapUnmanaged(Metadata, void) = .{}, |
| 7990 | 7990 | |
| 7991 | | fn unwrapAssumeExists(formatter: *Formatter, item: Metadata) FormatData.Item { |
| 7992 | | if (item == .none) return .none; |
| 7993 | | const unwrapped_metadata = item.unwrap(formatter.builder); |
| 7994 | | const tag = formatter.builder.metadata_items.items(.tag)[@intFromEnum(unwrapped_metadata)]; |
| 7995 | | return if (tag.isInline()) |
| 7996 | | .{ .@"inline" = unwrapped_metadata } |
| 7997 | | else |
| 7998 | | .{ .index = @intCast(formatter.map.getIndex(unwrapped_metadata).?) }; |
| 7999 | | } |
| 8000 | | fn unwrap(formatter: *Formatter, item: Metadata) Allocator.Error!FormatData.Item { |
| 8001 | | if (item == .none) return .none; |
| 8002 | | const builder = formatter.builder; |
| 8003 | | const unwrapped_metadata = item.unwrap(builder); |
| 8004 | | const tag = formatter.builder.metadata_items.items(.tag)[@intFromEnum(unwrapped_metadata)]; |
| 8005 | | switch (tag) { |
| 8006 | | .none => unreachable, |
| 8007 | | .tuple => { |
| 8008 | | var extra = builder.metadataExtraDataTrail( |
| 8009 | | Metadata.Tuple, |
| 8010 | | builder.metadata_items.items(.data)[@intFromEnum(unwrapped_metadata)], |
| 8011 | | ); |
| 8012 | | const elements = extra.trail.next(extra.data.elements_len, Metadata, builder); |
| 8013 | | for (elements) |element| _ = try formatter.unwrap(element); |
| 8014 | | }, |
| 8015 | | .expression, .constant => {}, |
| 8016 | | else => { |
| 8017 | | assert(!tag.isInline()); |
| 8018 | | const gop = try formatter.map.getOrPutValue(builder.gpa, unwrapped_metadata, {}); |
| 8019 | | return .{ .index = @intCast(gop.index) }; |
| 8020 | | }, |
| 8021 | | } |
| 8022 | | return .{ .@"inline" = unwrapped_metadata }; |
| 8023 | | } |
| 8024 | | |
| 8025 | 7991 | const FormatData = struct { |
| 8026 | 7992 | formatter: *Formatter, |
| 8027 | 7993 | prefix: []const u8 = "", |
| 8028 | | item: FormatData.Item, |
| 7994 | node: Node, |
| 8029 | 7995 | |
| 8030 | | const Item = union(enum) { |
| 7996 | const Node = union(enum) { |
| 8031 | 7997 | none, |
| 8032 | 7998 | @"inline": Metadata, |
| 8033 | 7999 | index: u32, |
| 8000 | |
| 8001 | local_value: ValueData, |
| 8002 | local_metadata: ValueData, |
| 8003 | local_inline: Metadata, |
| 8004 | local_index: u32, |
| 8005 | |
| 8034 | 8006 | string: MetadataString, |
| 8035 | | value: struct { |
| 8036 | | value: Value, |
| 8037 | | function: Function.Index, |
| 8038 | | }, |
| 8039 | 8007 | bool: bool, |
| 8040 | 8008 | u32: u32, |
| 8041 | 8009 | u64: u64, |
| 8042 | 8010 | raw: []const u8, |
| 8011 | |
| 8012 | const ValueData = struct { |
| 8013 | value: Value, |
| 8014 | function: Function.Index, |
| 8015 | }; |
| 8043 | 8016 | }; |
| 8044 | 8017 | }; |
| 8045 | 8018 | fn format( |
| ... | ... | @@ -8048,146 +8021,154 @@ pub const Metadata = enum(u32) { |
| 8048 | 8021 | fmt_opts: std.fmt.FormatOptions, |
| 8049 | 8022 | writer: anytype, |
| 8050 | 8023 | ) @TypeOf(writer).Error!void { |
| 8051 | | if (data.item == .none) return; |
| 8024 | if (data.node == .none) return; |
| 8025 | |
| 8026 | const is_specialized = fmt_str.len > 0 and fmt_str[0] == 'S'; |
| 8027 | const recurse_fmt_str = if (is_specialized) fmt_str[1..] else fmt_str; |
| 8052 | 8028 | |
| 8053 | 8029 | if (data.formatter.need_comma) try writer.writeAll(", "); |
| 8054 | 8030 | defer data.formatter.need_comma = true; |
| 8055 | 8031 | try writer.writeAll(data.prefix); |
| 8056 | 8032 | |
| 8057 | 8033 | const builder = data.formatter.builder; |
| 8058 | | switch (data.item) { |
| 8034 | switch (data.node) { |
| 8059 | 8035 | .none => unreachable, |
| 8060 | | .@"inline" => |item| { |
| 8036 | .@"inline" => |node| { |
| 8061 | 8037 | const needed_comma = data.formatter.need_comma; |
| 8062 | 8038 | defer data.formatter.need_comma = needed_comma; |
| 8063 | 8039 | data.formatter.need_comma = false; |
| 8064 | 8040 | |
| 8065 | | const metadata_item = builder.metadata_items.get(@intFromEnum(item)); |
| 8066 | | switch (metadata_item.tag) { |
| 8067 | | .tuple => { |
| 8068 | | var extra = |
| 8069 | | builder.metadataExtraDataTrail(Metadata.Tuple, metadata_item.data); |
| 8070 | | const elements = |
| 8071 | | extra.trail.next(extra.data.elements_len, Metadata, builder); |
| 8072 | | try writer.writeAll("!{"); |
| 8073 | | for (elements) |element| try format(.{ |
| 8074 | | .formatter = data.formatter, |
| 8075 | | .item = data.formatter.unwrapAssumeExists(element), |
| 8076 | | }, "%", fmt_opts, writer); |
| 8077 | | try writer.writeByte('}'); |
| 8078 | | }, |
| 8041 | const item = builder.metadata_items.get(@intFromEnum(node)); |
| 8042 | switch (item.tag) { |
| 8079 | 8043 | .expression => { |
| 8080 | | var extra = |
| 8081 | | builder.metadataExtraDataTrail(Metadata.Expression, metadata_item.data); |
| 8044 | var extra = builder.metadataExtraDataTrail(Expression, item.data); |
| 8082 | 8045 | const elements = extra.trail.next(extra.data.elements_len, u32, builder); |
| 8083 | 8046 | try writer.writeAll("!DIExpression("); |
| 8084 | 8047 | for (elements) |element| try format(.{ |
| 8085 | 8048 | .formatter = data.formatter, |
| 8086 | | .item = .{ .u64 = element }, |
| 8049 | .node = .{ .u64 = element }, |
| 8087 | 8050 | }, "%", fmt_opts, writer); |
| 8088 | 8051 | try writer.writeByte(')'); |
| 8089 | 8052 | }, |
| 8090 | 8053 | .constant => try Constant.format(.{ |
| 8091 | | .constant = @enumFromInt(metadata_item.data), |
| 8054 | .constant = @enumFromInt(item.data), |
| 8092 | 8055 | .builder = builder, |
| 8093 | | }, fmt_str, fmt_opts, writer), |
| 8056 | }, recurse_fmt_str, fmt_opts, writer), |
| 8094 | 8057 | else => unreachable, |
| 8095 | 8058 | } |
| 8096 | 8059 | }, |
| 8097 | | .index => |item| try writer.print("!{d}", .{item}), |
| 8098 | | .value => |item| switch (item.value.unwrap()) { |
| 8099 | | .instruction, .constant => try Value.format(.{ |
| 8100 | | .value = item.value, |
| 8101 | | .function = item.function, |
| 8102 | | .builder = builder, |
| 8103 | | }, fmt_str, fmt_opts, writer), |
| 8104 | | .metadata => |metadata| if (@intFromEnum(metadata) >= |
| 8105 | | Metadata.first_local_metadata) |
| 8106 | | try Value.format(.{ |
| 8107 | | .value = item.function.ptrConst(builder).debug_values[ |
| 8108 | | @intFromEnum(metadata) - Metadata.first_local_metadata |
| 8109 | | ].toValue(), |
| 8110 | | .function = item.function, |
| 8111 | | .builder = builder, |
| 8112 | | }, "%", fmt_opts, writer) |
| 8113 | | else if (metadata != .none) { |
| 8114 | | if (comptime std.mem.eql(u8, fmt_str, "%")) |
| 8115 | | try writer.print("{%} ", .{Type.metadata.fmt(builder)}); |
| 8116 | | try Metadata.Formatter.format(.{ |
| 8117 | | .formatter = data.formatter, |
| 8118 | | .item = data.formatter.unwrapAssumeExists(metadata), |
| 8119 | | }, "", fmt_opts, writer); |
| 8120 | | }, |
| 8060 | .index => |node| try writer.print("!{d}", .{node}), |
| 8061 | inline .local_value, .local_metadata => |node, tag| try Value.format(.{ |
| 8062 | .value = node.value, |
| 8063 | .function = node.function, |
| 8064 | .builder = builder, |
| 8065 | }, switch (tag) { |
| 8066 | .local_value => recurse_fmt_str, |
| 8067 | .local_metadata => "%", |
| 8068 | else => unreachable, |
| 8069 | }, fmt_opts, writer), |
| 8070 | inline .local_inline, .local_index => |node, tag| { |
| 8071 | if (comptime std.mem.eql(u8, recurse_fmt_str, "%")) |
| 8072 | try writer.print("{%} ", .{Type.metadata.fmt(builder)}); |
| 8073 | try format(.{ |
| 8074 | .formatter = data.formatter, |
| 8075 | .node = @unionInit(FormatData.Node, @tagName(tag)["local_".len..], node), |
| 8076 | }, "", fmt_opts, writer); |
| 8121 | 8077 | }, |
| 8122 | | .string => |item| try writer.print("{}", .{item.fmt(data.formatter.builder)}), |
| 8123 | | inline .bool, .u32, .u64 => |item| try writer.print("{}", .{item}), |
| 8124 | | .raw => |item| try writer.writeAll(item), |
| 8078 | .string => |node| try writer.print("{s}{}", .{ |
| 8079 | if (is_specialized) "" else "!", |
| 8080 | node.fmt(builder), |
| 8081 | }), |
| 8082 | inline .bool, .u32, .u64 => |node| try writer.print("{}", .{node}), |
| 8083 | .raw => |node| try writer.writeAll(node), |
| 8125 | 8084 | } |
| 8126 | 8085 | } |
| 8127 | | inline fn fmt(formatter: *Formatter, prefix: []const u8, item: anytype) switch (@TypeOf(item)) { |
| 8086 | inline fn fmt(formatter: *Formatter, prefix: []const u8, node: anytype) switch (@TypeOf(node)) { |
| 8128 | 8087 | Metadata => Allocator.Error, |
| 8129 | 8088 | else => error{}, |
| 8130 | 8089 | }!std.fmt.Formatter(format) { |
| 8090 | const Node = @TypeOf(node); |
| 8091 | const MaybeNode = switch (@typeInfo(Node)) { |
| 8092 | .Optional => Node, |
| 8093 | .Null => ?noreturn, |
| 8094 | else => ?Node, |
| 8095 | }; |
| 8096 | const Some = @typeInfo(MaybeNode).Optional.child; |
| 8131 | 8097 | return .{ .data = .{ |
| 8132 | 8098 | .formatter = formatter, |
| 8133 | 8099 | .prefix = prefix, |
| 8134 | | .item = switch (@typeInfo(@TypeOf(item))) { |
| 8135 | | .Null => .none, |
| 8136 | | .Enum => |enum_info| switch (@TypeOf(item)) { |
| 8137 | | Metadata => try formatter.unwrap(item), |
| 8138 | | MetadataString => .{ .string = item }, |
| 8100 | .node = if (@as(MaybeNode, node)) |some| switch (@typeInfo(Some)) { |
| 8101 | .Enum => |enum_info| switch (Some) { |
| 8102 | Metadata => switch (some) { |
| 8103 | .none => .none, |
| 8104 | else => try formatter.refUnwrapped(some.unwrap(formatter.builder)), |
| 8105 | }, |
| 8106 | MetadataString => .{ .string = some }, |
| 8139 | 8107 | else => if (enum_info.is_exhaustive) |
| 8140 | | .{ .raw = @tagName(item) } |
| 8108 | .{ .raw = @tagName(some) } |
| 8141 | 8109 | else |
| 8142 | | @compileError("unknown type to format: " ++ @typeName(@TypeOf(item))), |
| 8143 | | }, |
| 8144 | | .EnumLiteral => .{ .raw = @tagName(item) }, |
| 8145 | | .Bool => .{ .bool = item }, |
| 8146 | | .Struct => .{ .u32 = @bitCast(item) }, |
| 8147 | | .Int, .ComptimeInt => .{ .u64 = item }, |
| 8148 | | .Pointer => .{ .raw = item }, |
| 8149 | | .Optional => if (item) |some| switch (@typeInfo(@TypeOf(some))) { |
| 8150 | | .Enum => |enum_info| switch (@TypeOf(some)) { |
| 8151 | | Metadata => try formatter.unwrap(some), |
| 8152 | | MetadataString => .{ .string = some }, |
| 8153 | | else => if (enum_info.is_exhaustive) |
| 8154 | | .{ .raw = @tagName(some) } |
| 8155 | | else |
| 8156 | | @compileError("unknown type to format: " ++ @typeName(@TypeOf(item))), |
| 8157 | | }, |
| 8158 | | .Bool => .{ .bool = some }, |
| 8159 | | .Struct => .{ .u32 = @bitCast(some) }, |
| 8160 | | .Int => .{ .u64 = some }, |
| 8161 | | .Pointer => .{ .raw = some }, |
| 8162 | | else => @compileError("unknown type to format: " ++ @typeName(@TypeOf(item))), |
| 8163 | | } else .none, |
| 8164 | | else => @compileError("unknown type to format: " ++ @typeName(@TypeOf(item))), |
| 8110 | @compileError("unknown type to format: " ++ @typeName(Node)), |
| 8111 | }, |
| 8112 | .EnumLiteral => .{ .raw = @tagName(some) }, |
| 8113 | .Bool => .{ .bool = some }, |
| 8114 | .Struct => .{ .u32 = @bitCast(some) }, |
| 8115 | .Int, .ComptimeInt => .{ .u64 = some }, |
| 8116 | .Pointer => .{ .raw = some }, |
| 8117 | else => @compileError("unknown type to format: " ++ @typeName(Node)), |
| 8118 | } else switch (@typeInfo(Node)) { |
| 8119 | .Optional, .Null => .none, |
| 8120 | else => unreachable, |
| 8165 | 8121 | }, |
| 8166 | 8122 | } }; |
| 8167 | 8123 | } |
| 8168 | 8124 | inline fn fmtLocal( |
| 8169 | 8125 | formatter: *Formatter, |
| 8170 | 8126 | prefix: []const u8, |
| 8171 | | item: Value, |
| 8127 | value: Value, |
| 8172 | 8128 | function: Function.Index, |
| 8173 | 8129 | ) Allocator.Error!std.fmt.Formatter(format) { |
| 8174 | 8130 | return .{ .data = .{ |
| 8175 | 8131 | .formatter = formatter, |
| 8176 | 8132 | .prefix = prefix, |
| 8177 | | .item = .{ .value = .{ |
| 8178 | | .value = switch (item.unwrap()) { |
| 8179 | | .instruction, .constant => item, |
| 8180 | | .metadata => |metadata| value: { |
| 8181 | | const unwrapped_metadata = metadata.unwrap(formatter.builder); |
| 8182 | | if (@intFromEnum(unwrapped_metadata) < Metadata.first_local_metadata) |
| 8183 | | _ = try formatter.unwrap(unwrapped_metadata); |
| 8184 | | break :value unwrapped_metadata.toValue(); |
| 8185 | | }, |
| 8133 | .node = switch (value.unwrap()) { |
| 8134 | .instruction, .constant => .{ .local_value = .{ |
| 8135 | .value = value, |
| 8136 | .function = function, |
| 8137 | } }, |
| 8138 | .metadata => |metadata| if (value == .none) .none else node: { |
| 8139 | const unwrapped = metadata.unwrap(formatter.builder); |
| 8140 | break :node if (@intFromEnum(unwrapped) >= first_local_metadata) |
| 8141 | .{ .local_metadata = .{ |
| 8142 | .value = function.ptrConst(formatter.builder).debug_values[ |
| 8143 | @intFromEnum(unwrapped) - first_local_metadata |
| 8144 | ].toValue(), |
| 8145 | .function = function, |
| 8146 | } } |
| 8147 | else switch (try formatter.refUnwrapped(unwrapped)) { |
| 8148 | .@"inline" => |node| .{ .local_inline = node }, |
| 8149 | .index => |node| .{ .local_index = node }, |
| 8150 | else => unreachable, |
| 8151 | }; |
| 8186 | 8152 | }, |
| 8187 | | .function = function, |
| 8188 | | } }, |
| 8153 | }, |
| 8189 | 8154 | } }; |
| 8190 | 8155 | } |
| 8156 | fn refUnwrapped(formatter: *Formatter, node: Metadata) Allocator.Error!FormatData.Node { |
| 8157 | assert(node != .none); |
| 8158 | assert(@intFromEnum(node) < first_forward_reference); |
| 8159 | const builder = formatter.builder; |
| 8160 | const unwrapped_metadata = node.unwrap(builder); |
| 8161 | const tag = formatter.builder.metadata_items.items(.tag)[@intFromEnum(unwrapped_metadata)]; |
| 8162 | switch (tag) { |
| 8163 | .none => unreachable, |
| 8164 | .expression, .constant => return .{ .@"inline" = unwrapped_metadata }, |
| 8165 | else => { |
| 8166 | assert(!tag.isInline()); |
| 8167 | const gop = try formatter.map.getOrPutValue(builder.gpa, unwrapped_metadata, {}); |
| 8168 | return .{ .index = @intCast(gop.index) }; |
| 8169 | }, |
| 8170 | } |
| 8171 | } |
| 8191 | 8172 | |
| 8192 | 8173 | inline fn specialized( |
| 8193 | 8174 | formatter: *Formatter, |
| ... | ... | @@ -8208,11 +8189,11 @@ pub const Metadata = enum(u32) { |
| 8208 | 8189 | DIGlobalVariable, |
| 8209 | 8190 | DIGlobalVariableExpression, |
| 8210 | 8191 | }, |
| 8211 | | items: anytype, |
| 8192 | nodes: anytype, |
| 8212 | 8193 | writer: anytype, |
| 8213 | 8194 | ) !void { |
| 8214 | 8195 | comptime var fmt_str: []const u8 = ""; |
| 8215 | | const names = comptime std.meta.fieldNames(@TypeOf(items)); |
| 8196 | const names = comptime std.meta.fieldNames(@TypeOf(nodes)); |
| 8216 | 8197 | comptime var fields: [2 + names.len]std.builtin.Type.StructField = undefined; |
| 8217 | 8198 | inline for (fields[0..2], .{ "distinct", "node" }) |*field, name| { |
| 8218 | 8199 | fmt_str = fmt_str ++ "{[" ++ name ++ "]s}"; |
| ... | ... | @@ -8226,7 +8207,7 @@ pub const Metadata = enum(u32) { |
| 8226 | 8207 | } |
| 8227 | 8208 | fmt_str = fmt_str ++ "("; |
| 8228 | 8209 | inline for (fields[2..], names) |*field, name| { |
| 8229 | | fmt_str = fmt_str ++ "{[" ++ name ++ "]}"; |
| 8210 | fmt_str = fmt_str ++ "{[" ++ name ++ "]S}"; |
| 8230 | 8211 | field.* = .{ |
| 8231 | 8212 | .name = name, |
| 8232 | 8213 | .type = std.fmt.Formatter(format), |
| ... | ... | @@ -8247,7 +8228,7 @@ pub const Metadata = enum(u32) { |
| 8247 | 8228 | fmt_args.node = @tagName(node); |
| 8248 | 8229 | inline for (names) |name| @field(fmt_args, name) = try formatter.fmt( |
| 8249 | 8230 | name ++ ": ", |
| 8250 | | @field(items, name), |
| 8231 | @field(nodes, name), |
| 8251 | 8232 | ); |
| 8252 | 8233 | try writer.print(fmt_str, fmt_args); |
| 8253 | 8234 | } |
| ... | ... | @@ -9877,7 +9858,7 @@ pub fn printUnbuffered( |
| 9877 | 9858 | metadata_formatter.need_comma = false; |
| 9878 | 9859 | defer metadata_formatter.need_comma = undefined; |
| 9879 | 9860 | switch (metadata_item.tag) { |
| 9880 | | .none, .tuple, .expression, .constant => unreachable, |
| 9861 | .none, .expression, .constant => unreachable, |
| 9881 | 9862 | .file => { |
| 9882 | 9863 | const extra = self.metadataExtraData(Metadata.File, metadata_item.data); |
| 9883 | 9864 | try metadata_formatter.specialized(.@"!", .DIFile, .{ |
| ... | ... | @@ -10139,11 +10120,20 @@ pub fn printUnbuffered( |
| 10139 | 10120 | .stride = null, |
| 10140 | 10121 | }, writer); |
| 10141 | 10122 | }, |
| 10123 | .tuple => { |
| 10124 | var extra = self.metadataExtraDataTrail(Metadata.Tuple, metadata_item.data); |
| 10125 | const elements = extra.trail.next(extra.data.elements_len, Metadata, self); |
| 10126 | try writer.writeAll("!{"); |
| 10127 | for (elements) |element| try writer.print("{[element]%}", .{ |
| 10128 | .element = try metadata_formatter.fmt("", element), |
| 10129 | }); |
| 10130 | try writer.writeAll("}\n"); |
| 10131 | }, |
| 10142 | 10132 | .module_flag => { |
| 10143 | 10133 | const extra = self.metadataExtraData(Metadata.ModuleFlag, metadata_item.data); |
| 10144 | 10134 | try writer.print("!{{{[behavior]%}{[name]%}{[constant]%}}}\n", .{ |
| 10145 | 10135 | .behavior = try metadata_formatter.fmt("", extra.behavior), |
| 10146 | | .name = try metadata_formatter.fmt("!", extra.name), |
| 10136 | .name = try metadata_formatter.fmt("", extra.name), |
| 10147 | 10137 | .constant = try metadata_formatter.fmt("", extra.constant), |
| 10148 | 10138 | }); |
| 10149 | 10139 | }, |