authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-23 06:17:37+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-23 06:18:10+01:00
log43daed64fe8ce6e18571154adfea37ace2d84a34
tree6dc65fff060be102bb6066da4b237e15ce5f7325
parent1d4a7e123c8ea07d9cc5adcf0f51c640ccc2784a

Builder: change tuple metadata to not be inlined in llvm ir


1 files changed, 128 insertions(+), 138 deletions(-)

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