diff --git a/CMakeLists.txt b/CMakeLists.txt index 2722acf0a4a522428688c4d6b0c125d13599db28..081872fbdfbc1672febe68a3f57d2685ebeb5a39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -526,7 +526,6 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/src/Package/Fetch.zig" "${CMAKE_SOURCE_DIR}/src/RangeSet.zig" "${CMAKE_SOURCE_DIR}/src/Sema.zig" - "${CMAKE_SOURCE_DIR}/src/TypedValue.zig" "${CMAKE_SOURCE_DIR}/src/Value.zig" "${CMAKE_SOURCE_DIR}/src/arch/aarch64/CodeGen.zig" "${CMAKE_SOURCE_DIR}/src/arch/aarch64/Emit.zig" @@ -634,9 +633,11 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/src/main.zig" "${CMAKE_SOURCE_DIR}/src/mingw.zig" "${CMAKE_SOURCE_DIR}/src/musl.zig" + "${CMAKE_SOURCE_DIR}/src/mutable_value.zig" "${CMAKE_SOURCE_DIR}/src/print_air.zig" "${CMAKE_SOURCE_DIR}/src/print_env.zig" "${CMAKE_SOURCE_DIR}/src/print_targets.zig" + "${CMAKE_SOURCE_DIR}/src/print_value.zig" "${CMAKE_SOURCE_DIR}/src/print_zir.zig" "${CMAKE_SOURCE_DIR}/src/register_manager.zig" "${CMAKE_SOURCE_DIR}/src/target.zig" diff --git a/src/Sema.zig b/src/Sema.zig index 18f4e01dd24846d55c46d5106f2b97e8ce8db774..d21fed6910eda7f95d8cc959bec8d8d72addaf06 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2272,7 +2272,7 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: if (int_ty.zigTypeTag(mod) == .Vector) { const msg = msg: { const msg = try sema.errMsg(block, src, "overflow of vector type '{}' with value '{}'", .{ - int_ty.fmt(sema.mod), val.fmtValue(int_ty, sema.mod), + int_ty.fmt(sema.mod), val.fmtValue(sema.mod), }); errdefer msg.destroy(sema.gpa); try sema.errNote(block, src, msg, "when computing vector element at index '{d}'", .{vector_index}); @@ -2281,7 +2281,7 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: return sema.failWithOwnedErrorMsg(block, msg); } return sema.fail(block, src, "overflow of integer type '{}' with value '{}'", .{ - int_ty.fmt(sema.mod), val.fmtValue(int_ty, sema.mod), + int_ty.fmt(sema.mod), val.fmtValue(sema.mod), }); } @@ -2914,7 +2914,7 @@ fn createAnonymousDeclTypeNamed( return sema.createAnonymousDeclTypeNamed(block, src, val, .anon, anon_prefix, null); if (arg_i != 0) try writer.writeByte(','); - try writer.print("{}", .{arg_val.fmtValue(sema.typeOf(arg), sema.mod)}); + try writer.print("{}", .{arg_val.fmtValue(sema.mod)}); arg_i += 1; continue; @@ -3186,7 +3186,7 @@ fn zirEnumDecl( }).lazy; const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = conflict.prev_field_idx }).lazy; const msg = msg: { - const msg = try sema.errMsg(block, value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(int_tag_ty, sema.mod)}); + const msg = try sema.errMsg(block, value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(sema.mod)}); errdefer msg.destroy(gpa); try sema.errNote(block, other_field_src, msg, "other occurrence here", .{}); break :msg msg; @@ -3206,7 +3206,7 @@ fn zirEnumDecl( const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy; const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = conflict.prev_field_idx }).lazy; const msg = msg: { - const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(int_tag_ty, sema.mod)}); + const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(sema.mod)}); errdefer msg.destroy(gpa); try sema.errNote(block, other_field_src, msg, "other occurrence here", .{}); break :msg msg; @@ -3228,7 +3228,7 @@ fn zirEnumDecl( .range = if (has_tag_value) .value else .name, }).lazy; const msg = try sema.errMsg(block, value_src, "enumeration value '{}' too large for type '{}'", .{ - last_tag_val.?.fmtValue(int_tag_ty, mod), int_tag_ty.fmt(mod), + last_tag_val.?.fmtValue(mod), int_tag_ty.fmt(mod), }); return sema.failWithOwnedErrorMsg(block, msg); } @@ -4381,10 +4381,10 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. .input_index = len_idx, } }; try sema.errNote(block, a_src, msg, "length {} here", .{ - v.fmtValue(Type.usize, sema.mod), + v.fmtValue(sema.mod), }); try sema.errNote(block, arg_src, msg, "length {} here", .{ - arg_val.fmtValue(Type.usize, sema.mod), + arg_val.fmtValue(sema.mod), }); break :msg msg; }; @@ -5794,7 +5794,7 @@ fn zirCompileLog( const arg_ty = sema.typeOf(arg); if (try sema.resolveValueResolveLazy(arg)) |val| { try writer.print("@as({}, {})", .{ - arg_ty.fmt(mod), val.fmtValue(arg_ty, mod), + arg_ty.fmt(mod), val.fmtValue(mod), }); } else { try writer.print("@as({}, [runtime value])", .{arg_ty.fmt(mod)}); @@ -8880,7 +8880,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError return Air.internedToRef((try mod.getCoerced(int_val, dest_ty)).toIntern()); } return sema.fail(block, src, "int value '{}' out of range of non-exhaustive enum '{}'", .{ - int_val.fmtValue(sema.typeOf(operand), mod), dest_ty.fmt(mod), + int_val.fmtValue(mod), dest_ty.fmt(mod), }); } if (int_val.isUndef(mod)) { @@ -8888,7 +8888,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError } if (!(try sema.enumHasInt(dest_ty, int_val))) { return sema.fail(block, src, "enum '{}' has no tag with value '{}'", .{ - dest_ty.fmt(mod), int_val.fmtValue(sema.typeOf(operand), mod), + dest_ty.fmt(mod), int_val.fmtValue(mod), }); } return Air.internedToRef((try mod.getCoerced(int_val, dest_ty)).toIntern()); @@ -13934,7 +13934,7 @@ fn zirShl( const rhs_elem = try rhs_val.elemValue(mod, i); if (rhs_elem.compareHetero(.gte, bit_value, mod)) { return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{ - rhs_elem.fmtValue(scalar_ty, mod), + rhs_elem.fmtValue(mod), i, scalar_ty.fmt(mod), }); @@ -13942,7 +13942,7 @@ fn zirShl( } } else if (rhs_val.compareHetero(.gte, bit_value, mod)) { return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{ - rhs_val.fmtValue(scalar_ty, mod), + rhs_val.fmtValue(mod), scalar_ty.fmt(mod), }); } @@ -13953,14 +13953,14 @@ fn zirShl( const rhs_elem = try rhs_val.elemValue(mod, i); if (rhs_elem.compareHetero(.lt, try mod.intValue(scalar_rhs_ty, 0), mod)) { return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{ - rhs_elem.fmtValue(scalar_ty, mod), + rhs_elem.fmtValue(mod), i, }); } } } else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) { return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{ - rhs_val.fmtValue(scalar_ty, mod), + rhs_val.fmtValue(mod), }); } } @@ -14099,7 +14099,7 @@ fn zirShr( const rhs_elem = try rhs_val.elemValue(mod, i); if (rhs_elem.compareHetero(.gte, bit_value, mod)) { return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{ - rhs_elem.fmtValue(scalar_ty, mod), + rhs_elem.fmtValue(mod), i, scalar_ty.fmt(mod), }); @@ -14107,7 +14107,7 @@ fn zirShr( } } else if (rhs_val.compareHetero(.gte, bit_value, mod)) { return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{ - rhs_val.fmtValue(scalar_ty, mod), + rhs_val.fmtValue(mod), scalar_ty.fmt(mod), }); } @@ -14118,14 +14118,14 @@ fn zirShr( const rhs_elem = try rhs_val.elemValue(mod, i); if (rhs_elem.compareHetero(.lt, try mod.intValue(rhs_ty.childType(mod), 0), mod)) { return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{ - rhs_elem.fmtValue(scalar_ty, mod), + rhs_elem.fmtValue(mod), i, }); } } } else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) { return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{ - rhs_val.fmtValue(scalar_ty, mod), + rhs_val.fmtValue(mod), }); } if (maybe_lhs_val) |lhs_val| { @@ -15046,7 +15046,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins block, src, "ambiguous coercion of division operands '{}' and '{}'; non-zero remainder '{}'", - .{ lhs_ty.fmt(mod), rhs_ty.fmt(mod), rem.fmtValue(resolved_type, mod) }, + .{ lhs_ty.fmt(mod), rhs_ty.fmt(mod), rem.fmtValue(mod) }, ); } } @@ -21094,7 +21094,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const enum_decl = mod.declPtr(enum_decl_index); const msg = msg: { const msg = try sema.errMsg(block, src, "no field with value '{}' in enum '{}'", .{ - val.fmtValue(enum_ty, sema.mod), enum_decl.name.fmt(ip), + val.fmtValue(sema.mod), enum_decl.name.fmt(ip), }); errdefer msg.destroy(sema.gpa); try mod.errNoteNonLazy(enum_decl.srcLoc(mod), msg, "declared here", .{}); @@ -21729,7 +21729,7 @@ fn reifyEnum( // TODO: better source location return sema.fail(block, src, "field '{}' with enumeration value '{}' is too large for backing int type '{}'", .{ field_name.fmt(ip), - field_value_val.fmtValue(Type.comptime_int, mod), + field_value_val.fmtValue(mod), tag_ty.fmt(mod), }); } @@ -21745,7 +21745,7 @@ fn reifyEnum( break :msg msg; }, .value => msg: { - const msg = try sema.errMsg(block, src, "enum tag value {} already taken", .{field_value_val.fmtValue(Type.comptime_int, mod)}); + const msg = try sema.errMsg(block, src, "enum tag value {} already taken", .{field_value_val.fmtValue(mod)}); errdefer msg.destroy(gpa); _ = conflict.prev_field_idx; // TODO: this note is incorrect try sema.errNote(block, src, msg, "other enum tag value here", .{}); @@ -22883,12 +22883,12 @@ fn ptrCastFull( return sema.failWithOwnedErrorMsg(block, msg: { const msg = if (src_info.sentinel == .none) blk: { break :blk try sema.errMsg(block, src, "destination pointer requires '{}' sentinel", .{ - Value.fromInterned(dest_info.sentinel).fmtValue(Type.fromInterned(dest_info.child), mod), + Value.fromInterned(dest_info.sentinel).fmtValue(mod), }); } else blk: { break :blk try sema.errMsg(block, src, "pointer sentinel '{}' cannot coerce into pointer sentinel '{}'", .{ - Value.fromInterned(src_info.sentinel).fmtValue(Type.fromInterned(src_info.child), mod), - Value.fromInterned(dest_info.sentinel).fmtValue(Type.fromInterned(dest_info.child), mod), + Value.fromInterned(src_info.sentinel).fmtValue(mod), + Value.fromInterned(dest_info.sentinel).fmtValue(mod), }); }; errdefer msg.destroy(sema.gpa); @@ -25285,10 +25285,10 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const msg = try sema.errMsg(block, src, "non-matching @memcpy lengths", .{}); errdefer msg.destroy(sema.gpa); try sema.errNote(block, dest_src, msg, "length {} here", .{ - dest_len_val.fmtValue(Type.usize, sema.mod), + dest_len_val.fmtValue(sema.mod), }); try sema.errNote(block, src_src, msg, "length {} here", .{ - src_len_val.fmtValue(Type.usize, sema.mod), + src_len_val.fmtValue(sema.mod), }); break :msg msg; }; @@ -29162,7 +29162,7 @@ fn coerceExtra( // comptime-known integer to other number if (!(try sema.intFitsInType(val, dest_ty, null))) { if (!opts.report_err) return error.NotCoercible; - return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(mod), val.fmtValue(inst_ty, mod) }); + return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(mod), val.fmtValue(mod) }); } return switch (mod.intern_pool.indexToKey(val.toIntern())) { .undef => try mod.undefRef(dest_ty), @@ -29207,7 +29207,7 @@ fn coerceExtra( block, inst_src, "type '{}' cannot represent float value '{}'", - .{ dest_ty.fmt(mod), val.fmtValue(inst_ty, mod) }, + .{ dest_ty.fmt(mod), val.fmtValue(mod) }, ); } return Air.internedToRef(result_val.toIntern()); @@ -29578,11 +29578,11 @@ const InMemoryCoercionResult = union(enum) { .array_sentinel => |sentinel| { if (sentinel.actual.toIntern() != .unreachable_value) { try sema.errNote(block, src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{ - sentinel.actual.fmtValue(sentinel.ty, mod), sentinel.wanted.fmtValue(sentinel.ty, mod), + sentinel.actual.fmtValue(mod), sentinel.wanted.fmtValue(mod), }); } else { try sema.errNote(block, src, msg, "destination array requires '{}' sentinel", .{ - sentinel.wanted.fmtValue(sentinel.ty, mod), + sentinel.wanted.fmtValue(mod), }); } break; @@ -29704,11 +29704,11 @@ const InMemoryCoercionResult = union(enum) { .ptr_sentinel => |sentinel| { if (sentinel.actual.toIntern() != .unreachable_value) { try sema.errNote(block, src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{ - sentinel.actual.fmtValue(sentinel.ty, mod), sentinel.wanted.fmtValue(sentinel.ty, mod), + sentinel.actual.fmtValue(mod), sentinel.wanted.fmtValue(mod), }); } else { try sema.errNote(block, src, msg, "destination pointer requires '{}' sentinel", .{ - sentinel.wanted.fmtValue(sentinel.ty, mod), + sentinel.wanted.fmtValue(mod), }); } break; @@ -31708,7 +31708,7 @@ fn coerceEnumToUnion( if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| { const field_index = union_ty.unionTagFieldIndex(val, sema.mod) orelse { return sema.fail(block, inst_src, "union '{}' has no tag with value '{}'", .{ - union_ty.fmt(sema.mod), val.fmtValue(tag_ty, sema.mod), + union_ty.fmt(sema.mod), val.fmtValue(sema.mod), }); }; @@ -32928,8 +32928,8 @@ fn analyzeSlice( msg, "expected '{}', found '{}'", .{ - Value.zero_comptime_int.fmtValue(Type.comptime_int, mod), - start_value.fmtValue(Type.comptime_int, mod), + Value.zero_comptime_int.fmtValue(mod), + start_value.fmtValue(mod), }, ); break :msg msg; @@ -32945,8 +32945,8 @@ fn analyzeSlice( msg, "expected '{}', found '{}'", .{ - Value.one_comptime_int.fmtValue(Type.comptime_int, mod), - end_value.fmtValue(Type.comptime_int, mod), + Value.one_comptime_int.fmtValue(mod), + end_value.fmtValue(mod), }, ); break :msg msg; @@ -32959,7 +32959,7 @@ fn analyzeSlice( block, end_src, "end index {} out of bounds for slice of single-item pointer", - .{end_value.fmtValue(Type.comptime_int, mod)}, + .{end_value.fmtValue(mod)}, ); } } @@ -33054,8 +33054,8 @@ fn analyzeSlice( end_src, "end index {} out of bounds for array of length {}{s}", .{ - end_val.fmtValue(Type.usize, mod), - len_val.fmtValue(Type.usize, mod), + end_val.fmtValue(mod), + len_val.fmtValue(mod), sentinel_label, }, ); @@ -33099,7 +33099,7 @@ fn analyzeSlice( end_src, "end index {} out of bounds for slice of length {d}{s}", .{ - end_val.fmtValue(Type.usize, mod), + end_val.fmtValue(mod), try slice_val.sliceLen(sema), sentinel_label, }, @@ -33159,8 +33159,8 @@ fn analyzeSlice( start_src, "start index {} is larger than end index {}", .{ - start_val.fmtValue(Type.usize, mod), - end_val.fmtValue(Type.usize, mod), + start_val.fmtValue(mod), + end_val.fmtValue(mod), }, ); } @@ -33198,8 +33198,8 @@ fn analyzeSlice( const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{}); errdefer msg.destroy(sema.gpa); try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{ - expected_sentinel.fmtValue(elem_ty, mod), - actual_sentinel.fmtValue(elem_ty, mod), + expected_sentinel.fmtValue(mod), + actual_sentinel.fmtValue(mod), }); break :msg msg; @@ -37213,7 +37213,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded const field_src = mod.fieldSrcLoc(union_type.decl, .{ .index = field_i }).lazy; const other_field_src = mod.fieldSrcLoc(union_type.decl, .{ .index = gop.index }).lazy; const msg = msg: { - const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{enum_tag_val.fmtValue(int_tag_ty, mod)}); + const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{enum_tag_val.fmtValue(mod)}); errdefer msg.destroy(gpa); try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{}); break :msg msg; @@ -38566,18 +38566,17 @@ fn intFromFloat( ) CompileError!Value { const mod = sema.mod; if (float_ty.zigTypeTag(mod) == .Vector) { - const elem_ty = float_ty.scalarType(mod); const result_data = try sema.arena.alloc(InternPool.Index, float_ty.vectorLen(mod)); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(sema.mod, i); - scalar.* = (try sema.intFromFloatScalar(block, src, elem_val, elem_ty, int_ty.scalarType(mod), mode)).toIntern(); + scalar.* = (try sema.intFromFloatScalar(block, src, elem_val, int_ty.scalarType(mod), mode)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = int_ty.toIntern(), .storage = .{ .elems = result_data }, } }))); } - return sema.intFromFloatScalar(block, src, val, float_ty, int_ty, mode); + return sema.intFromFloatScalar(block, src, val, int_ty, mode); } // float is expected to be finite and non-NaN @@ -38610,7 +38609,6 @@ fn intFromFloatScalar( block: *Block, src: LazySrcLoc, val: Value, - float_ty: Type, int_ty: Type, mode: IntFromFloatMode, ) CompileError!Value { @@ -38622,7 +38620,7 @@ fn intFromFloatScalar( block, src, "fractional component prevents float value '{}' from coercion to type '{}'", - .{ val.fmtValue(float_ty, mod), int_ty.fmt(mod) }, + .{ val.fmtValue(mod), int_ty.fmt(mod) }, ); const float = val.toFloat(f128, mod); @@ -38644,7 +38642,7 @@ fn intFromFloatScalar( if (!(try sema.intFitsInType(cti_result, int_ty, null))) { return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{ - val.fmtValue(float_ty, sema.mod), int_ty.fmt(sema.mod), + val.fmtValue(sema.mod), int_ty.fmt(sema.mod), }); } return mod.getCoerced(cti_result, int_ty); diff --git a/src/TypedValue.zig b/src/TypedValue.zig deleted file mode 100644 index 6947e4cad22ac345ba2c861fb98c1d25ca02c4d7..0000000000000000000000000000000000000000 --- a/src/TypedValue.zig +++ /dev/null @@ -1,363 +0,0 @@ -//! This type exists only for legacy purposes, and will be removed in the future. -//! It is a thin wrapper around a `Value` which also, redundantly, stores its `Type`. - -const std = @import("std"); -const Type = @import("type.zig").Type; -const Value = @import("Value.zig"); -const Zcu = @import("Module.zig"); -const Module = Zcu; -const Sema = @import("Sema.zig"); -const InternPool = @import("InternPool.zig"); -const Allocator = std.mem.Allocator; -const TypedValue = @This(); -const Target = std.Target; - -ty: Type, -val: Value, - -const max_aggregate_items = 100; -const max_string_len = 256; - -const FormatContext = struct { - tv: TypedValue, - mod: *Module, -}; - -pub fn format( - ctx: FormatContext, - comptime fmt: []const u8, - options: std.fmt.FormatOptions, - writer: anytype, -) !void { - _ = options; - comptime std.debug.assert(fmt.len == 0); - return ctx.tv.print(writer, 3, ctx.mod, null) catch |err| switch (err) { - error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function - error.ComptimeBreak, error.ComptimeReturn => unreachable, - error.AnalysisFail, error.NeededSourceLocation => unreachable, // TODO: re-evaluate when we actually pass `opt_sema` - else => |e| return e, - }; -} - -pub fn print( - tv: TypedValue, - writer: anytype, - level: u8, - mod: *Module, - /// If this `Sema` is provided, we will recurse through pointers where possible to provide friendly output. - opt_sema: ?*Sema, -) (@TypeOf(writer).Error || Module.CompileError)!void { - const ip = &mod.intern_pool; - const val = tv.val; - switch (ip.indexToKey(val.toIntern())) { - .int_type, - .ptr_type, - .array_type, - .vector_type, - .opt_type, - .anyframe_type, - .error_union_type, - .simple_type, - .struct_type, - .anon_struct_type, - .union_type, - .opaque_type, - .enum_type, - .func_type, - .error_set_type, - .inferred_error_set_type, - => try Type.print(val.toType(), writer, mod), - .undef => try writer.writeAll("undefined"), - .simple_value => |simple_value| switch (simple_value) { - .void => try writer.writeAll("{}"), - .empty_struct => try writer.writeAll(".{}"), - .generic_poison => try writer.writeAll("(generic poison)"), - else => try writer.writeAll(@tagName(simple_value)), - }, - .variable => try writer.writeAll("(variable)"), - .extern_func => |extern_func| try writer.print("(extern function '{}')", .{ - mod.declPtr(extern_func.decl).name.fmt(ip), - }), - .func => |func| try writer.print("(function '{}')", .{ - mod.declPtr(func.owner_decl).name.fmt(ip), - }), - .int => |int| switch (int.storage) { - inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}), - .lazy_align => |ty| if (opt_sema) |sema| { - const a = (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar; - try writer.print("{}", .{a.toByteUnits(0)}); - } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(mod)}), - .lazy_size => |ty| if (opt_sema) |sema| { - const s = (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar; - try writer.print("{}", .{s}); - } else try writer.print("@sizeOf({})", .{Type.fromInterned(ty).fmt(mod)}), - }, - .err => |err| try writer.print("error.{}", .{ - err.name.fmt(ip), - }), - .error_union => |error_union| switch (error_union.val) { - .err_name => |err_name| try writer.print("error.{}", .{ - err_name.fmt(ip), - }), - .payload => |payload| try print(.{ - .ty = tv.ty.errorUnionPayload(mod), - .val = Value.fromInterned(payload), - }, writer, level, mod, opt_sema), - }, - .enum_literal => |enum_literal| try writer.print(".{}", .{ - enum_literal.fmt(ip), - }), - .enum_tag => |enum_tag| { - const enum_type = ip.loadEnumType(val.typeOf(mod).toIntern()); - if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| { - try writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)}); - return; - } - if (level == 0) { - try writer.writeAll("@enumFromInt(...)"); - } - try writer.writeAll("@enumFromInt("); - try print(.{ - .ty = Type.fromInterned(ip.typeOf(enum_tag.int)), - .val = Value.fromInterned(enum_tag.int), - }, writer, level - 1, mod, opt_sema); - try writer.writeAll(")"); - }, - .empty_enum_value => try writer.writeAll("(empty enum value)"), - .float => |float| switch (float.storage) { - inline else => |x| try writer.print("{d}", .{@as(f64, @floatCast(x))}), - }, - .slice => |slice| { - const print_contents = switch (ip.getBackingAddrTag(slice.ptr).?) { - .field, .elem, .eu_payload, .opt_payload => unreachable, - .anon_decl, .comptime_alloc, .comptime_field => true, - .decl, .int => false, - }; - if (print_contents) { - // TODO: eventually we want to load the slice as an array with `opt_sema`, but that's - // currently not possible without e.g. triggering compile errors. - } - try printPtr(slice.ptr, writer, false, false, 0, level, mod, opt_sema); - try writer.writeAll("[0.."); - try print(.{ - .ty = Type.usize, - .val = Value.fromInterned(slice.len), - }, writer, level - 1, mod, opt_sema); - try writer.writeAll("]"); - }, - .ptr => { - const print_contents = switch (ip.getBackingAddrTag(val.toIntern()).?) { - .field, .elem, .eu_payload, .opt_payload => unreachable, - .anon_decl, .comptime_alloc, .comptime_field => true, - .decl, .int => false, - }; - if (print_contents) { - // TODO: eventually we want to load the pointer with `opt_sema`, but that's - // currently not possible without e.g. triggering compile errors. - } - try printPtr(val.toIntern(), writer, false, false, 0, level, mod, opt_sema); - }, - .opt => |opt| switch (opt.val) { - .none => try writer.writeAll("null"), - else => |payload| try print(.{ - .ty = tv.ty.childType(mod), - .val = Value.fromInterned(payload), - }, writer, level, mod, opt_sema), - }, - .aggregate => |aggregate| try printAggregate(val, aggregate, writer, level, mod, opt_sema), - .un => |un| { - if (level == 0) { - try writer.writeAll(".{ ... }"); - return; - } - if (un.tag == .none) { - const backing_ty = try tv.ty.unionBackingType(mod); - try writer.print("@bitCast(@as({}, ", .{backing_ty.fmt(mod)}); - try print(.{ - .ty = backing_ty, - .val = Value.fromInterned(un.val), - }, writer, level - 1, mod, opt_sema); - try writer.writeAll("))"); - } else { - try writer.writeAll(".{ "); - try print(.{ - .ty = tv.ty.unionTagTypeHypothetical(mod), - .val = Value.fromInterned(un.tag), - }, writer, level - 1, mod, opt_sema); - try writer.writeAll(" = "); - const field_ty = tv.ty.unionFieldType(Value.fromInterned(un.tag), mod).?; - try print(.{ - .ty = field_ty, - .val = Value.fromInterned(un.val), - }, writer, level - 1, mod, opt_sema); - try writer.writeAll(" }"); - } - }, - .memoized_call => unreachable, - } -} - -fn printAggregate( - val: Value, - aggregate: InternPool.Key.Aggregate, - writer: anytype, - level: u8, - zcu: *Zcu, - opt_sema: ?*Sema, -) (@TypeOf(writer).Error || Module.CompileError)!void { - if (level == 0) { - return writer.writeAll(".{ ... }"); - } - const ip = &zcu.intern_pool; - const ty = Type.fromInterned(aggregate.ty); - switch (ty.zigTypeTag(zcu)) { - .Struct => if (!ty.isTuple(zcu)) { - if (ty.structFieldCount(zcu) == 0) { - return writer.writeAll(".{}"); - } - try writer.writeAll(".{ "); - const max_len = @min(ty.structFieldCount(zcu), max_aggregate_items); - for (0..max_len) |i| { - if (i != 0) try writer.writeAll(", "); - const field_name = ty.structFieldName(@intCast(i), zcu).unwrap().?; - try writer.print(".{i} = ", .{field_name.fmt(ip)}); - try print(.{ - .ty = ty.structFieldType(i, zcu), - .val = try val.fieldValue(zcu, i), - }, writer, level - 1, zcu, opt_sema); - } - try writer.writeAll(" }"); - return; - }, - .Array => if (aggregate.storage == .bytes) { - return writer.print("\"{}\".*", .{std.zig.fmtEscapes(aggregate.storage.bytes)}); - } else if (ty.arrayLen(zcu) == 0) { - return writer.writeAll(".{}"); - }, - .Vector => if (ty.arrayLen(zcu) == 0) { - return writer.writeAll(".{}"); - }, - else => unreachable, - } - - const elem_ty = ty.childType(zcu); - const len = ty.arrayLen(zcu); - - try writer.writeAll(".{ "); - - const max_len = @min(len, max_aggregate_items); - for (0..max_len) |i| { - if (i != 0) try writer.writeAll(", "); - try print(.{ - .ty = elem_ty, - .val = try val.fieldValue(zcu, i), - }, writer, level - 1, zcu, opt_sema); - } - if (len > max_aggregate_items) { - try writer.writeAll(", ..."); - } - return writer.writeAll(" }"); -} - -fn printPtr( - ptr_val: InternPool.Index, - writer: anytype, - force_type: bool, - force_addrof: bool, - leading_parens: u32, - level: u8, - zcu: *Zcu, - opt_sema: ?*Sema, -) (@TypeOf(writer).Error || Module.CompileError)!void { - const ip = &zcu.intern_pool; - const ptr = switch (ip.indexToKey(ptr_val)) { - .undef => |ptr_ty| { - if (force_addrof) try writer.writeAll("&"); - try writer.writeByteNTimes('(', leading_parens); - try writer.print("@as({}, undefined)", .{Type.fromInterned(ptr_ty).fmt(zcu)}); - return; - }, - .ptr => |ptr| ptr, - else => unreachable, - }; - switch (ptr.addr) { - .int => |int| { - if (force_addrof) try writer.writeAll("&"); - try writer.writeByteNTimes('(', leading_parens); - if (force_type) { - try writer.print("@as({}, @ptrFromInt(", .{Type.fromInterned(ptr.ty).fmt(zcu)}); - try print(.{ - .ty = Type.usize, - .val = Value.fromInterned(int), - }, writer, level - 1, zcu, opt_sema); - try writer.writeAll("))"); - } else { - try writer.writeAll("@ptrFromInt("); - try print(.{ - .ty = Type.usize, - .val = Value.fromInterned(int), - }, writer, level - 1, zcu, opt_sema); - try writer.writeAll(")"); - } - }, - .decl => |index| { - try writer.writeAll("&"); - try zcu.declPtr(index).renderFullyQualifiedName(zcu, writer); - }, - .comptime_alloc => try writer.writeAll("&(comptime alloc)"), - .anon_decl => |anon| { - const ty = Type.fromInterned(ip.typeOf(anon.val)); - try writer.print("&@as({}, ", .{ty.fmt(zcu)}); - try print(.{ - .ty = ty, - .val = Value.fromInterned(anon.val), - }, writer, level - 1, zcu, opt_sema); - try writer.writeAll(")"); - }, - .comptime_field => |val| { - const ty = Type.fromInterned(ip.typeOf(val)); - try writer.print("&@as({}, ", .{ty.fmt(zcu)}); - try print(.{ - .ty = ty, - .val = Value.fromInterned(val), - }, writer, level - 1, zcu, opt_sema); - try writer.writeAll(")"); - }, - .eu_payload => |base| { - try printPtr(base, writer, true, true, leading_parens, level, zcu, opt_sema); - try writer.writeAll(".?"); - }, - .opt_payload => |base| { - try writer.writeAll("("); - try printPtr(base, writer, true, true, leading_parens + 1, level, zcu, opt_sema); - try writer.writeAll(" catch unreachable"); - }, - .elem => |elem| { - try printPtr(elem.base, writer, true, true, leading_parens, level, zcu, opt_sema); - try writer.print("[{d}]", .{elem.index}); - }, - .field => |field| { - try printPtr(field.base, writer, true, true, leading_parens, level, zcu, opt_sema); - const base_ty = Type.fromInterned(ip.typeOf(field.base)).childType(zcu); - switch (base_ty.zigTypeTag(zcu)) { - .Struct => if (base_ty.isTuple(zcu)) { - try writer.print("[{d}]", .{field.index}); - } else { - const field_name = base_ty.structFieldName(@intCast(field.index), zcu).unwrap().?; - try writer.print(".{i}", .{field_name.fmt(ip)}); - }, - .Union => { - const tag_ty = base_ty.unionTagTypeHypothetical(zcu); - const field_name = tag_ty.enumFieldName(@intCast(field.index), zcu); - try writer.print(".{i}", .{field_name.fmt(ip)}); - }, - .Pointer => switch (field.index) { - Value.slice_ptr_index => try writer.writeAll(".ptr"), - Value.slice_len_index => try writer.writeAll(".len"), - else => unreachable, - }, - else => unreachable, - } - }, - } -} diff --git a/src/Value.zig b/src/Value.zig index 81b8583a84e497032da9535fd3f7568f403e6abf..b1230954ede58139154a5cbce9c1e8640cf48629 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -8,9 +8,9 @@ const Target = std.Target; const Allocator = std.mem.Allocator; const Zcu = @import("Module.zig"); const Module = Zcu; -const TypedValue = @import("TypedValue.zig"); const Sema = @import("Sema.zig"); const InternPool = @import("InternPool.zig"); +const print_value = @import("print_value.zig"); const Value = @This(); ip_index: InternPool.Index, @@ -39,9 +39,9 @@ pub fn fmtDebug(val: Value) std.fmt.Formatter(dump) { return .{ .data = val }; } -pub fn fmtValue(val: Value, ty: Type, mod: *Module) std.fmt.Formatter(TypedValue.format) { +pub fn fmtValue(val: Value, mod: *Module) std.fmt.Formatter(print_value.format) { return .{ .data = .{ - .tv = .{ .ty = ty, .val = val }, + .val = val, .mod = mod, } }; } diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 680dce0b48687566adf6e0d3fbb04dc37036aa7a..1b584bfe53c1ff0fd511709e5df8c2799f3ee073 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -17876,11 +17876,8 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { break :result null; }) orelse return self.fail("TODO implement airShuffle from {} and {} to {} with {}", .{ - lhs_ty.fmt(mod), rhs_ty.fmt(mod), dst_ty.fmt(mod), - Value.fromInterned(extra.mask).fmtValue( - Type.fromInterned(mod.intern_pool.typeOf(extra.mask)), - mod, - ), + lhs_ty.fmt(mod), rhs_ty.fmt(mod), dst_ty.fmt(mod), + Value.fromInterned(extra.mask).fmtValue(mod), }); return self.finishAir(inst, result, .{ extra.a, extra.b, .none }); } diff --git a/src/codegen.zig b/src/codegen.zig index 049b10b3082d413b3ec10719582d88922201e03f..c5da0ebcb75c70f55327017e0374b04ebfc4f56f 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -185,9 +185,7 @@ pub fn generateSymbol( const target = mod.getTarget(); const endian = target.cpu.arch.endian(); - log.debug("generateSymbol: val = {}", .{ - val.fmtValue(ty, mod), - }); + log.debug("generateSymbol: val = {}", .{val.fmtValue(mod)}); if (val.isUndefDeep(mod)) { const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow; @@ -862,7 +860,7 @@ fn genDeclRef( ) CodeGenError!GenResult { const zcu = lf.comp.module.?; const ty = val.typeOf(zcu); - log.debug("genDeclRef: val = {}", .{val.fmtValue(ty, zcu)}); + log.debug("genDeclRef: val = {}", .{val.fmtValue(zcu)}); const ptr_decl = zcu.declPtr(ptr_decl_index); const namespace = zcu.namespacePtr(ptr_decl.src_namespace); @@ -976,7 +974,7 @@ fn genUnnamedConst( ) CodeGenError!GenResult { const zcu = lf.comp.module.?; const gpa = lf.comp.gpa; - log.debug("genUnnamedConst: val = {}", .{val.fmtValue(val.typeOf(zcu), zcu)}); + log.debug("genUnnamedConst: val = {}", .{val.fmtValue(zcu)}); const local_sym_index = lf.lowerUnnamedConst(val, owner_decl_index) catch |err| { return GenResult.fail(gpa, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)}); @@ -1016,7 +1014,7 @@ pub fn genTypedValue( const zcu = lf.comp.module.?; const ty = val.typeOf(zcu); - log.debug("genTypedValue: val = {}", .{val.fmtValue(ty, zcu)}); + log.debug("genTypedValue: val = {}", .{val.fmtValue(zcu)}); if (val.isUndef(zcu)) return GenResult.mcv(.undef); diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 3e560b0918e884d3103e6654be94d110c52e8057..6b13f2623aa3a7f53c969f84982b28512921235c 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -860,7 +860,7 @@ const DeclGen = struct { const val = arg_val; - log.debug("constant: ty = {}, val = {}", .{ ty.fmt(mod), val.fmtValue(ty, mod) }); + log.debug("constant: ty = {}, val = {}", .{ ty.fmt(mod), val.fmtValue(mod) }); if (val.isUndefDeep(mod)) { return self.spv.constUndef(result_ty_ref); } diff --git a/src/print_air.zig b/src/print_air.zig index 0c1beac3a85eac27b609cf2897066765c502082a..12e2825d4ef00b214229e1fc0b474afb56ee8adb 100644 --- a/src/print_air.zig +++ b/src/print_air.zig @@ -951,7 +951,7 @@ const Writer = struct { const ty = Type.fromInterned(mod.intern_pool.indexToKey(ip_index).typeOf()); try s.print("<{}, {}>", .{ ty.fmt(mod), - Value.fromInterned(ip_index).fmtValue(ty, mod), + Value.fromInterned(ip_index).fmtValue(mod), }); } else { return w.writeInstIndex(s, operand.toIndex().?, dies); diff --git a/src/print_value.zig b/src/print_value.zig new file mode 100644 index 0000000000000000000000000000000000000000..f10fbbc2920fee7ec611593a05e772f12d51a894 --- /dev/null +++ b/src/print_value.zig @@ -0,0 +1,317 @@ +//! This type exists only for legacy purposes, and will be removed in the future. +//! It is a thin wrapper around a `Value` which also, redundantly, stores its `Type`. + +const std = @import("std"); +const Type = @import("type.zig").Type; +const Value = @import("Value.zig"); +const Zcu = @import("Module.zig"); +const Module = Zcu; +const Sema = @import("Sema.zig"); +const InternPool = @import("InternPool.zig"); +const Allocator = std.mem.Allocator; +const Target = std.Target; + +const max_aggregate_items = 100; +const max_string_len = 256; + +const FormatContext = struct { + val: Value, + mod: *Module, +}; + +pub fn format( + ctx: FormatContext, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, +) !void { + _ = options; + comptime std.debug.assert(fmt.len == 0); + return print(ctx.val, writer, 3, ctx.mod, null) catch |err| switch (err) { + error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function + error.ComptimeBreak, error.ComptimeReturn => unreachable, + error.AnalysisFail, error.NeededSourceLocation => unreachable, // TODO: re-evaluate when we actually pass `opt_sema` + else => |e| return e, + }; +} + +pub fn print( + val: Value, + writer: anytype, + level: u8, + mod: *Module, + /// If this `Sema` is provided, we will recurse through pointers where possible to provide friendly output. + opt_sema: ?*Sema, +) (@TypeOf(writer).Error || Module.CompileError)!void { + const ip = &mod.intern_pool; + switch (ip.indexToKey(val.toIntern())) { + .int_type, + .ptr_type, + .array_type, + .vector_type, + .opt_type, + .anyframe_type, + .error_union_type, + .simple_type, + .struct_type, + .anon_struct_type, + .union_type, + .opaque_type, + .enum_type, + .func_type, + .error_set_type, + .inferred_error_set_type, + => try Type.print(val.toType(), writer, mod), + .undef => try writer.writeAll("undefined"), + .simple_value => |simple_value| switch (simple_value) { + .void => try writer.writeAll("{}"), + .empty_struct => try writer.writeAll(".{}"), + .generic_poison => try writer.writeAll("(generic poison)"), + else => try writer.writeAll(@tagName(simple_value)), + }, + .variable => try writer.writeAll("(variable)"), + .extern_func => |extern_func| try writer.print("(extern function '{}')", .{ + mod.declPtr(extern_func.decl).name.fmt(ip), + }), + .func => |func| try writer.print("(function '{}')", .{ + mod.declPtr(func.owner_decl).name.fmt(ip), + }), + .int => |int| switch (int.storage) { + inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}), + .lazy_align => |ty| if (opt_sema) |sema| { + const a = (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar; + try writer.print("{}", .{a.toByteUnits(0)}); + } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(mod)}), + .lazy_size => |ty| if (opt_sema) |sema| { + const s = (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar; + try writer.print("{}", .{s}); + } else try writer.print("@sizeOf({})", .{Type.fromInterned(ty).fmt(mod)}), + }, + .err => |err| try writer.print("error.{}", .{ + err.name.fmt(ip), + }), + .error_union => |error_union| switch (error_union.val) { + .err_name => |err_name| try writer.print("error.{}", .{ + err_name.fmt(ip), + }), + .payload => |payload| try print(Value.fromInterned(payload), writer, level, mod, opt_sema), + }, + .enum_literal => |enum_literal| try writer.print(".{}", .{ + enum_literal.fmt(ip), + }), + .enum_tag => |enum_tag| { + const enum_type = ip.loadEnumType(val.typeOf(mod).toIntern()); + if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| { + try writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)}); + return; + } + if (level == 0) { + try writer.writeAll("@enumFromInt(...)"); + } + try writer.writeAll("@enumFromInt("); + try print(Value.fromInterned(enum_tag.int), writer, level - 1, mod, opt_sema); + try writer.writeAll(")"); + }, + .empty_enum_value => try writer.writeAll("(empty enum value)"), + .float => |float| switch (float.storage) { + inline else => |x| try writer.print("{d}", .{@as(f64, @floatCast(x))}), + }, + .slice => |slice| { + const print_contents = switch (ip.getBackingAddrTag(slice.ptr).?) { + .field, .elem, .eu_payload, .opt_payload => unreachable, + .anon_decl, .comptime_alloc, .comptime_field => true, + .decl, .int => false, + }; + if (print_contents) { + // TODO: eventually we want to load the slice as an array with `opt_sema`, but that's + // currently not possible without e.g. triggering compile errors. + } + try printPtr(slice.ptr, writer, false, false, 0, level, mod, opt_sema); + try writer.writeAll("[0.."); + try print(Value.fromInterned(slice.len), writer, level - 1, mod, opt_sema); + try writer.writeAll("]"); + }, + .ptr => { + const print_contents = switch (ip.getBackingAddrTag(val.toIntern()).?) { + .field, .elem, .eu_payload, .opt_payload => unreachable, + .anon_decl, .comptime_alloc, .comptime_field => true, + .decl, .int => false, + }; + if (print_contents) { + // TODO: eventually we want to load the pointer with `opt_sema`, but that's + // currently not possible without e.g. triggering compile errors. + } + try printPtr(val.toIntern(), writer, false, false, 0, level, mod, opt_sema); + }, + .opt => |opt| switch (opt.val) { + .none => try writer.writeAll("null"), + else => |payload| try print(Value.fromInterned(payload), writer, level, mod, opt_sema), + }, + .aggregate => |aggregate| try printAggregate(val, aggregate, writer, level, mod, opt_sema), + .un => |un| { + if (level == 0) { + try writer.writeAll(".{ ... }"); + return; + } + if (un.tag == .none) { + const backing_ty = try val.typeOf(mod).unionBackingType(mod); + try writer.print("@bitCast(@as({}, ", .{backing_ty.fmt(mod)}); + try print(Value.fromInterned(un.val), writer, level - 1, mod, opt_sema); + try writer.writeAll("))"); + } else { + try writer.writeAll(".{ "); + try print(Value.fromInterned(un.tag), writer, level - 1, mod, opt_sema); + try writer.writeAll(" = "); + try print(Value.fromInterned(un.val), writer, level - 1, mod, opt_sema); + try writer.writeAll(" }"); + } + }, + .memoized_call => unreachable, + } +} + +fn printAggregate( + val: Value, + aggregate: InternPool.Key.Aggregate, + writer: anytype, + level: u8, + zcu: *Zcu, + opt_sema: ?*Sema, +) (@TypeOf(writer).Error || Module.CompileError)!void { + if (level == 0) { + return writer.writeAll(".{ ... }"); + } + const ip = &zcu.intern_pool; + const ty = Type.fromInterned(aggregate.ty); + switch (ty.zigTypeTag(zcu)) { + .Struct => if (!ty.isTuple(zcu)) { + if (ty.structFieldCount(zcu) == 0) { + return writer.writeAll(".{}"); + } + try writer.writeAll(".{ "); + const max_len = @min(ty.structFieldCount(zcu), max_aggregate_items); + for (0..max_len) |i| { + if (i != 0) try writer.writeAll(", "); + const field_name = ty.structFieldName(@intCast(i), zcu).unwrap().?; + try writer.print(".{i} = ", .{field_name.fmt(ip)}); + try print(try val.fieldValue(zcu, i), writer, level - 1, zcu, opt_sema); + } + try writer.writeAll(" }"); + return; + }, + .Array => if (aggregate.storage == .bytes) { + return writer.print("\"{}\".*", .{std.zig.fmtEscapes(aggregate.storage.bytes)}); + } else if (ty.arrayLen(zcu) == 0) { + return writer.writeAll(".{}"); + }, + .Vector => if (ty.arrayLen(zcu) == 0) { + return writer.writeAll(".{}"); + }, + else => unreachable, + } + + const len = ty.arrayLen(zcu); + + try writer.writeAll(".{ "); + + const max_len = @min(len, max_aggregate_items); + for (0..max_len) |i| { + if (i != 0) try writer.writeAll(", "); + try print(try val.fieldValue(zcu, i), writer, level - 1, zcu, opt_sema); + } + if (len > max_aggregate_items) { + try writer.writeAll(", ..."); + } + return writer.writeAll(" }"); +} + +fn printPtr( + ptr_val: InternPool.Index, + writer: anytype, + force_type: bool, + force_addrof: bool, + leading_parens: u32, + level: u8, + zcu: *Zcu, + opt_sema: ?*Sema, +) (@TypeOf(writer).Error || Module.CompileError)!void { + const ip = &zcu.intern_pool; + const ptr = switch (ip.indexToKey(ptr_val)) { + .undef => |ptr_ty| { + if (force_addrof) try writer.writeAll("&"); + try writer.writeByteNTimes('(', leading_parens); + try writer.print("@as({}, undefined)", .{Type.fromInterned(ptr_ty).fmt(zcu)}); + return; + }, + .ptr => |ptr| ptr, + else => unreachable, + }; + switch (ptr.addr) { + .int => |int| { + if (force_addrof) try writer.writeAll("&"); + try writer.writeByteNTimes('(', leading_parens); + if (force_type) { + try writer.print("@as({}, @ptrFromInt(", .{Type.fromInterned(ptr.ty).fmt(zcu)}); + try print(Value.fromInterned(int), writer, level - 1, zcu, opt_sema); + try writer.writeAll("))"); + } else { + try writer.writeAll("@ptrFromInt("); + try print(Value.fromInterned(int), writer, level - 1, zcu, opt_sema); + try writer.writeAll(")"); + } + }, + .decl => |index| { + try writer.writeAll("&"); + try zcu.declPtr(index).renderFullyQualifiedName(zcu, writer); + }, + .comptime_alloc => try writer.writeAll("&(comptime alloc)"), + .anon_decl => |anon| { + const ty = Type.fromInterned(ip.typeOf(anon.val)); + try writer.print("&@as({}, ", .{ty.fmt(zcu)}); + try print(Value.fromInterned(anon.val), writer, level - 1, zcu, opt_sema); + try writer.writeAll(")"); + }, + .comptime_field => |val| { + const ty = Type.fromInterned(ip.typeOf(val)); + try writer.print("&@as({}, ", .{ty.fmt(zcu)}); + try print(Value.fromInterned(val), writer, level - 1, zcu, opt_sema); + try writer.writeAll(")"); + }, + .eu_payload => |base| { + try printPtr(base, writer, true, true, leading_parens, level, zcu, opt_sema); + try writer.writeAll(".?"); + }, + .opt_payload => |base| { + try writer.writeAll("("); + try printPtr(base, writer, true, true, leading_parens + 1, level, zcu, opt_sema); + try writer.writeAll(" catch unreachable"); + }, + .elem => |elem| { + try printPtr(elem.base, writer, true, true, leading_parens, level, zcu, opt_sema); + try writer.print("[{d}]", .{elem.index}); + }, + .field => |field| { + try printPtr(field.base, writer, true, true, leading_parens, level, zcu, opt_sema); + const base_ty = Type.fromInterned(ip.typeOf(field.base)).childType(zcu); + switch (base_ty.zigTypeTag(zcu)) { + .Struct => if (base_ty.isTuple(zcu)) { + try writer.print("[{d}]", .{field.index}); + } else { + const field_name = base_ty.structFieldName(@intCast(field.index), zcu).unwrap().?; + try writer.print(".{i}", .{field_name.fmt(ip)}); + }, + .Union => { + const tag_ty = base_ty.unionTagTypeHypothetical(zcu); + const field_name = tag_ty.enumFieldName(@intCast(field.index), zcu); + try writer.print(".{i}", .{field_name.fmt(ip)}); + }, + .Pointer => switch (field.index) { + Value.slice_ptr_index => try writer.writeAll(".ptr"), + Value.slice_len_index => try writer.writeAll(".len"), + else => unreachable, + }, + else => unreachable, + } + }, + } +} diff --git a/src/type.zig b/src/type.zig index 5d67f13cbd1616d9327e96e50a4062525448de26..203ab4f63e68733a357b41bdf002506d71095694 100644 --- a/src/type.zig +++ b/src/type.zig @@ -187,8 +187,8 @@ pub const Type = struct { if (info.sentinel != .none) switch (info.flags.size) { .One, .C => unreachable, - .Many => try writer.print("[*:{}]", .{Value.fromInterned(info.sentinel).fmtValue(Type.fromInterned(info.child), mod)}), - .Slice => try writer.print("[:{}]", .{Value.fromInterned(info.sentinel).fmtValue(Type.fromInterned(info.child), mod)}), + .Many => try writer.print("[*:{}]", .{Value.fromInterned(info.sentinel).fmtValue(mod)}), + .Slice => try writer.print("[:{}]", .{Value.fromInterned(info.sentinel).fmtValue(mod)}), } else switch (info.flags.size) { .One => try writer.writeAll("*"), .Many => try writer.writeAll("[*]"), @@ -234,7 +234,7 @@ pub const Type = struct { } else { try writer.print("[{d}:{}]", .{ array_type.len, - Value.fromInterned(array_type.sentinel).fmtValue(Type.fromInterned(array_type.child), mod), + Value.fromInterned(array_type.sentinel).fmtValue(mod), }); try print(Type.fromInterned(array_type.child), writer, mod); } @@ -352,7 +352,7 @@ pub const Type = struct { try print(Type.fromInterned(field_ty), writer, mod); if (val != .none) { - try writer.print(" = {}", .{Value.fromInterned(val).fmtValue(Type.fromInterned(field_ty), mod)}); + try writer.print(" = {}", .{Value.fromInterned(val).fmtValue(mod)}); } } try writer.writeAll("}");