diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-05-04 20:30:25 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-06-10 20:42:27 -0700 |
| commit | 5e636643d2a36c777a607b65cfd1abbb1822ad1e (patch) | |
| tree | 500ec74bd5cc60bb8a4db95ab5f5e90fcfb222aa /src/type.zig | |
| parent | 9d422bff18dbb92d3a6b8705c3dae7404a34bba6 (diff) | |
| download | zig-5e636643d2a36c777a607b65cfd1abbb1822ad1e.tar.gz zig-5e636643d2a36c777a607b65cfd1abbb1822ad1e.zip | |
stage2: move many Type encodings to InternPool
Notably, `vector`.
Additionally, all alternate encodings of `pointer`, `optional`, and
`array`.
Diffstat (limited to 'src/type.zig')
| -rw-r--r-- | src/type.zig | 1770 |
1 files changed, 472 insertions, 1298 deletions
diff --git a/src/type.zig b/src/type.zig index 868ae4231b..1f970919c9 100644 --- a/src/type.zig +++ b/src/type.zig @@ -40,7 +40,7 @@ pub const Type = struct { .ptr_type => return .Pointer, .array_type => return .Array, .vector_type => return .Vector, - .optional_type => return .Optional, + .opt_type => return .Optional, .error_union_type => return .ErrorUnion, .struct_type => return .Struct, .union_type => return .Union, @@ -118,38 +118,17 @@ pub const Type = struct { .function => return .Fn, .array, - .array_u8_sentinel_0, - .array_u8, .array_sentinel, => return .Array, - .vector => return .Vector, - - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .const_slice_u8_sentinel_0, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, .pointer, .inferred_alloc_const, .inferred_alloc_mut, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, => return .Pointer, - .optional, - .optional_single_const_pointer, - .optional_single_mut_pointer, - => return .Optional, + .optional => return .Optional, - .anyerror_void_error_union, .error_union => return .ErrorUnion, + .error_union => return .ErrorUnion, .anyframe_T => return .AnyFrame, @@ -177,8 +156,7 @@ pub const Type = struct { return switch (self.zigTypeTag(mod)) { .ErrorUnion => self.errorUnionPayload().baseZigTypeTag(mod), .Optional => { - var buf: Payload.ElemType = undefined; - return self.optionalChild(&buf).baseZigTypeTag(mod); + return self.optionalChild(mod).baseZigTypeTag(mod); }, else => |t| t, }; @@ -218,8 +196,7 @@ pub const Type = struct { .Pointer => !ty.isSlice(mod) and (is_equality_cmp or ty.isCPtr()), .Optional => { if (!is_equality_cmp) return false; - var buf: Payload.ElemType = undefined; - return ty.optionalChild(&buf).isSelfComparable(mod, is_equality_cmp); + return ty.optionalChild(mod).isSelfComparable(mod, is_equality_cmp); }, }; } @@ -275,9 +252,8 @@ pub const Type = struct { } pub fn castTag(self: Type, comptime t: Tag) ?*t.Type() { - if (self.ip_index != .none) { - return null; - } + assert(self.ip_index == .none); + if (@enumToInt(self.legacy.tag_if_small_enough) < Tag.no_payload_count) return null; @@ -287,281 +263,61 @@ pub const Type = struct { return null; } - pub fn castPointer(self: Type) ?*Payload.ElemType { - return switch (self.tag()) { - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .optional_single_const_pointer, - .optional_single_mut_pointer, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, - => self.cast(Payload.ElemType), - - .inferred_alloc_const => unreachable, - .inferred_alloc_mut => unreachable, - - else => null, - }; - } - /// If it is a function pointer, returns the function type. Otherwise returns null. pub fn castPtrToFn(ty: Type, mod: *const Module) ?Type { if (ty.zigTypeTag(mod) != .Pointer) return null; - const elem_ty = ty.childType(); + const elem_ty = ty.childType(mod); if (elem_ty.zigTypeTag(mod) != .Fn) return null; return elem_ty; } - pub fn ptrIsMutable(ty: Type) bool { - return switch (ty.tag()) { - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .const_slice_u8_sentinel_0, - .single_const_pointer, - .many_const_pointer, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, - .c_const_pointer, - .const_slice, - => false, - - .single_mut_pointer, - .many_mut_pointer, - .manyptr_u8, - .c_mut_pointer, - .mut_slice, - => true, - - .pointer => ty.castTag(.pointer).?.data.mutable, - - else => unreachable, + pub fn ptrIsMutable(ty: Type, mod: *const Module) bool { + return switch (ty.ip_index) { + .none => switch (ty.tag()) { + .pointer => ty.castTag(.pointer).?.data.mutable, + else => unreachable, + }, + else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { + .ptr_type => |ptr_type| !ptr_type.is_const, + else => unreachable, + }, }; } - pub const ArrayInfo = struct { elem_type: Type, sentinel: ?Value = null, len: u64 }; - pub fn arrayInfo(self: Type) ArrayInfo { + pub const ArrayInfo = struct { + elem_type: Type, + sentinel: ?Value = null, + len: u64, + }; + + pub fn arrayInfo(self: Type, mod: *const Module) ArrayInfo { return .{ - .len = self.arrayLen(), - .sentinel = self.sentinel(), - .elem_type = self.elemType(), + .len = self.arrayLen(mod), + .sentinel = self.sentinel(mod), + .elem_type = self.childType(mod), }; } - pub fn ptrInfo(self: Type) Payload.Pointer { - switch (self.ip_index) { - .none => switch (self.tag()) { - .single_const_pointer_to_comptime_int => return .{ .data = .{ - .pointee_type = Type.comptime_int, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .One, - } }, - .const_slice_u8 => return .{ .data = .{ - .pointee_type = Type.u8, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .Slice, - } }, - .const_slice_u8_sentinel_0 => return .{ .data = .{ - .pointee_type = Type.u8, - .sentinel = Value.zero, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .Slice, - } }, - .single_const_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .One, - } }, - .single_mut_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = true, - .@"volatile" = false, - .size = .One, - } }, - .many_const_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .Many, - } }, - .manyptr_const_u8 => return .{ .data = .{ - .pointee_type = Type.u8, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .Many, - } }, - .manyptr_const_u8_sentinel_0 => return .{ .data = .{ - .pointee_type = Type.u8, - .sentinel = Value.zero, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .Many, - } }, - .many_mut_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = true, - .@"volatile" = false, - .size = .Many, - } }, - .manyptr_u8 => return .{ .data = .{ - .pointee_type = Type.u8, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = true, - .@"volatile" = false, - .size = .Many, - } }, - .c_const_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = true, - .mutable = false, - .@"volatile" = false, - .size = .C, - } }, - .c_mut_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = true, - .mutable = true, - .@"volatile" = false, - .size = .C, - } }, - .const_slice => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .Slice, - } }, - .mut_slice => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = true, - .@"volatile" = false, - .size = .Slice, - } }, - - .pointer => return self.castTag(.pointer).?.*, - - .optional_single_mut_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = true, - .@"volatile" = false, - .size = .One, - } }, - .optional_single_const_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .One, - } }, - .optional => { - var buf: Payload.ElemType = undefined; - const child_type = self.optionalChild(&buf); - return child_type.ptrInfo(); + pub fn ptrInfo(ty: Type, mod: *const Module) Payload.Pointer.Data { + return switch (ty.ip_index) { + .none => switch (ty.tag()) { + .pointer => ty.castTag(.pointer).?.data, + .optional => b: { + const child_type = ty.optionalChild(mod); + break :b child_type.ptrInfo(mod); }, else => unreachable, }, - else => @panic("TODO"), - } + else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { + .ptr_type => |p| Payload.Pointer.Data.fromKey(p), + .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) { + .ptr_type => |p| Payload.Pointer.Data.fromKey(p), + else => unreachable, + }, + else => unreachable, + }, + }; } pub fn eql(a: Type, b: Type, mod: *Module) bool { @@ -658,20 +414,17 @@ pub const Type = struct { }, .array, - .array_u8_sentinel_0, - .array_u8, .array_sentinel, - .vector, => { if (a.zigTypeTag(mod) != b.zigTypeTag(mod)) return false; - if (a.arrayLen() != b.arrayLen()) + if (a.arrayLen(mod) != b.arrayLen(mod)) return false; - const elem_ty = a.elemType(); - if (!elem_ty.eql(b.elemType(), mod)) + const elem_ty = a.childType(mod); + if (!elem_ty.eql(b.childType(mod), mod)) return false; - const sentinel_a = a.sentinel(); - const sentinel_b = b.sentinel(); + const sentinel_a = a.sentinel(mod); + const sentinel_b = b.sentinel(mod); if (sentinel_a) |sa| { if (sentinel_b) |sb| { return sa.eql(sb, elem_ty, mod); @@ -683,28 +436,14 @@ pub const Type = struct { } }, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .const_slice_u8_sentinel_0, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, .pointer, .inferred_alloc_const, .inferred_alloc_mut, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, => { if (b.zigTypeTag(mod) != .Pointer) return false; - const info_a = a.ptrInfo().data; - const info_b = b.ptrInfo().data; + const info_a = a.ptrInfo(mod); + const info_b = b.ptrInfo(mod); if (!info_a.pointee_type.eql(info_b.pointee_type, mod)) return false; if (info_a.@"align" != info_b.@"align") @@ -743,18 +482,13 @@ pub const Type = struct { return true; }, - .optional, - .optional_single_const_pointer, - .optional_single_mut_pointer, - => { + .optional => { if (b.zigTypeTag(mod) != .Optional) return false; - var buf_a: Payload.ElemType = undefined; - var buf_b: Payload.ElemType = undefined; - return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b), mod); + return a.optionalChild(mod).eql(b.optionalChild(mod), mod); }, - .anyerror_void_error_union, .error_union => { + .error_union => { if (b.zigTypeTag(mod) != .ErrorUnion) return false; const a_set = a.errorUnionSet(); @@ -947,47 +681,23 @@ pub const Type = struct { }, .array, - .array_u8_sentinel_0, - .array_u8, .array_sentinel, => { std.hash.autoHash(hasher, std.builtin.TypeId.Array); - const elem_ty = ty.elemType(); - std.hash.autoHash(hasher, ty.arrayLen()); + const elem_ty = ty.childType(mod); + std.hash.autoHash(hasher, ty.arrayLen(mod)); hashWithHasher(elem_ty, hasher, mod); - hashSentinel(ty.sentinel(), elem_ty, hasher, mod); + hashSentinel(ty.sentinel(mod), elem_ty, hasher, mod); }, - .vector => { - std.hash.autoHash(hasher, std.builtin.TypeId.Vector); - - const elem_ty = ty.elemType(); - std.hash.autoHash(hasher, ty.vectorLen()); - hashWithHasher(elem_ty, hasher, mod); - }, - - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .const_slice_u8_sentinel_0, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, .pointer, .inferred_alloc_const, .inferred_alloc_mut, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, => { std.hash.autoHash(hasher, std.builtin.TypeId.Pointer); - const info = ty.ptrInfo().data; + const info = ty.ptrInfo(mod); hashWithHasher(info.pointee_type, hasher, mod); hashSentinel(info.sentinel, info.pointee_type, hasher, mod); std.hash.autoHash(hasher, info.@"align"); @@ -1001,17 +711,13 @@ pub const Type = struct { std.hash.autoHash(hasher, info.size); }, - .optional, - .optional_single_const_pointer, - .optional_single_mut_pointer, - => { + .optional => { std.hash.autoHash(hasher, std.builtin.TypeId.Optional); - var buf: Payload.ElemType = undefined; - hashWithHasher(ty.optionalChild(&buf), hasher, mod); + hashWithHasher(ty.optionalChild(mod), hasher, mod); }, - .anyerror_void_error_union, .error_union => { + .error_union => { std.hash.autoHash(hasher, std.builtin.TypeId.ErrorUnion); const set_ty = ty.errorUnionSet(); @@ -1023,7 +729,7 @@ pub const Type = struct { .anyframe_T => { std.hash.autoHash(hasher, std.builtin.TypeId.AnyFrame); - hashWithHasher(ty.childType(), hasher, mod); + hashWithHasher(ty.childType(mod), hasher, mod); }, .empty_struct => { @@ -1129,33 +835,12 @@ pub const Type = struct { .legacy = .{ .tag_if_small_enough = self.legacy.tag_if_small_enough }, }; } else switch (self.legacy.ptr_otherwise.tag) { - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .const_slice_u8_sentinel_0, - .anyerror_void_error_union, .inferred_alloc_const, .inferred_alloc_mut, .empty_struct_literal, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, => unreachable, - .array_u8, - .array_u8_sentinel_0, - => return self.copyPayloadShallow(allocator, Payload.Len), - - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, .anyframe_T, => { const payload = self.cast(Payload.ElemType).?; @@ -1170,13 +855,6 @@ pub const Type = struct { }; }, - .vector => { - const payload = self.castTag(.vector).?.data; - return Tag.vector.create(allocator, .{ - .len = payload.len, - .elem_type = try payload.elem_type.copy(allocator), - }); - }, .array => { const payload = self.castTag(.array).?.data; return Tag.array.create(allocator, .{ @@ -1408,13 +1086,6 @@ pub const Type = struct { }); }, - .anyerror_void_error_union => return writer.writeAll("anyerror!void"), - .const_slice_u8 => return writer.writeAll("[]const u8"), - .const_slice_u8_sentinel_0 => return writer.writeAll("[:0]const u8"), - .single_const_pointer_to_comptime_int => return writer.writeAll("*const comptime_int"), - .manyptr_u8 => return writer.writeAll("[*]u8"), - .manyptr_const_u8 => return writer.writeAll("[*]const u8"), - .manyptr_const_u8_sentinel_0 => return writer.writeAll("[*:0]const u8"), .function => { const payload = ty.castTag(.function).?.data; try writer.writeAll("fn("); @@ -1447,20 +1118,6 @@ pub const Type = struct { ty = return_type; continue; }, - .array_u8 => { - const len = ty.castTag(.array_u8).?.data; - return writer.print("[{d}]u8", .{len}); - }, - .array_u8_sentinel_0 => { - const len = ty.castTag(.array_u8_sentinel_0).?.data; - return writer.print("[{d}:0]u8", .{len}); - }, - .vector => { - const payload = ty.castTag(.vector).?.data; - try writer.print("@Vector({d}, ", .{payload.len}); - try payload.elem_type.dump("", .{}, writer); - return writer.writeAll(")"); - }, .array => { const payload = ty.castTag(.array).?.data; try writer.print("[{d}]", .{payload.len}); @@ -1512,72 +1169,12 @@ pub const Type = struct { try writer.writeAll("}"); return; }, - .single_const_pointer => { - const pointee_type = ty.castTag(.single_const_pointer).?.data; - try writer.writeAll("*const "); - ty = pointee_type; - continue; - }, - .single_mut_pointer => { - const pointee_type = ty.castTag(.single_mut_pointer).?.data; - try writer.writeAll("*"); - ty = pointee_type; - continue; - }, - .many_const_pointer => { - const pointee_type = ty.castTag(.many_const_pointer).?.data; - try writer.writeAll("[*]const "); - ty = pointee_type; - continue; - }, - .many_mut_pointer => { - const pointee_type = ty.castTag(.many_mut_pointer).?.data; - try writer.writeAll("[*]"); - ty = pointee_type; - continue; - }, - .c_const_pointer => { - const pointee_type = ty.castTag(.c_const_pointer).?.data; - try writer.writeAll("[*c]const "); - ty = pointee_type; - continue; - }, - .c_mut_pointer => { - const pointee_type = ty.castTag(.c_mut_pointer).?.data; - try writer.writeAll("[*c]"); - ty = pointee_type; - continue; - }, - .const_slice => { - const pointee_type = ty.castTag(.const_slice).?.data; - try writer.writeAll("[]const "); - ty = pointee_type; - continue; - }, - .mut_slice => { - const pointee_type = ty.castTag(.mut_slice).?.data; - try writer.writeAll("[]"); - ty = pointee_type; - continue; - }, .optional => { const child_type = ty.castTag(.optional).?.data; try writer.writeByte('?'); ty = child_type; continue; }, - .optional_single_const_pointer => { - const pointee_type = ty.castTag(.optional_single_const_pointer).?.data; - try writer.writeAll("?*const "); - ty = pointee_type; - continue; - }, - .optional_single_mut_pointer => { - const pointee_type = ty.castTag(.optional_single_mut_pointer).?.data; - try writer.writeAll("?*"); - ty = pointee_type; - continue; - }, .pointer => { const payload = ty.castTag(.pointer).?.data; @@ -1680,7 +1277,7 @@ pub const Type = struct { .ptr_type => @panic("TODO"), .array_type => @panic("TODO"), .vector_type => @panic("TODO"), - .optional_type => @panic("TODO"), + .opt_type => @panic("TODO"), .error_union_type => @panic("TODO"), .simple_type => |s| return writer.writeAll(@tagName(s)), .struct_type => @panic("TODO"), @@ -1733,14 +1330,6 @@ pub const Type = struct { try decl.renderFullyQualifiedName(mod, writer); }, - .anyerror_void_error_union => try writer.writeAll("anyerror!void"), - .const_slice_u8 => try writer.writeAll("[]const u8"), - .const_slice_u8_sentinel_0 => try writer.writeAll("[:0]const u8"), - .single_const_pointer_to_comptime_int => try writer.writeAll("*const comptime_int"), - .manyptr_u8 => try writer.writeAll("[*]u8"), - .manyptr_const_u8 => try writer.writeAll("[*]const u8"), - .manyptr_const_u8_sentinel_0 => try writer.writeAll("[*:0]const u8"), - .error_set_inferred => { const func = ty.castTag(.error_set_inferred).?.data.func; @@ -1799,20 +1388,6 @@ pub const Type = struct { try print(error_union.payload, writer, mod); }, - .array_u8 => { - const len = ty.castTag(.array_u8).?.data; - try writer.print("[{d}]u8", .{len}); - }, - .array_u8_sentinel_0 => { - const len = ty.castTag(.array_u8_sentinel_0).?.data; - try writer.print("[{d}:0]u8", .{len}); - }, - .vector => { - const payload = ty.castTag(.vector).?.data; - try writer.print("@Vector({d}, ", .{payload.len}); - try print(payload.elem_type, writer, mod); - try writer.writeAll(")"); - }, .array => { const payload = ty.castTag(.array).?.data; try writer.print("[{d}]", .{payload.len}); @@ -1865,17 +1440,8 @@ pub const Type = struct { try writer.writeAll("}"); }, - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - => { - const info = ty.ptrInfo().data; + .pointer => { + const info = ty.ptrInfo(mod); if (info.sentinel) |s| switch (info.size) { .One, .C => unreachable, @@ -1920,16 +1486,6 @@ pub const Type = struct { try writer.writeByte('?'); try print(child_type, writer, mod); }, - .optional_single_mut_pointer => { - const pointee_type = ty.castTag(.optional_single_mut_pointer).?.data; - try writer.writeAll("?*"); - try print(pointee_type, writer, mod); - }, - .optional_single_const_pointer => { - const pointee_type = ty.castTag(.optional_single_const_pointer).?.data; - try writer.writeAll("?*const "); - try print(pointee_type, writer, mod); - }, .anyframe_T => { const return_type = ty.castTag(.anyframe_T).?.data; try writer.print("anyframe->", .{}); @@ -1963,12 +1519,6 @@ pub const Type = struct { pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value { if (self.ip_index != .none) return self.ip_index.toValue(); switch (self.tag()) { - .single_const_pointer_to_comptime_int => return Value{ .ip_index = .single_const_pointer_to_comptime_int_type, .legacy = undefined }, - .const_slice_u8 => return Value{ .ip_index = .const_slice_u8_type, .legacy = undefined }, - .const_slice_u8_sentinel_0 => return Value{ .ip_index = .const_slice_u8_sentinel_0_type, .legacy = undefined }, - .manyptr_u8 => return Value{ .ip_index = .manyptr_u8_type, .legacy = undefined }, - .manyptr_const_u8 => return Value{ .ip_index = .manyptr_const_u8_type, .legacy = undefined }, - .manyptr_const_u8_sentinel_0 => return Value{ .ip_index = .manyptr_const_u8_sentinel_0_type, .legacy = undefined }, .inferred_alloc_const => unreachable, .inferred_alloc_mut => unreachable, else => return Value.Tag.ty.create(allocator, self), @@ -1996,10 +1546,41 @@ pub const Type = struct { ) RuntimeBitsError!bool { if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { .int_type => |int_type| return int_type.bits != 0, - .ptr_type => @panic("TODO"), - .array_type => @panic("TODO"), - .vector_type => @panic("TODO"), - .optional_type => @panic("TODO"), + .ptr_type => |ptr_type| { + // Pointers to zero-bit types still have a runtime address; however, pointers + // to comptime-only types do not, with the exception of function pointers. + if (ignore_comptime_only) return true; + const child_ty = ptr_type.elem_type.toType(); + if (child_ty.zigTypeTag(mod) == .Fn) return !child_ty.fnInfo().is_generic; + if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty)); + return !comptimeOnly(ty, mod); + }, + .array_type => |array_type| { + if (array_type.sentinel != .none) { + return array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); + } else { + return array_type.len > 0 and + try array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); + } + }, + .vector_type => |vector_type| { + return vector_type.len > 0 and + try vector_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); + }, + .opt_type => |child| { + const child_ty = child.toType(); + if (child_ty.isNoReturn()) { + // Then the optional is comptime-known to be null. + return false; + } + if (ignore_comptime_only) { + return true; + } else if (strat == .sema) { + return !(try strat.sema.typeRequiresComptime(child_ty)); + } else { + return !comptimeOnly(child_ty, mod); + } + }, .error_union_type => @panic("TODO"), .simple_type => |t| return switch (t) { .f16, @@ -2058,14 +1639,7 @@ pub const Type = struct { .enum_tag => unreachable, // it's a value, not a type }; switch (ty.tag()) { - .const_slice_u8, - .const_slice_u8_sentinel_0, - .array_u8_sentinel_0, - .anyerror_void_error_union, .error_set_inferred, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, .@"opaque", .error_set_single, @@ -2077,22 +1651,12 @@ pub const Type = struct { // Pointers to zero-bit types still have a runtime address; however, pointers // to comptime-only types do not, with the exception of function pointers. .anyframe_T, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, .pointer, => { if (ignore_comptime_only) { return true; - } else if (ty.childType().zigTypeTag(mod) == .Fn) { - return !ty.childType().fnInfo().is_generic; + } else if (ty.childType(mod).zigTypeTag(mod) == .Fn) { + return !ty.childType(mod).fnInfo().is_generic; } else if (strat == .sema) { return !(try strat.sema.typeRequiresComptime(ty)); } else { @@ -2101,7 +1665,6 @@ pub const Type = struct { }, // These are false because they are comptime-only types. - .single_const_pointer_to_comptime_int, .empty_struct, .empty_struct_literal, // These are function *bodies*, not pointers. @@ -2111,8 +1674,7 @@ pub const Type = struct { => return false, .optional => { - var buf: Payload.ElemType = undefined; - const child_ty = ty.optionalChild(&buf); + const child_ty = ty.optionalChild(mod); if (child_ty.isNoReturn()) { // Then the optional is comptime-known to be null. return false; @@ -2200,10 +1762,9 @@ pub const Type = struct { } }, - .array, .vector => return ty.arrayLen() != 0 and - try ty.elemType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), - .array_u8 => return ty.arrayLen() != 0, - .array_sentinel => return ty.childType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), + .array => return ty.arrayLen(mod) != 0 and + try ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), + .array_sentinel => return ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), .tuple, .anon_struct => { const tuple = ty.tupleFields(); @@ -2224,14 +1785,14 @@ pub const Type = struct { /// readFrom/writeToMemory are supported only for types with a well- /// defined memory layout pub fn hasWellDefinedLayout(ty: Type, mod: *const Module) bool { - if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { - .int_type => return true, - .ptr_type => @panic("TODO"), - .array_type => @panic("TODO"), - .vector_type => @panic("TODO"), - .optional_type => @panic("TODO"), - .error_union_type => @panic("TODO"), - .simple_type => |t| return switch (t) { + if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) { + .int_type => true, + .ptr_type => true, + .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod), + .vector_type => true, + .opt_type => |child| child.toType().isPtrLikeOptional(mod), + .error_union_type => false, + .simple_type => |t| switch (t) { .f16, .f32, .f64, @@ -2287,23 +1848,8 @@ pub const Type = struct { .enum_tag => unreachable, // it's a value, not a type }; return switch (ty.tag()) { - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, - .array_u8, - .array_u8_sentinel_0, .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .single_const_pointer_to_comptime_int, .enum_numbered, - .vector, - .optional_single_mut_pointer, - .optional_single_const_pointer, => true, .error_set, @@ -2313,13 +1859,8 @@ pub const Type = struct { .@"opaque", // These are function bodies, not function pointers. .function, - .const_slice_u8, - .const_slice_u8_sentinel_0, - .const_slice, - .mut_slice, .enum_simple, .error_union, - .anyerror_void_error_union, .anyframe_T, .tuple, .anon_struct, @@ -2336,7 +1877,7 @@ pub const Type = struct { .array, .array_sentinel, - => ty.childType().hasWellDefinedLayout(mod), + => ty.childType(mod).hasWellDefinedLayout(mod), .optional => ty.isPtrLikeOptional(mod), .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto, @@ -2417,76 +1958,36 @@ pub const Type = struct { } pub fn ptrAlignmentAdvanced(ty: Type, mod: *const Module, opt_sema: ?*Sema) !u32 { - switch (ty.tag()) { - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .optional_single_const_pointer, - .optional_single_mut_pointer, - => { - const child_type = ty.cast(Payload.ElemType).?.data; - if (opt_sema) |sema| { - const res = try child_type.abiAlignmentAdvanced(mod, .{ .sema = sema }); - return res.scalar; - } - return (child_type.abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar; - }, - - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, - .const_slice_u8, - .const_slice_u8_sentinel_0, - => return 1, + switch (ty.ip_index) { + .none => switch (ty.tag()) { + .pointer => { + const ptr_info = ty.castTag(.pointer).?.data; + if (ptr_info.@"align" != 0) { + return ptr_info.@"align"; + } else if (opt_sema) |sema| { + const res = try ptr_info.pointee_type.abiAlignmentAdvanced(mod, .{ .sema = sema }); + return res.scalar; + } else { + return (ptr_info.pointee_type.abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar; + } + }, + .optional => return ty.castTag(.optional).?.data.ptrAlignmentAdvanced(mod, opt_sema), - .pointer => { - const ptr_info = ty.castTag(.pointer).?.data; - if (ptr_info.@"align" != 0) { - return ptr_info.@"align"; - } else if (opt_sema) |sema| { - const res = try ptr_info.pointee_type.abiAlignmentAdvanced(mod, .{ .sema = sema }); - return res.scalar; - } else { - return (ptr_info.pointee_type.abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar; - } + else => unreachable, + }, + else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { + else => @panic("TODO"), }, - .optional => return ty.castTag(.optional).?.data.ptrAlignmentAdvanced(mod, opt_sema), - - else => unreachable, } } - pub fn ptrAddressSpace(self: Type) std.builtin.AddressSpace { + pub fn ptrAddressSpace(self: Type, mod: *const Module) std.builtin.AddressSpace { return switch (self.tag()) { - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .const_slice_u8_sentinel_0, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .inferred_alloc_const, - .inferred_alloc_mut, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, - => .generic, - .pointer => self.castTag(.pointer).?.data.@"addrspace", .optional => { - var buf: Payload.ElemType = undefined; - const child_type = self.optionalChild(&buf); - return child_type.ptrAddressSpace(); + const child_type = self.optionalChild(mod); + return child_type.ptrAddressSpace(mod); }, else => unreachable, @@ -2530,15 +2031,31 @@ pub const Type = struct { ) Module.CompileError!AbiAlignmentAdvanced { const target = mod.getTarget(); + const opt_sema = switch (strat) { + .sema => |sema| sema, + else => null, + }; + if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { .int_type => |int_type| { if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 }; return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(int_type.bits, target) }; }, - .ptr_type => @panic("TODO"), - .array_type => @panic("TODO"), - .vector_type => @panic("TODO"), - .optional_type => @panic("TODO"), + .ptr_type => { + return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }; + }, + .array_type => |array_type| { + return array_type.child.toType().abiAlignmentAdvanced(mod, strat); + }, + .vector_type => |vector_type| { + const bits_u64 = try bitSizeAdvanced(vector_type.child.toType(), mod, opt_sema); + const bits = @intCast(u32, bits_u64); + const bytes = ((bits * vector_type.len) + 7) / 8; + const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); + return AbiAlignmentAdvanced{ .scalar = alignment }; + }, + + .opt_type => @panic("TODO"), .error_union_type => @panic("TODO"), .simple_type => |t| switch (t) { .bool, @@ -2617,15 +2134,8 @@ pub const Type = struct { .enum_tag => unreachable, // it's a value, not a type }; - const opt_sema = switch (strat) { - .sema => |sema| sema, - else => null, - }; switch (ty.tag()) { - .array_u8_sentinel_0, - .array_u8, - .@"opaque", - => return AbiAlignmentAdvanced{ .scalar = 1 }, + .@"opaque" => return AbiAlignmentAdvanced{ .scalar = 1 }, // represents machine code; not a pointer .function => { @@ -2634,47 +2144,21 @@ pub const Type = struct { return AbiAlignmentAdvanced{ .scalar = target_util.defaultFunctionAlignment(target) }; }, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .const_slice_u8_sentinel_0, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .optional_single_const_pointer, - .optional_single_mut_pointer, .pointer, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, .anyframe_T, => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, // TODO revisit this when we have the concept of the error tag type - .anyerror_void_error_union, .error_set_inferred, .error_set_single, .error_set, .error_set_merged, => return AbiAlignmentAdvanced{ .scalar = 2 }, - .array, .array_sentinel => return ty.elemType().abiAlignmentAdvanced(mod, strat), - - .vector => { - const len = ty.arrayLen(); - const bits = try bitSizeAdvanced(ty.elemType(), mod, opt_sema); - const bytes = ((bits * len) + 7) / 8; - const alignment = std.math.ceilPowerOfTwoAssert(u64, bytes); - return AbiAlignmentAdvanced{ .scalar = @intCast(u32, alignment) }; - }, + .array, .array_sentinel => return ty.childType(mod).abiAlignmentAdvanced(mod, strat), .optional => { - var buf: Payload.ElemType = undefined; - const child_type = ty.optionalChild(&buf); + const child_type = ty.optionalChild(mod); switch (child_type.zigTypeTag(mod)) { .Pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, @@ -2933,8 +2417,29 @@ pub const Type = struct { }, .ptr_type => @panic("TODO"), .array_type => @panic("TODO"), - .vector_type => @panic("TODO"), - .optional_type => @panic("TODO"), + .vector_type => |vector_type| { + const opt_sema = switch (strat) { + .sema => |sema| sema, + .eager => null, + .lazy => |arena| return AbiSizeAdvanced{ + .val = try Value.Tag.lazy_size.create(arena, ty), + }, + }; + const elem_bits_u64 = try vector_type.child.toType().bitSizeAdvanced(mod, opt_sema); + const elem_bits = @intCast(u32, elem_bits_u64); + const total_bits = elem_bits * vector_type.len; + const total_bytes = (total_bits + 7) / 8; + const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) { + .scalar => |x| x, + .val => return AbiSizeAdvanced{ + .val = try Value.Tag.lazy_size.create(strat.lazy, ty), + }, + }; + const result = std.mem.alignForwardGeneric(u32, total_bytes, alignment); + return AbiSizeAdvanced{ .scalar = result }; + }, + + .opt_type => @panic("TODO"), .error_union_type => @panic("TODO"), .simple_type => |t| switch (t) { .bool, @@ -3014,7 +2519,6 @@ pub const Type = struct { .inferred_alloc_const => unreachable, .inferred_alloc_mut => unreachable, - .single_const_pointer_to_comptime_int, .empty_struct_literal, .empty_struct, => return AbiSizeAdvanced{ .scalar = 0 }, @@ -3068,8 +2572,6 @@ pub const Type = struct { return abiSizeAdvancedUnion(ty, mod, strat, union_obj, true); }, - .array_u8 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8).?.data }, - .array_u8_sentinel_0 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8_sentinel_0).?.data + 1 }, .array => { const payload = ty.castTag(.array).?.data; switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) { @@ -3093,47 +2595,7 @@ pub const Type = struct { } }, - .vector => { - const payload = ty.castTag(.vector).?.data; - const opt_sema = switch (strat) { - .sema => |sema| sema, - .eager => null, - .lazy => |arena| return AbiSizeAdvanced{ - .val = try Value.Tag.lazy_size.create(arena, ty), - }, - }; - const elem_bits = try payload.elem_type.bitSizeAdvanced(mod, opt_sema); - const total_bits = elem_bits * payload.len; - const total_bytes = (total_bits + 7) / 8; - const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) { - .scalar => |x| x, - .val => return AbiSizeAdvanced{ - .val = try Value.Tag.lazy_size.create(strat.lazy, ty), - }, - }; - const result = std.mem.alignForwardGeneric(u64, total_bytes, alignment); - return AbiSizeAdvanced{ .scalar = result }; - }, - - .anyframe_T, - .optional_single_const_pointer, - .optional_single_mut_pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, - => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, - - .const_slice, - .mut_slice, - .const_slice_u8, - .const_slice_u8_sentinel_0, - => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 }, + .anyframe_T => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, .pointer => switch (ty.castTag(.pointer).?.data.size) { .Slice => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 }, @@ -3141,7 +2603,6 @@ pub const Type = struct { }, // TODO revisit this when we have the concept of the error tag type - .anyerror_void_error_union, .error_set_inferred, .error_set, .error_set_merged, @@ -3149,8 +2610,7 @@ pub const Type = struct { => return AbiSizeAdvanced{ .scalar = 2 }, .optional => { - var buf: Payload.ElemType = undefined; - const child_type = ty.optionalChild(&buf); + const child_type = ty.optionalChild(mod); if (child_type.isNoReturn()) { return AbiSizeAdvanced{ .scalar = 0 }; @@ -3272,8 +2732,12 @@ pub const Type = struct { .int_type => |int_type| return int_type.bits, .ptr_type => @panic("TODO"), .array_type => @panic("TODO"), - .vector_type => @panic("TODO"), - .optional_type => @panic("TODO"), + .vector_type => |vector_type| { + const child_ty = vector_type.child.toType(); + const elem_bit_size = try bitSizeAdvanced(child_ty, mod, opt_sema); + return elem_bit_size * vector_type.len; + }, + .opt_type => @panic("TODO"), .error_union_type => @panic("TODO"), .simple_type => |t| switch (t) { .f16 => return 16, @@ -3339,7 +2803,6 @@ pub const Type = struct { switch (ty.tag()) { .function => unreachable, // represents machine code; not a pointer - .single_const_pointer_to_comptime_int => unreachable, .empty_struct => unreachable, .empty_struct_literal => unreachable, .inferred_alloc_const => unreachable, @@ -3388,13 +2851,6 @@ pub const Type = struct { return size; }, - .vector => { - const payload = ty.castTag(.vector).?.data; - const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema); - return elem_bit_size * payload.len; - }, - .array_u8 => return 8 * ty.castTag(.array_u8).?.data, - .array_u8_sentinel_0 => return 8 * (ty.castTag(.array_u8_sentinel_0).?.data + 1), .array => { const payload = ty.castTag(.array).?.data; const elem_size = std.math.max(payload.elem_type.abiAlignment(mod), payload.elem_type.abiSize(mod)); @@ -3415,43 +2871,13 @@ pub const Type = struct { .anyframe_T => return target.ptrBitWidth(), - .const_slice, - .mut_slice, - => return target.ptrBitWidth() * 2, - - .const_slice_u8, - .const_slice_u8_sentinel_0, - => return target.ptrBitWidth() * 2, - - .optional_single_const_pointer, - .optional_single_mut_pointer, - => { - return target.ptrBitWidth(); - }, - - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - => { - return target.ptrBitWidth(); - }, - .pointer => switch (ty.castTag(.pointer).?.data.size) { .Slice => return target.ptrBitWidth() * 2, else => return target.ptrBitWidth(), }, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, - => return target.ptrBitWidth(), - .error_set, .error_set_single, - .anyerror_void_error_union, .error_set_inferred, .error_set_merged, => return 16, // TODO revisit this when we have the concept of the error tag type @@ -3481,12 +2907,11 @@ pub const Type = struct { return true; }, .Array => { - if (ty.arrayLenIncludingSentinel() == 0) return true; - return ty.childType().layoutIsResolved(mod); + if (ty.arrayLenIncludingSentinel(mod) == 0) return true; + return ty.childType(mod).layoutIsResolved(mod); }, .Optional => { - var buf: Type.Payload.ElemType = undefined; - const payload_ty = ty.optionalChild(&buf); + const payload_ty = ty.optionalChild(mod); return payload_ty.layoutIsResolved(mod); }, .ErrorUnion => { @@ -3500,9 +2925,6 @@ pub const Type = struct { pub fn isSinglePointer(ty: Type, mod: *const Module) bool { switch (ty.ip_index) { .none => return switch (ty.tag()) { - .single_const_pointer, - .single_mut_pointer, - .single_const_pointer_to_comptime_int, .inferred_alloc_const, .inferred_alloc_mut, => true, @@ -3519,54 +2941,33 @@ pub const Type = struct { } /// Asserts `ty` is a pointer. - pub fn ptrSize(ty: Type) std.builtin.Type.Pointer.Size { - return ptrSizeOrNull(ty).?; + pub fn ptrSize(ty: Type, mod: *const Module) std.builtin.Type.Pointer.Size { + return ptrSizeOrNull(ty, mod).?; } /// Returns `null` if `ty` is not a pointer. - pub fn ptrSizeOrNull(ty: Type) ?std.builtin.Type.Pointer.Size { - return switch (ty.tag()) { - .const_slice, - .mut_slice, - .const_slice_u8, - .const_slice_u8_sentinel_0, - => .Slice, - - .many_const_pointer, - .many_mut_pointer, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, - => .Many, - - .c_const_pointer, - .c_mut_pointer, - => .C, - - .single_const_pointer, - .single_mut_pointer, - .single_const_pointer_to_comptime_int, - .inferred_alloc_const, - .inferred_alloc_mut, - => .One, + pub fn ptrSizeOrNull(ty: Type, mod: *const Module) ?std.builtin.Type.Pointer.Size { + return switch (ty.ip_index) { + .none => switch (ty.tag()) { + .inferred_alloc_const, + .inferred_alloc_mut, + => .One, - .pointer => ty.castTag(.pointer).?.data.size, + .pointer => ty.castTag(.pointer).?.data.size, - else => null, + else => null, + }, + else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { + .ptr_type => |ptr_info| ptr_info.size, + else => null, + }, }; } pub fn isSlice(ty: Type, mod: *const Module) bool { return switch (ty.ip_index) { .none => switch (ty.tag()) { - .const_slice, - .mut_slice, - .const_slice_u8, - .const_slice_u8_sentinel_0, - => true, - .pointer => ty.castTag(.pointer).?.data.size == .Slice, - else => false, }, else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { @@ -3583,78 +2984,28 @@ pub const Type = struct { pub fn slicePtrFieldType(self: Type, buffer: *SlicePtrFieldTypeBuffer) Type { switch (self.tag()) { - .const_slice_u8 => return Type.initTag(.manyptr_const_u8), - .const_slice_u8_sentinel_0 => return Type.initTag(.manyptr_const_u8_sentinel_0), - - .const_slice => { - const elem_type = self.castTag(.const_slice).?.data; - buffer.* = .{ - .elem_type = .{ - .base = .{ .tag = .many_const_pointer }, - .data = elem_type, - }, - }; - return Type.initPayload(&buffer.elem_type.base); - }, - .mut_slice => { - const elem_type = self.castTag(.mut_slice).?.data; - buffer.* = .{ - .elem_type = .{ - .base = .{ .tag = .many_mut_pointer }, - .data = elem_type, - }, - }; - return Type.initPayload(&buffer.elem_type.base); - }, - .pointer => { const payload = self.castTag(.pointer).?.data; assert(payload.size == .Slice); - if (payload.sentinel != null or - payload.@"align" != 0 or - payload.@"addrspace" != .generic or - payload.bit_offset != 0 or - payload.host_size != 0 or - payload.vector_index != .none or - payload.@"allowzero" or - payload.@"volatile") - { - buffer.* = .{ - .pointer = .{ - .data = .{ - .pointee_type = payload.pointee_type, - .sentinel = payload.sentinel, - .@"align" = payload.@"align", - .@"addrspace" = payload.@"addrspace", - .bit_offset = payload.bit_offset, - .host_size = payload.host_size, - .vector_index = payload.vector_index, - .@"allowzero" = payload.@"allowzero", - .mutable = payload.mutable, - .@"volatile" = payload.@"volatile", - .size = .Many, - }, - }, - }; - return Type.initPayload(&buffer.pointer.base); - } else if (payload.mutable) { - buffer.* = .{ - .elem_type = .{ - .base = .{ .tag = .many_mut_pointer }, - .data = payload.pointee_type, - }, - }; - return Type.initPayload(&buffer.elem_type.base); - } else { - buffer.* = .{ - .elem_type = .{ - .base = .{ .tag = .many_const_pointer }, - .data = payload.pointee_type, + buffer.* = .{ + .pointer = .{ + .data = .{ + .pointee_type = payload.pointee_type, + .sentinel = payload.sentinel, + .@"align" = payload.@"align", + .@"addrspace" = payload.@"addrspace", + .bit_offset = payload.bit_offset, + .host_size = payload.host_size, + .vector_index = payload.vector_index, + .@"allowzero" = payload.@"allowzero", + .mutable = payload.mutable, + .@"volatile" = payload.@"volatile", + .size = .Many, }, - }; - return Type.initPayload(&buffer.elem_type.base); - } + }, + }; + return Type.initPayload(&buffer.pointer.base); }, else => unreachable, @@ -3663,19 +3014,7 @@ pub const Type = struct { pub fn isConstPtr(self: Type) bool { return switch (self.tag()) { - .single_const_pointer, - .many_const_pointer, - .c_const_pointer, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .const_slice_u8_sentinel_0, - .const_slice, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, - => true, - .pointer => !self.castTag(.pointer).?.data.mutable, - else => false, }; } @@ -3702,49 +3041,46 @@ pub const Type = struct { pub fn isCPtr(self: Type) bool { return switch (self.tag()) { - .c_const_pointer, - .c_mut_pointer, - => return true, - .pointer => self.castTag(.pointer).?.data.size == .C, else => return false, }; } - pub fn isPtrAtRuntime(self: Type, mod: *const Module) bool { - switch (self.tag()) { - .c_const_pointer, - .c_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, - .manyptr_u8, - .optional_single_const_pointer, - .optional_single_mut_pointer, - .single_const_pointer, - .single_const_pointer_to_comptime_int, - .single_mut_pointer, - => return true, + pub fn isPtrAtRuntime(ty: Type, mod: *const Module) bool { + switch (ty.ip_index) { + .none => switch (ty.tag()) { + .pointer => switch (ty.castTag(.pointer).?.data.size) { + .Slice => return false, + .One, .Many, .C => return true, + }, - .pointer => switch (self.castTag(.pointer).?.data.size) { - .Slice => return false, - .One, .Many, .C => return true, - }, + .optional => { + const child_type = ty.optionalChild(mod); + if (child_type.zigTypeTag(mod) != .Pointer) return false; + const info = child_type.ptrInfo(mod); + switch (info.size) { + .Slice, .C => return false, + .Many, .One => return !info.@"allowzero", + } + }, - .optional => { - var buf: Payload.ElemType = undefined; - const child_type = self.optionalChild(&buf); - if (child_type.zigTypeTag(mod) != .Pointer) return false; - const info = child_type.ptrInfo().data; - switch (info.size) { - .Slice, .C => return false, - .Many, .One => return !info.@"allowzero", - } + else => return false, + }, + else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) { + .ptr_type => |ptr_type| switch (ptr_type.size) { + .Slice => false, + .One, .Many, .C => true, + }, + .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) { + .ptr_type => |p| switch (p.size) { + .Slice, .C => false, + .Many, .One => !p.is_allowzero, + }, + else => false, + }, + else => false, }, - - else => return false, } } @@ -3754,23 +3090,17 @@ pub const Type = struct { if (ty.isPtrLikeOptional(mod)) { return true; } - return ty.ptrInfo().data.@"allowzero"; + return ty.ptrInfo(mod).@"allowzero"; } /// See also `isPtrLikeOptional`. pub fn optionalReprIsPayload(ty: Type, mod: *const Module) bool { switch (ty.tag()) { - .optional_single_const_pointer, - .optional_single_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - => return true, - .optional => { const child_ty = ty.castTag(.optional).?.data; switch (child_ty.zigTypeTag(mod)) { .Pointer => { - const info = child_ty.ptrInfo().data; + const info = child_ty.ptrInfo(mod); switch (info.size) { .C => return false, .Slice, .Many, .One => return !info.@"allowzero", @@ -3793,7 +3123,7 @@ pub const Type = struct { pub fn isPtrLikeOptional(ty: Type, mod: *const Module) bool { if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) { .ptr_type => |ptr_type| ptr_type.size == .C, - .optional_type => |o| switch (mod.intern_pool.indexToKey(o.payload_type)) { + .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) { .ptr_type => |ptr_type| switch (ptr_type.size) { .Slice, .C => false, .Many, .One => !ptr_type.is_allowzero, @@ -3803,16 +3133,10 @@ pub const Type = struct { else => false, }; switch (ty.tag()) { - .optional_single_const_pointer, - .optional_single_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - => return true, - .optional => { const child_ty = ty.castTag(.optional).?.data; if (child_ty.zigTypeTag(mod) != .Pointer) return false; - const info = child_ty.ptrInfo().data; + const info = child_ty.ptrInfo(mod); switch (info.size) { .Slice, .C => return false, .Many, .One => return !info.@"allowzero", @@ -3828,43 +3152,24 @@ pub const Type = struct { /// For *[N]T, returns [N]T. /// For *T, returns T. /// For [*]T, returns T. - pub fn childType(ty: Type) Type { - return switch (ty.tag()) { - .vector => ty.castTag(.vector).?.data.elem_type, - .array => ty.castTag(.array).?.data.elem_type, - .array_sentinel => ty.castTag(.array_sentinel).?.data.elem_type, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - => ty.castPointer().?.data, - - .array_u8, - .array_u8_sentinel_0, - .const_slice_u8, - .const_slice_u8_sentinel_0, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, - => Type.u8, - - .single_const_pointer_to_comptime_int => Type.comptime_int, - .pointer => ty.castTag(.pointer).?.data.pointee_type, + pub fn childType(ty: Type, mod: *const Module) Type { + return childTypeIp(ty, mod.intern_pool); + } - else => unreachable, + pub fn childTypeIp(ty: Type, ip: InternPool) Type { + return switch (ty.ip_index) { + .none => switch (ty.tag()) { + .array => ty.castTag(.array).?.data.elem_type, + .array_sentinel => ty.castTag(.array_sentinel).?.data.elem_type, + + .pointer => ty.castTag(.pointer).?.data.pointee_type, + + else => unreachable, + }, + else => ip.childType(ty.ip_index).toType(), }; } - /// Asserts the type is a pointer or array type. - /// TODO this is deprecated in favor of `childType`. - pub const elemType = childType; - /// For *[N]T, returns T. /// For ?*T, returns T. /// For ?*[N]T, returns T. @@ -3875,54 +3180,42 @@ pub const Type = struct { /// For []T, returns T. /// For anyframe->T, returns T. pub fn elemType2(ty: Type, mod: *const Module) Type { - return switch (ty.tag()) { - .vector => ty.castTag(.vector).?.data.elem_type, - .array => ty.castTag(.array).?.data.elem_type, - .array_sentinel => ty.castTag(.array_sentinel).?.data.elem_type, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - => ty.castPointer().?.data, - - .single_const_pointer, - .single_mut_pointer, - => ty.castPointer().?.data.shallowElemType(mod), - - .array_u8, - .array_u8_sentinel_0, - .const_slice_u8, - .const_slice_u8_sentinel_0, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, - => Type.u8, - - .single_const_pointer_to_comptime_int => Type.comptime_int, - .pointer => { - const info = ty.castTag(.pointer).?.data; - const child_ty = info.pointee_type; - if (info.size == .One) { - return child_ty.shallowElemType(mod); - } else { - return child_ty; - } - }, - .optional => ty.castTag(.optional).?.data.childType(), - .optional_single_mut_pointer => ty.castPointer().?.data, - .optional_single_const_pointer => ty.castPointer().?.data, + return switch (ty.ip_index) { + .none => switch (ty.tag()) { + .array => ty.castTag(.array).?.data.elem_type, + .array_sentinel => ty.castTag(.array_sentinel).?.data.elem_type, + + .pointer => { + const info = ty.castTag(.pointer).?.data; + const child_ty = info.pointee_type; + if (info.size == .One) { + return child_ty.shallowElemType(mod); + } else { + return child_ty; + } + }, + .optional => ty.castTag(.optional).?.data.childType(mod), - .anyframe_T => ty.castTag(.anyframe_T).?.data, + .anyframe_T => ty.castTag(.anyframe_T).?.data, - else => unreachable, + else => unreachable, + }, + else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { + .ptr_type => |ptr_type| switch (ptr_type.size) { + .One => ptr_type.elem_type.toType().shallowElemType(mod), + .Many, .C, .Slice => ptr_type.elem_type.toType(), + }, + .vector_type => |vector_type| vector_type.child.toType(), + .array_type => |array_type| array_type.child.toType(), + .opt_type => |child| mod.intern_pool.childType(child).toType(), + else => unreachable, + }, }; } fn shallowElemType(child_ty: Type, mod: *const Module) Type { return switch (child_ty.zigTypeTag(mod)) { - .Array, .Vector => child_ty.childType(), + .Array, .Vector => child_ty.childType(mod), else => child_ty, }; } @@ -3930,7 +3223,7 @@ pub const Type = struct { /// For vectors, returns the element type. Otherwise returns self. pub fn scalarType(ty: Type, mod: *const Module) Type { return switch (ty.zigTypeTag(mod)) { - .Vector => ty.childType(), + .Vector => ty.childType(mod), else => ty, }; } @@ -3938,51 +3231,25 @@ pub const Type = struct { /// Asserts that the type is an optional. /// Resulting `Type` will have inner memory referencing `buf`. /// Note that for C pointers this returns the type unmodified. - pub fn optionalChild(ty: Type, buf: *Payload.ElemType) Type { - return switch (ty.tag()) { - .optional => ty.castTag(.optional).?.data, - .optional_single_mut_pointer => { - buf.* = .{ - .base = .{ .tag = .single_mut_pointer }, - .data = ty.castPointer().?.data, - }; - return Type.initPayload(&buf.base); - }, - .optional_single_const_pointer => { - buf.* = .{ - .base = .{ .tag = .single_const_pointer }, - .data = ty.castPointer().?.data, - }; - return Type.initPayload(&buf.base); - }, + pub fn optionalChild(ty: Type, mod: *const Module) Type { + return switch (ty.ip_index) { + .none => switch (ty.tag()) { + .optional => ty.castTag(.optional).?.data, - .pointer, // here we assume it is a C pointer - .c_const_pointer, - .c_mut_pointer, - => return ty, + .pointer, // here we assume it is a C pointer + => return ty, - else => unreachable, - }; - } - - /// Asserts that the type is an optional. - /// Same as `optionalChild` but allocates the buffer if needed. - pub fn optionalChildAlloc(ty: Type, allocator: Allocator) !Type { - switch (ty.tag()) { - .optional => return ty.castTag(.optional).?.data, - .optional_single_mut_pointer => { - return Tag.single_mut_pointer.create(allocator, ty.castPointer().?.data); + else => unreachable, }, - .optional_single_const_pointer => { - return Tag.single_const_pointer.create(allocator, ty.castPointer().?.data); + else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { + .opt_type => |child| child.toType(), + .ptr_type => |ptr_type| b: { + assert(ptr_type.size == .C); + break :b ty; + }, + else => unreachable, }, - .pointer, // here we assume it is a C pointer - .c_const_pointer, - .c_mut_pointer, - => return ty, - - else => unreachable, - } + }; } /// Returns the tag type of a union, if the type is a union and it has a tag type. @@ -4071,19 +3338,25 @@ pub const Type = struct { } /// Asserts that the type is an error union. - pub fn errorUnionPayload(self: Type) Type { - return switch (self.tag()) { - .anyerror_void_error_union => Type.void, - .error_union => self.castTag(.error_union).?.data.payload, - else => unreachable, + pub fn errorUnionPayload(ty: Type) Type { + return switch (ty.ip_index) { + .anyerror_void_error_union_type => Type.void, + .none => switch (ty.tag()) { + .error_union => ty.castTag(.error_union).?.data.payload, + else => unreachable, + }, + else => @panic("TODO"), }; } - pub fn errorUnionSet(self: Type) Type { - return switch (self.tag()) { - .anyerror_void_error_union => Type.anyerror, - .error_union => self.castTag(.error_union).?.data.error_set, - else => unreachable, + pub fn errorUnionSet(ty: Type) Type { + return switch (ty.ip_index) { + .anyerror_void_error_union_type => Type.anyerror, + .none => switch (ty.tag()) { + .error_union => ty.castTag(.error_union).?.data.error_set, + else => unreachable, + }, + else => @panic("TODO"), }; } @@ -4168,67 +3441,73 @@ pub const Type = struct { } /// Asserts the type is an array or vector or struct. - pub fn arrayLen(ty: Type) u64 { - return switch (ty.tag()) { - .vector => ty.castTag(.vector).?.data.len, - .array => ty.castTag(.array).?.data.len, - .array_sentinel => ty.castTag(.array_sentinel).?.data.len, - .array_u8 => ty.castTag(.array_u8).?.data, - .array_u8_sentinel_0 => ty.castTag(.array_u8_sentinel_0).?.data, - .tuple => ty.castTag(.tuple).?.data.types.len, - .anon_struct => ty.castTag(.anon_struct).?.data.types.len, - .@"struct" => ty.castTag(.@"struct").?.data.fields.count(), - .empty_struct, .empty_struct_literal => 0, + pub fn arrayLen(ty: Type, mod: *const Module) u64 { + return arrayLenIp(ty, mod.intern_pool); + } - else => unreachable, + pub fn arrayLenIp(ty: Type, ip: InternPool) u64 { + return switch (ty.ip_index) { + .none => switch (ty.tag()) { + .array => ty.castTag(.array).?.data.len, + .array_sentinel => ty.castTag(.array_sentinel).?.data.len, + .tuple => ty.castTag(.tuple).?.data.types.len, + .anon_struct => ty.castTag(.anon_struct).?.data.types.len, + .@"struct" => ty.castTag(.@"struct").?.data.fields.count(), + .empty_struct, .empty_struct_literal => 0, + + else => unreachable, + }, + else => switch (ip.indexToKey(ty.ip_index)) { + .vector_type => |vector_type| vector_type.len, + .array_type => |array_type| array_type.len, + else => unreachable, + }, }; } - pub fn arrayLenIncludingSentinel(ty: Type) u64 { - return ty.arrayLen() + @boolToInt(ty.sentinel() != null); + pub fn arrayLenIncludingSentinel(ty: Type, mod: *const Module) u64 { + return ty.arrayLen(mod) + @boolToInt(ty.sentinel(mod) != null); } - pub fn vectorLen(ty: Type) u32 { - return switch (ty.tag()) { - .vector => @intCast(u32, ty.castTag(.vector).?.data.len), - .tuple => @intCast(u32, ty.castTag(.tuple).?.data.types.len), - .anon_struct => @intCast(u32, ty.castTag(.anon_struct).?.data.types.len), - else => unreachable, + pub fn vectorLen(ty: Type, mod: *const Module) u32 { + return switch (ty.ip_index) { + .none => switch (ty.tag()) { + .tuple => @intCast(u32, ty.castTag(.tuple).?.data.types.len), + .anon_struct => @intCast(u32, ty.castTag(.anon_struct).?.data.types.len), + else => unreachable, + }, + else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { + .vector_type => |vector_type| vector_type.len, + else => unreachable, + }, }; } /// Asserts the type is an array, pointer or vector. - pub fn sentinel(self: Type) ?Value { - return switch (self.tag()) { - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .single_const_pointer_to_comptime_int, - .vector, - .array, - .array_u8, - .manyptr_u8, - .manyptr_const_u8, - .const_slice_u8, - .const_slice, - .mut_slice, - .tuple, - .empty_struct_literal, - .@"struct", - => return null, + pub fn sentinel(ty: Type, mod: *const Module) ?Value { + return switch (ty.ip_index) { + .none => switch (ty.tag()) { + .array, + .tuple, + .empty_struct_literal, + .@"struct", + => null, - .pointer => return self.castTag(.pointer).?.data.sentinel, - .array_sentinel => return self.castTag(.array_sentinel).?.data.sentinel, + .pointer => ty.castTag(.pointer).?.data.sentinel, + .array_sentinel => ty.castTag(.array_sentinel).?.data.sentinel, - .array_u8_sentinel_0, - .const_slice_u8_sentinel_0, - .manyptr_const_u8_sentinel_0, - => return Value.zero, + else => unreachable, + }, + else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { + .vector_type, + .struct_type, + => null, - else => unreachable, + .array_type => |t| if (t.sentinel != .none) t.sentinel.toValue() else null, + .ptr_type => |t| if (t.sentinel != .none) t.sentinel.toValue() else null, + + else => unreachable, + }, }; } @@ -4292,8 +3571,6 @@ pub const Type = struct { return .{ .signedness = .unsigned, .bits = 16 }; }, - .vector => ty = ty.castTag(.vector).?.data.elem_type, - .@"struct" => { const struct_obj = ty.castTag(.@"struct").?.data; assert(struct_obj.layout == .Packed); @@ -4321,8 +3598,9 @@ pub const Type = struct { .int_type => |int_type| return int_type, .ptr_type => unreachable, .array_type => unreachable, - .vector_type => @panic("TODO"), - .optional_type => unreachable, + .vector_type => |vector_type| ty = vector_type.child.toType(), + + .opt_type => unreachable, .error_union_type => unreachable, .simple_type => unreachable, // handled via Index enum tag above .struct_type => @panic("TODO"), @@ -4426,7 +3704,11 @@ pub const Type = struct { /// Asserts the type is a function or a function pointer. pub fn fnReturnType(ty: Type) Type { - const fn_ty = if (ty.castPointer()) |p| p.data else ty; + const fn_ty = switch (ty.tag()) { + .pointer => ty.castTag(.pointer).?.data.pointee_type, + .function => ty, + else => unreachable, + }; return fn_ty.castTag(.function).?.data.return_type; } @@ -4516,8 +3798,12 @@ pub const Type = struct { }, .ptr_type => @panic("TODO"), .array_type => @panic("TODO"), - .vector_type => @panic("TODO"), - .optional_type => @panic("TODO"), + .vector_type => |vector_type| { + if (vector_type.len == 0) return Value.initTag(.empty_array); + if (vector_type.child.toType().onePossibleValue(mod)) |v| return v; + return null; + }, + .opt_type => @panic("TODO"), .error_union_type => @panic("TODO"), .simple_type => |t| switch (t) { .f16, @@ -4580,34 +3866,15 @@ pub const Type = struct { .error_set, .error_set_merged, .function, - .single_const_pointer_to_comptime_int, .array_sentinel, - .array_u8_sentinel_0, - .const_slice_u8, - .const_slice_u8_sentinel_0, - .const_slice, - .mut_slice, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .anyerror_void_error_union, .error_set_inferred, .@"opaque", - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, .anyframe_T, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .single_const_pointer, - .single_mut_pointer, .pointer, => return null, .optional => { - var buf: Payload.ElemType = undefined; - const child_ty = ty.optionalChild(&buf); + const child_ty = ty.optionalChild(mod); if (child_ty.isNoReturn()) { return Value.null; } else { @@ -4690,10 +3957,10 @@ pub const Type = struct { .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value), - .vector, .array, .array_u8 => { - if (ty.arrayLen() == 0) + .array => { + if (ty.arrayLen(mod) == 0) return Value.initTag(.empty_array); - if (ty.elemType().onePossibleValue(mod) != null) + if (ty.childType(mod).onePossibleValue(mod) != null) return Value.initTag(.the_only_possible_value); return null; }, @@ -4711,9 +3978,9 @@ pub const Type = struct { if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) { .int_type => false, .ptr_type => @panic("TODO"), - .array_type => @panic("TODO"), - .vector_type => @panic("TODO"), - .optional_type => @panic("TODO"), + .array_type => |array_type| return array_type.child.toType().comptimeOnly(mod), + .vector_type => |vector_type| return vector_type.child.toType().comptimeOnly(mod), + .opt_type => @panic("TODO"), .error_union_type => @panic("TODO"), .simple_type => |t| switch (t) { .f16, @@ -4772,12 +4039,6 @@ pub const Type = struct { }; return switch (ty.tag()) { - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, - .const_slice_u8, - .const_slice_u8_sentinel_0, - .anyerror_void_error_union, .empty_struct_literal, .empty_struct, .error_set, @@ -4785,35 +4046,21 @@ pub const Type = struct { .error_set_inferred, .error_set_merged, .@"opaque", - .array_u8, - .array_u8_sentinel_0, .enum_simple, => false, - .single_const_pointer_to_comptime_int, // These are function bodies, not function pointers. - .function, - => true, + .function => true, .inferred_alloc_mut => unreachable, .inferred_alloc_const => unreachable, .array, .array_sentinel, - .vector, - => return ty.childType().comptimeOnly(mod), + => return ty.childType(mod).comptimeOnly(mod), - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - => { - const child_ty = ty.childType(); + .pointer => { + const child_ty = ty.childType(mod); if (child_ty.zigTypeTag(mod) == .Fn) { return false; } else { @@ -4821,12 +4068,8 @@ pub const Type = struct { } }, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - => { - var buf: Type.Payload.ElemType = undefined; - return ty.optionalChild(&buf).comptimeOnly(mod); + .optional => { + return ty.optionalChild(mod).comptimeOnly(mod); }, .tuple, .anon_struct => { @@ -4882,6 +4125,10 @@ pub const Type = struct { }; } + pub fn isVector(ty: Type, mod: *const Module) bool { + return ty.zigTypeTag(mod) == .Vector; + } + pub fn isArrayOrVector(ty: Type, mod: *const Module) bool { return switch (ty.zigTypeTag(mod)) { .Array, .Vector => true, @@ -4892,9 +4139,9 @@ pub const Type = struct { pub fn isIndexable(ty: Type, mod: *const Module) bool { return switch (ty.zigTypeTag(mod)) { .Array, .Vector => true, - .Pointer => switch (ty.ptrSize()) { + .Pointer => switch (ty.ptrSize(mod)) { .Slice, .Many, .C => true, - .One => ty.elemType().zigTypeTag(mod) == .Array, + .One => ty.childType(mod).zigTypeTag(mod) == .Array, }, .Struct => ty.isTuple(), else => false, @@ -4904,10 +4151,10 @@ pub const Type = struct { pub fn indexableHasLen(ty: Type, mod: *const Module) bool { return switch (ty.zigTypeTag(mod)) { .Array, .Vector => true, - .Pointer => switch (ty.ptrSize()) { + .Pointer => switch (ty.ptrSize(mod)) { .Many, .C => false, .Slice => true, - .One => ty.elemType().zigTypeTag(mod) == .Array, + .One => ty.childType(mod).zigTypeTag(mod) == .Array, }, .Struct => ty.isTuple(), else => false, @@ -5527,14 +4774,6 @@ pub const Type = struct { /// with different enum tags, because the the former requires more payload data than the latter. /// See `zigTypeTag` for the function that corresponds to `std.builtin.TypeId`. pub const Tag = enum(usize) { - // The first section of this enum are tags that require no payload. - manyptr_u8, - manyptr_const_u8, - manyptr_const_u8_sentinel_0, - single_const_pointer_to_comptime_int, - const_slice_u8, - const_slice_u8_sentinel_0, - anyerror_void_error_union, /// Same as `empty_struct` except it has an empty namespace. empty_struct_literal, /// This is a special value that tracks a set of types that have been stored @@ -5545,28 +4784,15 @@ pub const Type = struct { inferred_alloc_const, // See last_no_payload_tag below. // After this, the tag requires a payload. - array_u8, - array_u8_sentinel_0, array, array_sentinel, - vector, /// Possible Value tags for this: @"struct" tuple, /// Possible Value tags for this: @"struct" anon_struct, pointer, - single_const_pointer, - single_mut_pointer, - many_const_pointer, - many_mut_pointer, - c_const_pointer, - c_mut_pointer, - const_slice, - mut_slice, function, optional, - optional_single_mut_pointer, - optional_single_const_pointer, error_union, anyframe_T, error_set, @@ -5590,33 +4816,12 @@ pub const Type = struct { pub fn Type(comptime t: Tag) type { return switch (t) { - .single_const_pointer_to_comptime_int, - .anyerror_void_error_union, - .const_slice_u8, - .const_slice_u8_sentinel_0, .inferred_alloc_const, .inferred_alloc_mut, .empty_struct_literal, - .manyptr_u8, - .manyptr_const_u8, - .manyptr_const_u8_sentinel_0, => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"), - .array_u8, - .array_u8_sentinel_0, - => Payload.Len, - - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, .anyframe_T, => Payload.ElemType, @@ -5624,7 +4829,7 @@ pub const Type = struct { .error_set_inferred => Payload.ErrorSetInferred, .error_set_merged => Payload.ErrorSetMerged, - .array, .vector => Payload.Array, + .array => Payload.Array, .array_sentinel => Payload.ArraySentinel, .pointer => Payload.Pointer, .function => Payload.Function, @@ -5847,15 +5052,28 @@ pub const Type = struct { @"volatile": bool = false, size: std.builtin.Type.Pointer.Size = .One, - pub const VectorIndex = enum(u32) { - none = std.math.maxInt(u32), - runtime = std.math.maxInt(u32) - 1, - _, - }; + pub const VectorIndex = InternPool.Key.PtrType.VectorIndex; + pub fn alignment(data: Data, mod: *const Module) u32 { if (data.@"align" != 0) return data.@"align"; return abiAlignment(data.pointee_type, mod); } + + pub fn fromKey(p: InternPool.Key.PtrType) Data { + return .{ + .pointee_type = p.elem_type.toType(), + .sentinel = if (p.sentinel != .none) p.sentinel.toValue() else null, + .@"align" = p.alignment, + .@"addrspace" = p.address_space, + .bit_offset = p.bit_offset, + .host_size = p.host_size, + .vector_index = p.vector_index, + .@"allowzero" = p.is_allowzero, + .mutable = !p.is_const, + .@"volatile" = p.is_volatile, + .size = p.size, + }; + } }; }; @@ -5986,6 +5204,17 @@ pub const Type = struct { pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type, .legacy = undefined }; pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type, .legacy = undefined }; + pub const const_slice_u8: Type = .{ .ip_index = .const_slice_u8_type, .legacy = undefined }; + pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type, .legacy = undefined }; + pub const single_const_pointer_to_comptime_int: Type = .{ + .ip_index = .single_const_pointer_to_comptime_int_type, + .legacy = undefined, + }; + pub const const_slice_u8_sentinel_0: Type = .{ + .ip_index = .const_slice_u8_sentinel_0_type, + .legacy = undefined, + }; + pub const generic_poison: Type = .{ .ip_index = .generic_poison_type, .legacy = undefined }; pub const err_int = Type.u16; @@ -6019,50 +5248,6 @@ pub const Type = struct { } } - if (d.@"align" == 0 and d.@"addrspace" == .generic and - d.bit_offset == 0 and d.host_size == 0 and d.vector_index == .none and - !d.@"allowzero" and !d.@"volatile") - { - if (d.sentinel) |sent| { - if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) { - switch (d.size) { - .Slice => { - if (sent.compareAllWithZero(.eq, mod)) { - return Type.initTag(.const_slice_u8_sentinel_0); - } - }, - .Many => { - if (sent.compareAllWithZero(.eq, mod)) { - return Type.initTag(.manyptr_const_u8_sentinel_0); - } - }, - else => {}, - } - } - } else if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) { - switch (d.size) { - .Slice => return Type.initTag(.const_slice_u8), - .Many => return Type.initTag(.manyptr_const_u8), - else => {}, - } - } else { - const T = Type.Tag; - const type_payload = try arena.create(Type.Payload.ElemType); - type_payload.* = .{ - .base = .{ - .tag = switch (d.size) { - .One => if (d.mutable) T.single_mut_pointer else T.single_const_pointer, - .Many => if (d.mutable) T.many_mut_pointer else T.many_const_pointer, - .C => if (d.mutable) T.c_mut_pointer else T.c_const_pointer, - .Slice => if (d.mutable) T.mut_slice else T.const_slice, - }, - }, - .data = d.pointee_type, - }; - return Type.initPayload(&type_payload.base); - } - } - return Type.Tag.pointer.create(arena, d); } @@ -6073,13 +5258,21 @@ pub const Type = struct { elem_type: Type, mod: *Module, ) Allocator.Error!Type { - if (elem_type.eql(Type.u8, mod)) { - if (sent) |some| { - if (some.eql(Value.zero, elem_type, mod)) { - return Tag.array_u8_sentinel_0.create(arena, len); + if (elem_type.ip_index != .none) { + if (sent) |s| { + if (s.ip_index != .none) { + return mod.arrayType(.{ + .len = len, + .child = elem_type.ip_index, + .sentinel = s.ip_index, + }); } } else { - return Tag.array_u8.create(arena, len); + return mod.arrayType(.{ + .len = len, + .child = elem_type.ip_index, + .sentinel = .none, + }); } } @@ -6097,24 +5290,11 @@ pub const Type = struct { }); } - pub fn vector(arena: Allocator, len: u64, elem_type: Type) Allocator.Error!Type { - return Tag.vector.create(arena, .{ - .len = len, - .elem_type = elem_type, - }); - } - - pub fn optional(arena: Allocator, child_type: Type) Allocator.Error!Type { - switch (child_type.tag()) { - .single_const_pointer => return Type.Tag.optional_single_const_pointer.create( - arena, - child_type.elemType(), - ), - .single_mut_pointer => return Type.Tag.optional_single_mut_pointer.create( - arena, - child_type.elemType(), - ), - else => return Type.Tag.optional.create(arena, child_type), + pub fn optional(arena: Allocator, child_type: Type, mod: *Module) Allocator.Error!Type { + if (child_type.ip_index != .none) { + return mod.optionalType(child_type.ip_index); + } else { + return Type.Tag.optional.create(arena, child_type); } } @@ -6125,12 +5305,6 @@ pub const Type = struct { mod: *Module, ) Allocator.Error!Type { assert(error_set.zigTypeTag(mod) == .ErrorSet); - if (error_set.eql(Type.anyerror, mod) and - payload.eql(Type.void, mod)) - { - return Type.initTag(.anyerror_void_error_union); - } - return Type.Tag.error_union.create(arena, .{ .error_set = error_set, .payload = payload, |
