aboutsummaryrefslogtreecommitdiff
path: root/src/type.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-05-04 20:30:25 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-06-10 20:42:27 -0700
commit5e636643d2a36c777a607b65cfd1abbb1822ad1e (patch)
tree500ec74bd5cc60bb8a4db95ab5f5e90fcfb222aa /src/type.zig
parent9d422bff18dbb92d3a6b8705c3dae7404a34bba6 (diff)
downloadzig-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.zig1770
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,