Commit abded5cbb0

Jacob Young <jacobly0@users.noreply.github.com>
2023-05-26 20:58:07
TypedValue: implement more prints
1 parent f2c7161
Changed files (3)
src/codegen/llvm.zig
@@ -3255,9 +3255,9 @@ pub const DeclGen = struct {
                 try dg.module.markDeclAlive(fn_decl);
                 return dg.resolveLlvmFunction(fn_decl_index);
             },
-            .int => |int| {
+            .int => {
                 var bigint_space: Value.BigIntSpace = undefined;
-                const bigint = int.storage.toBigInt(&bigint_space);
+                const bigint = tv.val.toBigInt(&bigint_space, mod);
                 return lowerBigInt(dg, tv.ty, bigint);
             },
             .err => |err| {
src/Module.zig
@@ -6705,18 +6705,13 @@ pub fn getCoerced(mod: *Module, val: Value, new_ty: Type) Allocator.Error!Value
 }
 
 pub fn intType(mod: *Module, signedness: std.builtin.Signedness, bits: u16) Allocator.Error!Type {
-    const i = try intern(mod, .{ .int_type = .{
+    return (try intern(mod, .{ .int_type = .{
         .signedness = signedness,
         .bits = bits,
-    } });
-    return i.toType();
+    } })).toType();
 }
 
 pub fn arrayType(mod: *Module, info: InternPool.Key.ArrayType) Allocator.Error!Type {
-    if (std.debug.runtime_safety and info.sentinel != .none) {
-        const sent_ty = mod.intern_pool.typeOf(info.sentinel);
-        assert(sent_ty == info.child);
-    }
     const i = try intern(mod, .{ .array_type = info });
     return i.toType();
 }
@@ -6732,12 +6727,31 @@ pub fn optionalType(mod: *Module, child_type: InternPool.Index) Allocator.Error!
 }
 
 pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type {
-    if (std.debug.runtime_safety and info.sentinel != .none) {
-        const sent_ty = mod.intern_pool.typeOf(info.sentinel);
-        assert(sent_ty == info.elem_type);
+    var canon_info = info;
+
+    // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee
+    // type, we change it to 0 here. If this causes an assertion trip because the
+    // pointee type needs to be resolved more, that needs to be done before calling
+    // this ptr() function.
+    if (info.alignment.toByteUnitsOptional()) |info_align| {
+        const elem_align = info.elem_type.toType().abiAlignment(mod);
+        if (info.elem_type.toType().layoutIsResolved(mod) and info_align == elem_align) {
+            canon_info.alignment = .none;
+        }
     }
-    const i = try intern(mod, .{ .ptr_type = info });
-    return i.toType();
+
+    // Canonicalize host_size. If it matches the bit size of the pointee type,
+    // we change it to 0 here. If this causes an assertion trip, the pointee type
+    // needs to be resolved before calling this ptr() function.
+    if (info.host_size != 0) {
+        const elem_bit_size = info.elem_type.toType().bitSize(mod);
+        assert(info.bit_offset + elem_bit_size <= info.host_size * 8);
+        if (info.host_size * 8 == elem_bit_size) {
+            canon_info.host_size = 0;
+        }
+    }
+
+    return (try intern(mod, .{ .ptr_type = canon_info })).toType();
 }
 
 pub fn singleMutPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
src/TypedValue.zig
@@ -33,7 +33,7 @@ pub fn copy(self: TypedValue, arena: Allocator) error{OutOfMemory}!TypedValue {
 }
 
 pub fn eql(a: TypedValue, b: TypedValue, mod: *Module) bool {
-    if (a.ty.ip_index != b.ty.ip_index) return false;
+    if (a.ty.toIntern() != b.ty.toIntern()) return false;
     return a.val.eql(b.val, a.ty, mod);
 }
 
@@ -76,11 +76,7 @@ pub fn print(
 ) (@TypeOf(writer).Error || Allocator.Error)!void {
     var val = tv.val;
     var ty = tv.ty;
-    if (val.isVariable(mod))
-        return writer.writeAll("(variable)");
-
     while (true) switch (val.ip_index) {
-        .empty_struct => return printAggregate(ty, val, writer, level, mod),
         .none => switch (val.tag()) {
             .aggregate => return printAggregate(ty, val, writer, level, mod),
             .@"union" => {
@@ -91,7 +87,7 @@ pub fn print(
                 try writer.writeAll(".{ ");
 
                 try print(.{
-                    .ty = mod.unionPtr(mod.intern_pool.indexToKey(ty.ip_index).union_type.index).tag_ty,
+                    .ty = mod.unionPtr(mod.intern_pool.indexToKey(ty.toIntern()).union_type.index).tag_ty,
                     .val = union_val.tag,
                 }, writer, level - 1, mod);
                 try writer.writeAll(" = ");
@@ -176,47 +172,112 @@ pub fn print(
             .opt_payload => {
                 val = val.castTag(.opt_payload).?.data;
                 ty = ty.optionalChild(mod);
-                return print(.{ .ty = ty, .val = val }, writer, level, mod);
             },
         },
-        else => {
-            const key = mod.intern_pool.indexToKey(val.ip_index);
-            if (key.typeOf() == .type_type) {
-                return Type.print(val.toType(), writer, mod);
-            }
-            switch (key) {
-                .int => |int| switch (int.storage) {
-                    inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),
-                    .lazy_align => |lazy_ty| return writer.print("{d}", .{
-                        lazy_ty.toType().abiAlignment(mod),
-                    }),
-                    .lazy_size => |lazy_ty| return writer.print("{d}", .{
-                        lazy_ty.toType().abiSize(mod),
-                    }),
+        else => switch (mod.intern_pool.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,
+            => return Type.print(val.toType(), writer, mod),
+            .undef => return writer.writeAll("undefined"),
+            .runtime_value => return writer.writeAll("(runtime value)"),
+            .simple_value => |simple_value| switch (simple_value) {
+                .empty_struct => return printAggregate(ty, val, writer, level, mod),
+                .generic_poison => return writer.writeAll("(generic poison)"),
+                else => return writer.writeAll(@tagName(simple_value)),
+            },
+            .variable => return writer.writeAll("(variable)"),
+            .extern_func => |extern_func| return writer.print("(extern function '{s}')", .{
+                mod.declPtr(extern_func.decl).name,
+            }),
+            .func => |func| return writer.print("(function '{s}')", .{
+                mod.declPtr(mod.funcPtr(func.index).owner_decl).name,
+            }),
+            .int => |int| switch (int.storage) {
+                inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),
+                .lazy_align => |lazy_ty| return writer.print("{d}", .{
+                    lazy_ty.toType().abiAlignment(mod),
+                }),
+                .lazy_size => |lazy_ty| return writer.print("{d}", .{
+                    lazy_ty.toType().abiSize(mod),
+                }),
+            },
+            .err => |err| return writer.print("error.{s}", .{
+                mod.intern_pool.stringToSlice(err.name),
+            }),
+            .error_union => |error_union| switch (error_union.val) {
+                .err_name => |err_name| return writer.print("error.{s}", .{
+                    mod.intern_pool.stringToSlice(err_name),
+                }),
+                .payload => |payload| {
+                    val = payload.toValue();
+                    ty = ty.errorUnionPayload(mod);
                 },
-                .enum_tag => |enum_tag| {
-                    if (level == 0) {
-                        return writer.writeAll("(enum)");
-                    }
+            },
+            .enum_literal => |enum_literal| return writer.print(".{s}", .{
+                mod.intern_pool.stringToSlice(enum_literal),
+            }),
+            .enum_tag => |enum_tag| {
+                if (level == 0) {
+                    return writer.writeAll("(enum)");
+                }
 
-                    try writer.writeAll("@intToEnum(");
+                try writer.writeAll("@intToEnum(");
+                try print(.{
+                    .ty = Type.type,
+                    .val = enum_tag.ty.toValue(),
+                }, writer, level - 1, mod);
+                try writer.writeAll(", ");
+                try print(.{
+                    .ty = mod.intern_pool.typeOf(enum_tag.int).toType(),
+                    .val = enum_tag.int.toValue(),
+                }, writer, level - 1, mod);
+                try writer.writeAll(")");
+                return;
+            },
+            .float => |float| switch (float.storage) {
+                inline else => |x| return writer.print("{}", .{x}),
+            },
+            .ptr => return writer.writeAll("(ptr)"),
+            .opt => |opt| switch (opt.val) {
+                .none => return writer.writeAll("null"),
+                else => {
+                    val = opt.val.toValue();
+                    ty = ty.optionalChild(mod);
+                },
+            },
+            .aggregate => |aggregate| switch (aggregate.storage) {
+                .bytes => |bytes| return writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)}),
+                .elems, .repeated_elem => return printAggregate(ty, val, writer, level, mod),
+            },
+            .un => |un| {
+                try writer.writeAll(".{ ");
+                if (level > 0) {
                     try print(.{
-                        .ty = Type.type,
-                        .val = enum_tag.ty.toValue(),
+                        .ty = ty.unionTagTypeHypothetical(mod),
+                        .val = un.tag.toValue(),
                     }, writer, level - 1, mod);
-                    try writer.writeAll(", ");
+                    try writer.writeAll(" = ");
                     try print(.{
-                        .ty = mod.intern_pool.typeOf(enum_tag.int).toType(),
-                        .val = enum_tag.int.toValue(),
+                        .ty = ty.unionFieldType(un.tag.toValue(), mod),
+                        .val = un.val.toValue(),
                     }, writer, level - 1, mod);
-                    try writer.writeAll(")");
-                    return;
-                },
-                .float => |float| switch (float.storage) {
-                    inline else => |x| return writer.print("{}", .{x}),
-                },
-                else => return writer.print("{}", .{val.ip_index}),
-            }
+                } else try writer.writeAll("...");
+                return writer.writeAll(" }");
+            },
         },
     };
 }
@@ -238,12 +299,9 @@ fn printAggregate(
         var i: u32 = 0;
         while (i < max_len) : (i += 1) {
             if (i != 0) try writer.writeAll(", ");
-            switch (ty.ip_index) {
-                .none => {}, // TODO make this unreachable after finishing InternPool migration
-                else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
-                    .struct_type, .anon_struct_type => try writer.print(".{s} = ", .{ty.structFieldName(i, mod)}),
-                    else => {},
-                },
+            switch (mod.intern_pool.indexToKey(ty.toIntern())) {
+                .struct_type, .anon_struct_type => try writer.print(".{s} = ", .{ty.structFieldName(i, mod)}),
+                else => {},
             }
             try print(.{
                 .ty = ty.structFieldType(i, mod),