authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-03-21 14:48:47+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-03-21 15:03:42+02:00
loga31fe0ff12270ba2f957c2a957941a23f2143ad5
tree3381f01ab6a370f0718c24732adf90cb03370a20
parent3d8d6c0a6d7a29396725467672023b5ec3adbce6

stage2: add way to print values with types


9 files changed, 318 insertions(+), 21 deletions(-)

src/Sema.zig+8-8
...@@ -1867,7 +1867,7 @@ fn createTypeName(...@@ -1867,7 +1867,7 @@ fn createTypeName(
1867 const arg_val = sema.resolveConstMaybeUndefVal(block, .unneeded, arg) catch unreachable;1867 const arg_val = sema.resolveConstMaybeUndefVal(block, .unneeded, arg) catch unreachable;
18681868
1869 if (arg_i != 0) try buf.appendSlice(",");1869 if (arg_i != 0) try buf.appendSlice(",");
1870 try buf.writer().print("{}", .{arg_val});1870 try buf.writer().print("{}", .{arg_val.fmtValue(sema.typeOf(arg))});
18711871
1872 arg_i += 1;1872 arg_i += 1;
1873 continue;1873 continue;
...@@ -3673,7 +3673,7 @@ fn zirCompileLog(...@@ -3673,7 +3673,7 @@ fn zirCompileLog(
3673 const arg = sema.resolveInst(arg_ref);3673 const arg = sema.resolveInst(arg_ref);
3674 const arg_ty = sema.typeOf(arg);3674 const arg_ty = sema.typeOf(arg);
3675 if (try sema.resolveMaybeUndefVal(block, src, arg)) |val| {3675 if (try sema.resolveMaybeUndefVal(block, src, arg)) |val| {
3676 try writer.print("@as({}, {})", .{ arg_ty, val });3676 try writer.print("@as({}, {})", .{ arg_ty, val.fmtValue(arg_ty) });
3677 } else {3677 } else {
3678 try writer.print("@as({}, [runtime value])", .{arg_ty});3678 try writer.print("@as({}, [runtime value])", .{arg_ty});
3679 }3679 }
...@@ -5670,7 +5670,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -5670,7 +5670,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
5670 block,5670 block,
5671 src,5671 src,
5672 "enum '{}' has no tag with value {}",5672 "enum '{}' has no tag with value {}",
5673 .{ dest_ty, int_val },5673 .{ dest_ty, int_val.fmtValue(sema.typeOf(operand)) },
5674 );5674 );
5675 errdefer msg.destroy(sema.gpa);5675 errdefer msg.destroy(sema.gpa);
5676 try sema.mod.errNoteNonLazy(5676 try sema.mod.errNoteNonLazy(
...@@ -7900,7 +7900,7 @@ fn validateSwitchItemEnum(...@@ -7900,7 +7900,7 @@ fn validateSwitchItemEnum(
7900 block,7900 block,
7901 src,7901 src,
7902 "enum '{}' has no tag with value '{}'",7902 "enum '{}' has no tag with value '{}'",
7903 .{ item_tv.ty, item_tv.val },7903 .{ item_tv.ty, item_tv.val.fmtValue(item_tv.ty) },
7904 );7904 );
7905 errdefer msg.destroy(sema.gpa);7905 errdefer msg.destroy(sema.gpa);
7906 try sema.mod.errNoteNonLazy(7906 try sema.mod.errNoteNonLazy(
...@@ -17507,7 +17507,7 @@ fn coerce(...@@ -17507,7 +17507,7 @@ fn coerce(
17507 const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse break :float;17507 const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse break :float;
1750817508
17509 if (val.floatHasFraction()) {17509 if (val.floatHasFraction()) {
17510 return sema.fail(block, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val, dest_ty });17510 return sema.fail(block, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val.fmtValue(inst_ty), dest_ty });
17511 }17511 }
17512 const result_val = val.floatToInt(sema.arena, dest_ty, target) catch |err| switch (err) {17512 const result_val = val.floatToInt(sema.arena, dest_ty, target) catch |err| switch (err) {
17513 error.FloatCannotFit => {17513 error.FloatCannotFit => {
...@@ -17521,7 +17521,7 @@ fn coerce(...@@ -17521,7 +17521,7 @@ fn coerce(
17521 if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {17521 if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {
17522 // comptime known integer to other number17522 // comptime known integer to other number
17523 if (!val.intFitsInType(dest_ty, target)) {17523 if (!val.intFitsInType(dest_ty, target)) {
17524 return sema.fail(block, inst_src, "type {} cannot represent integer value {}", .{ dest_ty, val });17524 return sema.fail(block, inst_src, "type {} cannot represent integer value {}", .{ dest_ty, val.fmtValue(inst_ty) });
17525 }17525 }
17526 return try sema.addConstant(dest_ty, val);17526 return try sema.addConstant(dest_ty, val);
17527 }17527 }
...@@ -17556,7 +17556,7 @@ fn coerce(...@@ -17556,7 +17556,7 @@ fn coerce(
17556 block,17556 block,
17557 inst_src,17557 inst_src,
17558 "type {} cannot represent float value {}",17558 "type {} cannot represent float value {}",
17559 .{ dest_ty, val },17559 .{ dest_ty, val.fmtValue(inst_ty) },
17560 );17560 );
17561 }17561 }
17562 return try sema.addConstant(dest_ty, result_val);17562 return try sema.addConstant(dest_ty, result_val);
...@@ -18850,7 +18850,7 @@ fn coerceEnumToUnion(...@@ -18850,7 +18850,7 @@ fn coerceEnumToUnion(
18850 const field_index = union_obj.tag_ty.enumTagFieldIndex(val) orelse {18850 const field_index = union_obj.tag_ty.enumTagFieldIndex(val) orelse {
18851 const msg = msg: {18851 const msg = msg: {
18852 const msg = try sema.errMsg(block, inst_src, "union {} has no tag with value {}", .{18852 const msg = try sema.errMsg(block, inst_src, "union {} has no tag with value {}", .{
18853 union_ty, val,18853 union_ty, val.fmtValue(tag_ty),
18854 });18854 });
18855 errdefer msg.destroy(sema.gpa);18855 errdefer msg.destroy(sema.gpa);
18856 try sema.addDeclaredHereNote(msg, union_ty);18856 try sema.addDeclaredHereNote(msg, union_ty);
src/TypedValue.zig+281
...@@ -42,3 +42,284 @@ pub fn hash(tv: TypedValue, hasher: *std.hash.Wyhash) void {...@@ -42,3 +42,284 @@ pub fn hash(tv: TypedValue, hasher: *std.hash.Wyhash) void {
42pub fn enumToInt(tv: TypedValue, buffer: *Value.Payload.U64) Value {42pub fn enumToInt(tv: TypedValue, buffer: *Value.Payload.U64) Value {
43 return tv.val.enumToInt(tv.ty, buffer);43 return tv.val.enumToInt(tv.ty, buffer);
44}44}
45
46const max_aggregate_items = 100;
47
48pub fn format(
49 tv: TypedValue,
50 comptime fmt: []const u8,
51 options: std.fmt.FormatOptions,
52 writer: anytype,
53) !void {
54 comptime std.debug.assert(fmt.len == 0);
55 return tv.print(options, writer, 3);
56}
57
58pub fn print(
59 tv: TypedValue,
60 options: std.fmt.FormatOptions,
61 writer: anytype,
62 level: u8,
63) @TypeOf(writer).Error!void {
64 var val = tv.val;
65 var ty = tv.ty;
66 while (true) switch (val.tag()) {
67 .u1_type => return writer.writeAll("u1"),
68 .u8_type => return writer.writeAll("u8"),
69 .i8_type => return writer.writeAll("i8"),
70 .u16_type => return writer.writeAll("u16"),
71 .i16_type => return writer.writeAll("i16"),
72 .u32_type => return writer.writeAll("u32"),
73 .i32_type => return writer.writeAll("i32"),
74 .u64_type => return writer.writeAll("u64"),
75 .i64_type => return writer.writeAll("i64"),
76 .u128_type => return writer.writeAll("u128"),
77 .i128_type => return writer.writeAll("i128"),
78 .isize_type => return writer.writeAll("isize"),
79 .usize_type => return writer.writeAll("usize"),
80 .c_short_type => return writer.writeAll("c_short"),
81 .c_ushort_type => return writer.writeAll("c_ushort"),
82 .c_int_type => return writer.writeAll("c_int"),
83 .c_uint_type => return writer.writeAll("c_uint"),
84 .c_long_type => return writer.writeAll("c_long"),
85 .c_ulong_type => return writer.writeAll("c_ulong"),
86 .c_longlong_type => return writer.writeAll("c_longlong"),
87 .c_ulonglong_type => return writer.writeAll("c_ulonglong"),
88 .c_longdouble_type => return writer.writeAll("c_longdouble"),
89 .f16_type => return writer.writeAll("f16"),
90 .f32_type => return writer.writeAll("f32"),
91 .f64_type => return writer.writeAll("f64"),
92 .f80_type => return writer.writeAll("f80"),
93 .f128_type => return writer.writeAll("f128"),
94 .anyopaque_type => return writer.writeAll("anyopaque"),
95 .bool_type => return writer.writeAll("bool"),
96 .void_type => return writer.writeAll("void"),
97 .type_type => return writer.writeAll("type"),
98 .anyerror_type => return writer.writeAll("anyerror"),
99 .comptime_int_type => return writer.writeAll("comptime_int"),
100 .comptime_float_type => return writer.writeAll("comptime_float"),
101 .noreturn_type => return writer.writeAll("noreturn"),
102 .null_type => return writer.writeAll("@Type(.Null)"),
103 .undefined_type => return writer.writeAll("@Type(.Undefined)"),
104 .fn_noreturn_no_args_type => return writer.writeAll("fn() noreturn"),
105 .fn_void_no_args_type => return writer.writeAll("fn() void"),
106 .fn_naked_noreturn_no_args_type => return writer.writeAll("fn() callconv(.Naked) noreturn"),
107 .fn_ccc_void_no_args_type => return writer.writeAll("fn() callconv(.C) void"),
108 .single_const_pointer_to_comptime_int_type => return writer.writeAll("*const comptime_int"),
109 .anyframe_type => return writer.writeAll("anyframe"),
110 .const_slice_u8_type => return writer.writeAll("[]const u8"),
111 .const_slice_u8_sentinel_0_type => return writer.writeAll("[:0]const u8"),
112 .anyerror_void_error_union_type => return writer.writeAll("anyerror!void"),
113
114 .enum_literal_type => return writer.writeAll("@Type(.EnumLiteral)"),
115 .manyptr_u8_type => return writer.writeAll("[*]u8"),
116 .manyptr_const_u8_type => return writer.writeAll("[*]const u8"),
117 .manyptr_const_u8_sentinel_0_type => return writer.writeAll("[*:0]const u8"),
118 .atomic_order_type => return writer.writeAll("std.builtin.AtomicOrder"),
119 .atomic_rmw_op_type => return writer.writeAll("std.builtin.AtomicRmwOp"),
120 .calling_convention_type => return writer.writeAll("std.builtin.CallingConvention"),
121 .address_space_type => return writer.writeAll("std.builtin.AddressSpace"),
122 .float_mode_type => return writer.writeAll("std.builtin.FloatMode"),
123 .reduce_op_type => return writer.writeAll("std.builtin.ReduceOp"),
124 .call_options_type => return writer.writeAll("std.builtin.CallOptions"),
125 .prefetch_options_type => return writer.writeAll("std.builtin.PrefetchOptions"),
126 .export_options_type => return writer.writeAll("std.builtin.ExportOptions"),
127 .extern_options_type => return writer.writeAll("std.builtin.ExternOptions"),
128 .type_info_type => return writer.writeAll("std.builtin.Type"),
129
130 .empty_struct_value => return writer.writeAll(".{}"),
131 .aggregate => {
132 if (level == 0) {
133 return writer.writeAll(".{ ... }");
134 }
135 const vals = val.castTag(.aggregate).?.data;
136 if (ty.zigTypeTag() == .Struct) {
137 try writer.writeAll(".{ ");
138 const struct_fields = ty.structFields();
139 const max_len = std.math.min(struct_fields.count(), max_aggregate_items);
140
141 const field_names = struct_fields.keys();
142 const fields = struct_fields.values();
143
144 var i: u32 = 0;
145 while (i < max_len) : (i += 1) {
146 if (i != 0) try writer.writeAll(", ");
147 try writer.print(".{s} = ", .{field_names[i]});
148 try print(.{
149 .ty = fields[i].ty,
150 .val = vals[i],
151 }, options, writer, level - 1);
152 }
153 return writer.writeAll(" }");
154 } else {
155 try writer.writeAll(".{ ");
156 const elem_ty = ty.elemType2();
157 const max_len = std.math.min(ty.arrayLen(), max_aggregate_items);
158
159 var i: u32 = 0;
160 while (i < max_len) : (i += 1) {
161 if (i != 0) try writer.writeAll(", ");
162 try print(.{
163 .ty = elem_ty,
164 .val = vals[i],
165 }, options, writer, level - 1);
166 }
167 return writer.writeAll(" }");
168 }
169 },
170 .@"union" => {
171 if (level == 0) {
172 return writer.writeAll(".{ ... }");
173 }
174 const union_val = val.castTag(.@"union").?.data;
175 try writer.writeAll(".{ ");
176
177 try print(.{
178 .ty = ty.unionTagType().?,
179 .val = union_val.tag,
180 }, options, writer, level - 1);
181 try writer.writeAll(" = ");
182 try print(.{
183 .ty = ty.unionFieldType(union_val.tag),
184 .val = union_val.val,
185 }, options, writer, level - 1);
186
187 return writer.writeAll(" }");
188 },
189 .null_value => return writer.writeAll("null"),
190 .undef => return writer.writeAll("undefined"),
191 .zero => return writer.writeAll("0"),
192 .one => return writer.writeAll("1"),
193 .void_value => return writer.writeAll("{}"),
194 .unreachable_value => return writer.writeAll("unreachable"),
195 .the_only_possible_value => {
196 val = ty.onePossibleValue().?;
197 },
198 .bool_true => return writer.writeAll("true"),
199 .bool_false => return writer.writeAll("false"),
200 .ty => return val.castTag(.ty).?.data.format("", options, writer),
201 .int_type => {
202 const int_type = val.castTag(.int_type).?.data;
203 return writer.print("{s}{d}", .{
204 if (int_type.signed) "s" else "u",
205 int_type.bits,
206 });
207 },
208 .int_u64 => return std.fmt.formatIntValue(val.castTag(.int_u64).?.data, "", options, writer),
209 .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", options, writer),
210 .int_big_positive => return writer.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}),
211 .int_big_negative => return writer.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}),
212 .function => return writer.print("(function '{s}')", .{val.castTag(.function).?.data.owner_decl.name}),
213 .extern_fn => return writer.writeAll("(extern function)"),
214 .variable => return writer.writeAll("(variable)"),
215 .decl_ref_mut => {
216 const decl = val.castTag(.decl_ref_mut).?.data.decl;
217 if (level == 0) {
218 return writer.print("(decl ref mut '{s}')", .{decl.name});
219 }
220 return print(.{
221 .ty = decl.ty,
222 .val = decl.val,
223 }, options, writer, level - 1);
224 },
225 .decl_ref => {
226 const decl = val.castTag(.decl_ref).?.data;
227 if (level == 0) {
228 return writer.print("(decl ref '{s}')", .{decl.name});
229 }
230 return print(.{
231 .ty = decl.ty,
232 .val = decl.val,
233 }, options, writer, level - 1);
234 },
235 .elem_ptr => {
236 const elem_ptr = val.castTag(.elem_ptr).?.data;
237 try writer.writeAll("&");
238 try print(.{
239 .ty = elem_ptr.elem_ty,
240 .val = elem_ptr.array_ptr,
241 }, options, writer, level - 1);
242 return writer.print("[{}]", .{elem_ptr.index});
243 },
244 .field_ptr => {
245 const field_ptr = val.castTag(.field_ptr).?.data;
246 try writer.writeAll("&");
247 try print(.{
248 .ty = field_ptr.container_ty,
249 .val = field_ptr.container_ptr,
250 }, options, writer, level - 1);
251
252 if (field_ptr.container_ty.zigTypeTag() == .Struct) {
253 const field_name = field_ptr.container_ty.structFields().keys()[field_ptr.field_index];
254 return writer.print(".{s}", .{field_name});
255 } else if (field_ptr.container_ty.zigTypeTag() == .Union) {
256 const field_name = field_ptr.container_ty.unionFields().keys()[field_ptr.field_index];
257 return writer.print(".{s}", .{field_name});
258 } else unreachable;
259 },
260 .empty_array => return writer.writeAll(".{}"),
261 .enum_literal => return writer.print(".{}", .{std.zig.fmtId(val.castTag(.enum_literal).?.data)}),
262 .enum_field_index => {
263 return writer.print(".{s}", .{ty.enumFieldName(val.castTag(.enum_field_index).?.data)});
264 },
265 .bytes => return writer.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}),
266 .repeated => {
267 if (level == 0) {
268 return writer.writeAll(".{ ... }");
269 }
270 var i: u32 = 0;
271 try writer.writeAll(".{ ");
272 const elem_tv = TypedValue{
273 .ty = ty.elemType2(),
274 .val = val.castTag(.repeated).?.data,
275 };
276 while (i < max_aggregate_items) : (i += 1) {
277 if (i != 0) try writer.writeAll(", ");
278 try print(elem_tv, options, writer, level - 1);
279 }
280 return writer.writeAll(" }");
281 },
282 .empty_array_sentinel => {
283 if (level == 0) {
284 return writer.writeAll(".{ (sentinel) }");
285 }
286 try writer.writeAll(".{ ");
287 try print(.{
288 .ty = ty.elemType2(),
289 .val = ty.sentinel().?,
290 }, options, writer, level - 1);
291 return writer.writeAll(" }");
292 },
293 .slice => return writer.writeAll("(slice)"),
294 .float_16 => return writer.print("{}", .{val.castTag(.float_16).?.data}),
295 .float_32 => return writer.print("{}", .{val.castTag(.float_32).?.data}),
296 .float_64 => return writer.print("{}", .{val.castTag(.float_64).?.data}),
297 .float_80 => return writer.print("{}", .{val.castTag(.float_80).?.data}),
298 .float_128 => return writer.print("{}", .{val.castTag(.float_128).?.data}),
299 .@"error" => return writer.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
300 .eu_payload => {
301 val = val.castTag(.eu_payload).?.data;
302 },
303 .opt_payload => {
304 val = val.castTag(.opt_payload).?.data;
305 },
306 .eu_payload_ptr => {
307 try writer.writeAll("&");
308 val = val.castTag(.eu_payload_ptr).?.data.container_ptr;
309 },
310 .opt_payload_ptr => {
311 try writer.writeAll("&");
312 val = val.castTag(.opt_payload_ptr).?.data.container_ptr;
313 },
314
315 // TODO these should not appear in this function
316 .inferred_alloc => return writer.writeAll("(inferred allocation value)"),
317 .inferred_alloc_comptime => return writer.writeAll("(inferred comptime allocation value)"),
318 .bound_fn => {
319 const bound_func = val.castTag(.bound_fn).?.data;
320 return writer.print("(bound_fn %{}(%{})", .{ bound_func.func_inst, bound_func.arg0_inst });
321 },
322 .generic_poison_type => return writer.writeAll("(generic poison type)"),
323 .generic_poison => return writer.writeAll("(generic poison)"),
324 };
325}
src/arch/aarch64/CodeGen.zig+1-1
...@@ -3873,7 +3873,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa...@@ -3873,7 +3873,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa
3873}3873}
38743874
3875fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {3875fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
3876 log.debug("lowerUnnamedConst: ty = {}, val = {}", .{ tv.ty, tv.val });3876 log.debug("lowerUnnamedConst: ty = {}, val = {}", .{ tv.ty, tv.val.fmtDebug() });
3877 const local_sym_index = self.bin_file.lowerUnnamedConst(tv, self.mod_fn.owner_decl) catch |err| {3877 const local_sym_index = self.bin_file.lowerUnnamedConst(tv, self.mod_fn.owner_decl) catch |err| {
3878 return self.fail("lowering unnamed constant failed: {s}", .{@errorName(err)});3878 return self.fail("lowering unnamed constant failed: {s}", .{@errorName(err)});
3879 };3879 };
src/arch/x86_64/CodeGen.zig+1-1
...@@ -5735,7 +5735,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa...@@ -5735,7 +5735,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa
5735}5735}
57365736
5737fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {5737fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
5738 log.debug("lowerUnnamedConst: ty = {}, val = {}", .{ tv.ty, tv.val });5738 log.debug("lowerUnnamedConst: ty = {}, val = {}", .{ tv.ty, tv.val.fmtDebug() });
5739 const local_sym_index = self.bin_file.lowerUnnamedConst(tv, self.mod_fn.owner_decl) catch |err| {5739 const local_sym_index = self.bin_file.lowerUnnamedConst(tv, self.mod_fn.owner_decl) catch |err| {
5740 return self.fail("lowering unnamed constant failed: {s}", .{@errorName(err)});5740 return self.fail("lowering unnamed constant failed: {s}", .{@errorName(err)});
5741 };5741 };
src/codegen.zig+1-1
...@@ -165,7 +165,7 @@ pub fn generateSymbol(...@@ -165,7 +165,7 @@ pub fn generateSymbol(
165 const target = bin_file.options.target;165 const target = bin_file.options.target;
166 const endian = target.cpu.arch.endian();166 const endian = target.cpu.arch.endian();
167167
168 log.debug("generateSymbol: ty = {}, val = {}", .{ typed_value.ty, typed_value.val });168 log.debug("generateSymbol: ty = {}, val = {}", .{ typed_value.ty, typed_value.val.fmtDebug() });
169169
170 if (typed_value.val.isUndefDeep()) {170 if (typed_value.val.isUndefDeep()) {
171 const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));171 const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
src/codegen/llvm.zig+1-1
...@@ -1676,7 +1676,7 @@ pub const DeclGen = struct {...@@ -1676,7 +1676,7 @@ pub const DeclGen = struct {
1676 const decl = dg.decl;1676 const decl = dg.decl;
1677 assert(decl.has_tv);1677 assert(decl.has_tv);
16781678
1679 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val });1679 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val.fmtDebug() });
16801680
1681 if (decl.val.castTag(.function)) |func_payload| {1681 if (decl.val.castTag(.function)) |func_payload| {
1682 _ = func_payload;1682 _ = func_payload;
src/print_air.zig+1-1
...@@ -491,7 +491,7 @@ const Writer = struct {...@@ -491,7 +491,7 @@ const Writer = struct {
491 fn writeConstant(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {491 fn writeConstant(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
492 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;492 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
493 const val = w.air.values[ty_pl.payload];493 const val = w.air.values[ty_pl.payload];
494 try s.print("{}, {}", .{ w.air.getRefType(ty_pl.ty), val });494 try s.print("{}, {}", .{ w.air.getRefType(ty_pl.ty), val.fmtDebug() });
495 }495 }
496496
497 fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {497 fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
src/type.zig+5-7
...@@ -1633,7 +1633,7 @@ pub const Type = extern union {...@@ -1633,7 +1633,7 @@ pub const Type = extern union {
1633 },1633 },
1634 .array_sentinel => {1634 .array_sentinel => {
1635 const payload = ty.castTag(.array_sentinel).?.data;1635 const payload = ty.castTag(.array_sentinel).?.data;
1636 try writer.print("[{d}:{}]", .{ payload.len, payload.sentinel });1636 try writer.print("[{d}:{}]", .{ payload.len, payload.sentinel.fmtValue(payload.elem_type) });
1637 ty = payload.elem_type;1637 ty = payload.elem_type;
1638 continue;1638 continue;
1639 },1639 },
...@@ -1648,8 +1648,7 @@ pub const Type = extern union {...@@ -1648,8 +1648,7 @@ pub const Type = extern union {
1648 }1648 }
1649 try field_ty.format("", .{}, writer);1649 try field_ty.format("", .{}, writer);
1650 if (val.tag() != .unreachable_value) {1650 if (val.tag() != .unreachable_value) {
1651 try writer.writeAll(" = ");1651 try writer.print(" = {}", .{val.fmtValue(field_ty)});
1652 try val.format("", .{}, writer);
1653 }1652 }
1654 }1653 }
1655 try writer.writeAll("}");1654 try writer.writeAll("}");
...@@ -1668,8 +1667,7 @@ pub const Type = extern union {...@@ -1668,8 +1667,7 @@ pub const Type = extern union {
1668 try writer.writeAll(": ");1667 try writer.writeAll(": ");
1669 try field_ty.format("", .{}, writer);1668 try field_ty.format("", .{}, writer);
1670 if (val.tag() != .unreachable_value) {1669 if (val.tag() != .unreachable_value) {
1671 try writer.writeAll(" = ");1670 try writer.print(" = {}", .{val.fmtValue(field_ty)});
1672 try val.format("", .{}, writer);
1673 }1671 }
1674 }1672 }
1675 try writer.writeAll("}");1673 try writer.writeAll("}");
...@@ -1754,8 +1752,8 @@ pub const Type = extern union {...@@ -1754,8 +1752,8 @@ pub const Type = extern union {
1754 const payload = ty.castTag(.pointer).?.data;1752 const payload = ty.castTag(.pointer).?.data;
1755 if (payload.sentinel) |some| switch (payload.size) {1753 if (payload.sentinel) |some| switch (payload.size) {
1756 .One, .C => unreachable,1754 .One, .C => unreachable,
1757 .Many => try writer.print("[*:{}]", .{some}),1755 .Many => try writer.print("[*:{}]", .{some.fmtValue(payload.pointee_type)}),
1758 .Slice => try writer.print("[:{}]", .{some}),1756 .Slice => try writer.print("[:{}]", .{some.fmtValue(payload.pointee_type)}),
1759 } else switch (payload.size) {1757 } else switch (payload.size) {
1760 .One => try writer.writeAll("*"),1758 .One => try writer.writeAll("*"),
1761 .Many => try writer.writeAll("[*]"),1759 .Many => try writer.writeAll("[*]"),
src/value.zig+19-1
...@@ -600,9 +600,17 @@ pub const Value = extern union {...@@ -600,9 +600,17 @@ pub const Value = extern union {
600 return Value{ .ptr_otherwise = &new_payload.base };600 return Value{ .ptr_otherwise = &new_payload.base };
601 }601 }
602602
603 pub fn format(val: Value, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
604 _ = val;
605 _ = fmt;
606 _ = options;
607 _ = writer;
608 @compileError("do not use format values directly; use either fmtDebug or fmtValue");
609 }
610
603 /// TODO this should become a debug dump() function. In order to print values in a meaningful way611 /// TODO this should become a debug dump() function. In order to print values in a meaningful way
604 /// we also need access to the type.612 /// we also need access to the type.
605 pub fn format(613 pub fn dump(
606 start_val: Value,614 start_val: Value,
607 comptime fmt: []const u8,615 comptime fmt: []const u8,
608 options: std.fmt.FormatOptions,616 options: std.fmt.FormatOptions,
...@@ -766,6 +774,16 @@ pub const Value = extern union {...@@ -766,6 +774,16 @@ pub const Value = extern union {
766 };774 };
767 }775 }
768776
777 pub fn fmtDebug(val: Value) std.fmt.Formatter(dump) {
778 return .{ .data = val };
779 }
780
781 const TypedValue = @import("TypedValue.zig");
782
783 pub fn fmtValue(val: Value, ty: Type) std.fmt.Formatter(TypedValue.format) {
784 return .{ .data = .{ .ty = ty, .val = val } };
785 }
786
769 /// Asserts that the value is representable as an array of bytes.787 /// Asserts that the value is representable as an array of bytes.
770 /// Copies the value into a freshly allocated slice of memory, which is owned by the caller.788 /// Copies the value into a freshly allocated slice of memory, which is owned by the caller.
771 pub fn toAllocatedBytes(val: Value, ty: Type, allocator: Allocator) ![]u8 {789 pub fn toAllocatedBytes(val: Value, ty: Type, allocator: Allocator) ![]u8 {