diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-07-01 15:52:54 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-07-01 15:52:54 -0700 |
| commit | c89dd15e1be4959800dc7092d7dd4375253db7bc (patch) | |
| tree | ca184ae53592efa21e67128a5f891d642d7f1118 /src/TypedValue.zig | |
| parent | 5466e87fce581f2ef90ac23bb80b1dbc05836fc6 (diff) | |
| parent | 2360f8c490f3ec684ed64ff28e8c1fade249070b (diff) | |
| download | zig-c89dd15e1be4959800dc7092d7dd4375253db7bc.tar.gz zig-c89dd15e1be4959800dc7092d7dd4375253db7bc.zip | |
Merge remote-tracking branch 'origin/master' into llvm14
Diffstat (limited to 'src/TypedValue.zig')
| -rw-r--r-- | src/TypedValue.zig | 465 |
1 files changed, 460 insertions, 5 deletions
diff --git a/src/TypedValue.zig b/src/TypedValue.zig index 1fa4813a34..a41c865827 100644 --- a/src/TypedValue.zig +++ b/src/TypedValue.zig @@ -1,8 +1,10 @@ const std = @import("std"); const Type = @import("type.zig").Type; const Value = @import("value.zig").Value; +const Module = @import("Module.zig"); const Allocator = std.mem.Allocator; const TypedValue = @This(); +const Target = std.Target; ty: Type, val: Value, @@ -30,15 +32,468 @@ pub fn copy(self: TypedValue, arena: Allocator) error{OutOfMemory}!TypedValue { }; } -pub fn eql(a: TypedValue, b: TypedValue) bool { - if (!a.ty.eql(b.ty)) return false; - return a.val.eql(b.val, a.ty); +pub fn eql(a: TypedValue, b: TypedValue, mod: *Module) bool { + if (!a.ty.eql(b.ty, mod)) return false; + return a.val.eql(b.val, a.ty, mod); } -pub fn hash(tv: TypedValue, hasher: *std.hash.Wyhash) void { - return tv.val.hash(tv.ty, hasher); +pub fn hash(tv: TypedValue, hasher: *std.hash.Wyhash, mod: *Module) void { + return tv.val.hash(tv.ty, hasher, mod); } pub fn enumToInt(tv: TypedValue, buffer: *Value.Payload.U64) Value { return tv.val.enumToInt(tv.ty, buffer); } + +const max_aggregate_items = 100; + +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); +} + +/// Prints the Value according to the Type, not according to the Value Tag. +pub fn print( + tv: TypedValue, + writer: anytype, + level: u8, + mod: *Module, +) @TypeOf(writer).Error!void { + const target = mod.getTarget(); + var val = tv.val; + var ty = tv.ty; + while (true) switch (val.tag()) { + .u1_type => return writer.writeAll("u1"), + .u8_type => return writer.writeAll("u8"), + .i8_type => return writer.writeAll("i8"), + .u16_type => return writer.writeAll("u16"), + .i16_type => return writer.writeAll("i16"), + .u29_type => return writer.writeAll("u29"), + .u32_type => return writer.writeAll("u32"), + .i32_type => return writer.writeAll("i32"), + .u64_type => return writer.writeAll("u64"), + .i64_type => return writer.writeAll("i64"), + .u128_type => return writer.writeAll("u128"), + .i128_type => return writer.writeAll("i128"), + .isize_type => return writer.writeAll("isize"), + .usize_type => return writer.writeAll("usize"), + .c_short_type => return writer.writeAll("c_short"), + .c_ushort_type => return writer.writeAll("c_ushort"), + .c_int_type => return writer.writeAll("c_int"), + .c_uint_type => return writer.writeAll("c_uint"), + .c_long_type => return writer.writeAll("c_long"), + .c_ulong_type => return writer.writeAll("c_ulong"), + .c_longlong_type => return writer.writeAll("c_longlong"), + .c_ulonglong_type => return writer.writeAll("c_ulonglong"), + .c_longdouble_type => return writer.writeAll("c_longdouble"), + .f16_type => return writer.writeAll("f16"), + .f32_type => return writer.writeAll("f32"), + .f64_type => return writer.writeAll("f64"), + .f80_type => return writer.writeAll("f80"), + .f128_type => return writer.writeAll("f128"), + .anyopaque_type => return writer.writeAll("anyopaque"), + .bool_type => return writer.writeAll("bool"), + .void_type => return writer.writeAll("void"), + .type_type => return writer.writeAll("type"), + .anyerror_type => return writer.writeAll("anyerror"), + .comptime_int_type => return writer.writeAll("comptime_int"), + .comptime_float_type => return writer.writeAll("comptime_float"), + .noreturn_type => return writer.writeAll("noreturn"), + .null_type => return writer.writeAll("@Type(.Null)"), + .undefined_type => return writer.writeAll("@Type(.Undefined)"), + .fn_noreturn_no_args_type => return writer.writeAll("fn() noreturn"), + .fn_void_no_args_type => return writer.writeAll("fn() void"), + .fn_naked_noreturn_no_args_type => return writer.writeAll("fn() callconv(.Naked) noreturn"), + .fn_ccc_void_no_args_type => return writer.writeAll("fn() callconv(.C) void"), + .single_const_pointer_to_comptime_int_type => return writer.writeAll("*const comptime_int"), + .anyframe_type => return writer.writeAll("anyframe"), + .const_slice_u8_type => return writer.writeAll("[]const u8"), + .const_slice_u8_sentinel_0_type => return writer.writeAll("[:0]const u8"), + .anyerror_void_error_union_type => return writer.writeAll("anyerror!void"), + + .enum_literal_type => return writer.writeAll("@Type(.EnumLiteral)"), + .manyptr_u8_type => return writer.writeAll("[*]u8"), + .manyptr_const_u8_type => return writer.writeAll("[*]const u8"), + .manyptr_const_u8_sentinel_0_type => return writer.writeAll("[*:0]const u8"), + .atomic_order_type => return writer.writeAll("std.builtin.AtomicOrder"), + .atomic_rmw_op_type => return writer.writeAll("std.builtin.AtomicRmwOp"), + .calling_convention_type => return writer.writeAll("std.builtin.CallingConvention"), + .address_space_type => return writer.writeAll("std.builtin.AddressSpace"), + .float_mode_type => return writer.writeAll("std.builtin.FloatMode"), + .reduce_op_type => return writer.writeAll("std.builtin.ReduceOp"), + .call_options_type => return writer.writeAll("std.builtin.CallOptions"), + .prefetch_options_type => return writer.writeAll("std.builtin.PrefetchOptions"), + .export_options_type => return writer.writeAll("std.builtin.ExportOptions"), + .extern_options_type => return writer.writeAll("std.builtin.ExternOptions"), + .type_info_type => return writer.writeAll("std.builtin.Type"), + + .empty_struct_value => return writer.writeAll(".{}"), + .aggregate => { + if (level == 0) { + return writer.writeAll(".{ ... }"); + } + const vals = val.castTag(.aggregate).?.data; + if (ty.castTag(.anon_struct)) |anon_struct| { + const field_names = anon_struct.data.names; + const types = anon_struct.data.types; + const max_len = std.math.min(types.len, max_aggregate_items); + + var i: u32 = 0; + while (i < max_len) : (i += 1) { + if (i != 0) try writer.writeAll(", "); + try writer.print(".{s} = ", .{field_names[i]}); + try print(.{ + .ty = types[i], + .val = vals[i], + }, writer, level - 1, mod); + } + if (types.len > max_aggregate_items) { + try writer.writeAll(", ..."); + } + return writer.writeAll(" }"); + } else if (ty.isTuple()) { + const fields = ty.tupleFields(); + const max_len = std.math.min(fields.types.len, max_aggregate_items); + + var i: u32 = 0; + while (i < max_len) : (i += 1) { + if (i != 0) try writer.writeAll(", "); + try print(.{ + .ty = fields.types[i], + .val = vals[i], + }, writer, level - 1, mod); + } + if (fields.types.len > max_aggregate_items) { + try writer.writeAll(", ..."); + } + return writer.writeAll(" }"); + } else if (ty.zigTypeTag() == .Struct) { + try writer.writeAll(".{ "); + const struct_fields = ty.structFields(); + const len = struct_fields.count(); + const max_len = std.math.min(len, max_aggregate_items); + + const field_names = struct_fields.keys(); + const fields = struct_fields.values(); + + var i: u32 = 0; + while (i < max_len) : (i += 1) { + if (i != 0) try writer.writeAll(", "); + try writer.print(".{s} = ", .{field_names[i]}); + try print(.{ + .ty = fields[i].ty, + .val = vals[i], + }, writer, level - 1, mod); + } + if (len > max_aggregate_items) { + try writer.writeAll(", ..."); + } + return writer.writeAll(" }"); + } else { + try writer.writeAll(".{ "); + const elem_ty = ty.elemType2(); + const len = ty.arrayLen(); + const max_len = std.math.min(len, max_aggregate_items); + + var i: u32 = 0; + while (i < max_len) : (i += 1) { + if (i != 0) try writer.writeAll(", "); + try print(.{ + .ty = elem_ty, + .val = vals[i], + }, writer, level - 1, mod); + } + if (len > max_aggregate_items) { + try writer.writeAll(", ..."); + } + return writer.writeAll(" }"); + } + }, + .@"union" => { + if (level == 0) { + return writer.writeAll(".{ ... }"); + } + const union_val = val.castTag(.@"union").?.data; + try writer.writeAll(".{ "); + + try print(.{ + .ty = ty.cast(Type.Payload.Union).?.data.tag_ty, + .val = union_val.tag, + }, writer, level - 1, mod); + try writer.writeAll(" = "); + try print(.{ + .ty = ty.unionFieldType(union_val.tag, mod), + .val = union_val.val, + }, writer, level - 1, mod); + + return writer.writeAll(" }"); + }, + .null_value => return writer.writeAll("null"), + .undef => return writer.writeAll("undefined"), + .zero => return writer.writeAll("0"), + .one => return writer.writeAll("1"), + .void_value => return writer.writeAll("{}"), + .unreachable_value => return writer.writeAll("unreachable"), + .the_only_possible_value => { + val = ty.onePossibleValue().?; + }, + .bool_true => return writer.writeAll("true"), + .bool_false => return writer.writeAll("false"), + .ty => return val.castTag(.ty).?.data.print(writer, mod), + .int_type => { + const int_type = val.castTag(.int_type).?.data; + return writer.print("{s}{d}", .{ + if (int_type.signed) "s" else "u", + int_type.bits, + }); + }, + .int_u64 => return std.fmt.formatIntValue(val.castTag(.int_u64).?.data, "", .{}, writer), + .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", .{}, writer), + .int_big_positive => return writer.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}), + .int_big_negative => return writer.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}), + .lazy_align => { + const sub_ty = val.castTag(.lazy_align).?.data; + const x = sub_ty.abiAlignment(target); + return writer.print("{d}", .{x}); + }, + .lazy_size => { + const sub_ty = val.castTag(.lazy_size).?.data; + const x = sub_ty.abiSize(target); + return writer.print("{d}", .{x}); + }, + .function => return writer.print("(function '{s}')", .{ + mod.declPtr(val.castTag(.function).?.data.owner_decl).name, + }), + .extern_fn => return writer.writeAll("(extern function)"), + .variable => return writer.writeAll("(variable)"), + .decl_ref_mut => { + const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index; + const decl = mod.declPtr(decl_index); + if (level == 0) { + return writer.print("(decl ref mut '{s}')", .{decl.name}); + } + return print(.{ + .ty = decl.ty, + .val = decl.val, + }, writer, level - 1, mod); + }, + .decl_ref => { + const decl_index = val.castTag(.decl_ref).?.data; + const decl = mod.declPtr(decl_index); + if (level == 0) { + return writer.print("(decl ref '{s}')", .{decl.name}); + } + return print(.{ + .ty = decl.ty, + .val = decl.val, + }, writer, level - 1, mod); + }, + .comptime_field_ptr => { + const payload = val.castTag(.comptime_field_ptr).?.data; + if (level == 0) { + return writer.writeAll("(comptime field ptr)"); + } + return print(.{ + .ty = payload.field_ty, + .val = payload.field_val, + }, writer, level - 1, mod); + }, + .elem_ptr => { + const elem_ptr = val.castTag(.elem_ptr).?.data; + try writer.writeAll("&"); + if (level == 0) { + try writer.writeAll("(ptr)"); + } else { + try print(.{ + .ty = elem_ptr.elem_ty, + .val = elem_ptr.array_ptr, + }, writer, level - 1, mod); + } + return writer.print("[{}]", .{elem_ptr.index}); + }, + .field_ptr => { + const field_ptr = val.castTag(.field_ptr).?.data; + try writer.writeAll("&"); + if (level == 0) { + try writer.writeAll("(ptr)"); + } else { + try print(.{ + .ty = field_ptr.container_ty, + .val = field_ptr.container_ptr, + }, writer, level - 1, mod); + } + + if (field_ptr.container_ty.zigTypeTag() == .Struct) { + const field_name = field_ptr.container_ty.structFields().keys()[field_ptr.field_index]; + return writer.print(".{s}", .{field_name}); + } else if (field_ptr.container_ty.zigTypeTag() == .Union) { + const field_name = field_ptr.container_ty.unionFields().keys()[field_ptr.field_index]; + return writer.print(".{s}", .{field_name}); + } else unreachable; + }, + .empty_array => return writer.writeAll(".{}"), + .enum_literal => return writer.print(".{}", .{std.zig.fmtId(val.castTag(.enum_literal).?.data)}), + .enum_field_index => { + return writer.print(".{s}", .{ty.enumFieldName(val.castTag(.enum_field_index).?.data)}); + }, + .bytes => return writer.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}), + .str_lit => { + const str_lit = val.castTag(.str_lit).?.data; + const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; + return writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)}); + }, + .repeated => { + if (level == 0) { + return writer.writeAll(".{ ... }"); + } + var i: u32 = 0; + try writer.writeAll(".{ "); + const elem_tv = TypedValue{ + .ty = ty.elemType2(), + .val = val.castTag(.repeated).?.data, + }; + const len = ty.arrayLen(); + const max_len = std.math.min(len, max_aggregate_items); + while (i < max_len) : (i += 1) { + if (i != 0) try writer.writeAll(", "); + try print(elem_tv, writer, level - 1, mod); + } + if (len > max_aggregate_items) { + try writer.writeAll(", ..."); + } + return writer.writeAll(" }"); + }, + .empty_array_sentinel => { + if (level == 0) { + return writer.writeAll(".{ (sentinel) }"); + } + try writer.writeAll(".{ "); + try print(.{ + .ty = ty.elemType2(), + .val = ty.sentinel().?, + }, writer, level - 1, mod); + return writer.writeAll(" }"); + }, + .slice => { + if (level == 0) { + return writer.writeAll(".{ ... }"); + } + const payload = val.castTag(.slice).?.data; + try writer.writeAll(".{ "); + const elem_ty = ty.elemType2(); + const len = payload.len.toUnsignedInt(target); + const max_len = std.math.min(len, max_aggregate_items); + + var i: u32 = 0; + while (i < max_len) : (i += 1) { + if (i != 0) try writer.writeAll(", "); + var buf: Value.ElemValueBuffer = undefined; + try print(.{ + .ty = elem_ty, + .val = payload.ptr.elemValueBuffer(mod, i, &buf), + }, writer, level - 1, mod); + } + if (len > max_aggregate_items) { + try writer.writeAll(", ..."); + } + return writer.writeAll(" }"); + }, + .float_16 => return writer.print("{d}", .{val.castTag(.float_16).?.data}), + .float_32 => return writer.print("{d}", .{val.castTag(.float_32).?.data}), + .float_64 => return writer.print("{d}", .{val.castTag(.float_64).?.data}), + .float_80 => return writer.print("{d}", .{@floatCast(f64, val.castTag(.float_80).?.data)}), + .float_128 => return writer.print("{d}", .{@floatCast(f64, val.castTag(.float_128).?.data)}), + .@"error" => return writer.print("error.{s}", .{val.castTag(.@"error").?.data.name}), + .eu_payload => { + val = val.castTag(.eu_payload).?.data; + ty = ty.errorUnionPayload(); + }, + .opt_payload => { + val = val.castTag(.opt_payload).?.data; + var buf: Type.Payload.ElemType = undefined; + ty = ty.optionalChild(&buf); + return print(.{ .ty = ty, .val = val }, writer, level, mod); + }, + .eu_payload_ptr => { + try writer.writeAll("&"); + + const data = val.castTag(.eu_payload_ptr).?.data; + + var ty_val: Value.Payload.Ty = .{ + .base = .{ .tag = .ty }, + .data = ty, + }; + + try writer.writeAll("@as("); + try print(.{ + .ty = Type.type, + .val = Value.initPayload(&ty_val.base), + }, writer, level - 1, mod); + + try writer.writeAll(", &(payload of "); + + var ptr_ty: Type.Payload.ElemType = .{ + .base = .{ .tag = .single_mut_pointer }, + .data = data.container_ty, + }; + + try print(.{ + .ty = Type.initPayload(&ptr_ty.base), + .val = data.container_ptr, + }, writer, level - 1, mod); + + try writer.writeAll("))"); + return; + }, + .opt_payload_ptr => { + const data = val.castTag(.opt_payload_ptr).?.data; + + var ty_val: Value.Payload.Ty = .{ + .base = .{ .tag = .ty }, + .data = ty, + }; + + try writer.writeAll("@as("); + try print(.{ + .ty = Type.type, + .val = Value.initPayload(&ty_val.base), + }, writer, level - 1, mod); + + try writer.writeAll(", &(payload of "); + + var ptr_ty: Type.Payload.ElemType = .{ + .base = .{ .tag = .single_mut_pointer }, + .data = data.container_ty, + }; + + try print(.{ + .ty = Type.initPayload(&ptr_ty.base), + .val = data.container_ptr, + }, writer, level - 1, mod); + + try writer.writeAll("))"); + return; + }, + + // TODO these should not appear in this function + .inferred_alloc => return writer.writeAll("(inferred allocation value)"), + .inferred_alloc_comptime => return writer.writeAll("(inferred comptime allocation value)"), + .bound_fn => { + const bound_func = val.castTag(.bound_fn).?.data; + return writer.print("(bound_fn %{}(%{})", .{ bound_func.func_inst, bound_func.arg0_inst }); + }, + .generic_poison_type => return writer.writeAll("(generic poison type)"), + .generic_poison => return writer.writeAll("(generic poison)"), + }; +} |
