fn format(data: FormatData, w: *Writer) Writer.Error!void {
assert(data.type != .none);
if (data.mode == .m) {
const item = data.builder.type_items.items[@backingInt(data.type)];
switch (item.tag) {
.simple => try w.writeAll(switch (@as(Simple, @fromBackingInt(@intCast(item.data)))) {
.void => "isVoid",
.half => "f16",
.bfloat => "bf16",
.float => "f32",
.double => "f64",
.fp128 => "f128",
.x86_fp80 => "f80",
.ppc_fp128 => "ppcf128",
.x86_amx => "x86amx",
.x86_mmx => "x86mmx",
.label, .token => unreachable,
.metadata => "Metadata",
}),
.function, .vararg_function => |kind| {
var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);
const params = extra.trail.next(extra.data.params_len, Type, data.builder);
try w.print("f_{f}", .{extra.data.ret.fmt(data.builder, .m)});
for (params) |param| try w.print("{f}", .{param.fmt(data.builder, .m)});
switch (kind) {
.function => {},
.vararg_function => try w.writeAll("vararg"),
else => unreachable,
}
try w.writeByte('f');
},
.integer => try w.print("i{d}", .{item.data}),
.pointer => try w.print("p{d}", .{item.data}),
.target => {
var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
const types = extra.trail.next(extra.data.types_len, Type, data.builder);
const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);
try w.print("t{s}", .{extra.data.name.slice(data.builder).?});
for (types) |ty| try w.print("_{f}", .{ty.fmt(data.builder, .m)});
for (ints) |int| try w.print("_{d}", .{int});
try w.writeByte('t');
},
.vector, .scalable_vector => |kind| {
const extra = data.builder.typeExtraData(Type.Vector, item.data);
try w.print("{s}v{d}{f}", .{
switch (kind) {
.vector => "",
.scalable_vector => "nx",
else => unreachable,
},
extra.len,
extra.child.fmt(data.builder, .m),
});
},
inline .small_array, .array => |kind| {
const extra = data.builder.typeExtraData(switch (kind) {
.small_array => Type.Vector,
.array => Type.Array,
else => unreachable,
}, item.data);
try w.print("a{d}{f}", .{ extra.length(), extra.child.fmt(data.builder, .m) });
},
.structure, .packed_structure => {
var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);
const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);
try w.writeAll("sl_");
for (fields) |field| try w.print("{f}", .{field.fmt(data.builder, .m)});
try w.writeByte('s');
},
.named_structure => {
const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);
try w.writeAll("s_");
if (extra.id.slice(data.builder)) |id| try w.writeAll(id);
},
}
return;
}
if (std.enums.tagName(Type, data.type)) |name| return w.writeAll(name);
const item = data.builder.type_items.items[@backingInt(data.type)];
switch (item.tag) {
.simple => unreachable,
.function, .vararg_function => |kind| {
var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);
const params = extra.trail.next(extra.data.params_len, Type, data.builder);
if (data.mode != .gt)
try w.print("{f} ", .{extra.data.ret.fmt(data.builder, .percent)});
if (data.mode != .lt) {
try w.writeByte('(');
for (params, 0..) |param, index| {
if (index > 0) try w.writeAll(", ");
try w.print("{f}", .{param.fmt(data.builder, .percent)});
}
switch (kind) {
.function => {},
.vararg_function => {
if (params.len > 0) try w.writeAll(", ");
try w.writeAll("...");
},
else => unreachable,
}
try w.writeByte(')');
}
},
.integer => try w.print("i{d}", .{item.data}),
.pointer => try w.print("ptr{f}", .{@as(AddrSpace, @fromBackingInt(@intCast(item.data))).fmt(" ")}),
.target => {
var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
const types = extra.trail.next(extra.data.types_len, Type, data.builder);
const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);
try w.print(
\\target({f}
, .{extra.data.name.fmtQ(data.builder)});
for (types) |ty| try w.print(", {f}", .{ty.fmt(data.builder, .percent)});
for (ints) |int| try w.print(", {d}", .{int});
try w.writeByte(')');
},
.vector, .scalable_vector => |kind| {
const extra = data.builder.typeExtraData(Type.Vector, item.data);
try w.print("<{s}{d} x {f}>", .{
switch (kind) {
.vector => "",
.scalable_vector => "vscale x ",
else => unreachable,
},
extra.len,
extra.child.fmt(data.builder, .percent),
});
},
inline .small_array, .array => |kind| {
const extra = data.builder.typeExtraData(switch (kind) {
.small_array => Type.Vector,
.array => Type.Array,
else => unreachable,
}, item.data);
try w.print("[{d} x {f}]", .{ extra.length(), extra.child.fmt(data.builder, .percent) });
},
.structure, .packed_structure => |kind| {
var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);
const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);
switch (kind) {
.structure => {},
.packed_structure => try w.writeByte('<'),
else => unreachable,
}
try w.writeAll("{ ");
for (fields, 0..) |field, index| {
if (index > 0) try w.writeAll(", ");
try w.print("{f}", .{field.fmt(data.builder, .percent)});
}
try w.writeAll(" }");
switch (kind) {
.structure => {},
.packed_structure => try w.writeByte('>'),
else => unreachable,
}
},
.named_structure => {
const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);
if (data.mode == .percent) try w.print("%{f}", .{
extra.id.fmt(data.builder),
}) else switch (extra.body) {
.none => try w.writeAll("opaque"),
else => try format(.{
.type = extra.body,
.builder = data.builder,
.mode = data.mode,
}, w),
}
},
}
}