diff --git a/src/Compilation.zig b/src/Compilation.zig index 8a0a6ee58d..11c8303fac 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -825,9 +825,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { const root_scope = rs: { if (mem.endsWith(u8, root_pkg.root_src_path, ".zig")) { - const struct_payload = try gpa.create(Type.Payload.EmptyStruct); const root_scope = try gpa.create(Module.Scope.File); - struct_payload.* = .{ .scope = &root_scope.root_container }; + const struct_ty = try Type.Tag.empty_struct.create( + gpa, + &root_scope.root_container, + ); root_scope.* = .{ // TODO this is duped so it can be freed in Container.deinit .sub_file_path = try gpa.dupe(u8, root_pkg.root_src_path), @@ -838,7 +840,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .root_container = .{ .file_scope = root_scope, .decls = .{}, - .ty = Type.initPayload(&struct_payload.base), + .ty = struct_ty, }, }; break :rs &root_scope.base; diff --git a/src/Module.zig b/src/Module.zig index 089bc51893..3e937fe49b 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -562,7 +562,7 @@ pub const Scope = struct { pub fn deinit(self: *Container, gpa: *Allocator) void { self.decls.deinit(gpa); // TODO either Container of File should have an arena for sub_file_path and ty - gpa.destroy(self.ty.cast(Type.Payload.EmptyStruct).?); + gpa.destroy(self.ty.castTag(.empty_struct).?); gpa.free(self.file_scope.sub_file_path); self.* = undefined; } @@ -2528,12 +2528,11 @@ pub fn analyzeImport(self: *Module, scope: *Scope, src: usize, target_string: [] } // TODO Scope.Container arena for ty and sub_file_path - const struct_payload = try self.gpa.create(Type.Payload.EmptyStruct); - errdefer self.gpa.destroy(struct_payload); const file_scope = try self.gpa.create(Scope.File); errdefer self.gpa.destroy(file_scope); + const struct_ty = try Type.Tag.empty_struct.create(self.gpa, &file_scope.root_container); + errdefer self.gpa.destroy(struct_ty.castTag(.empty_struct).?); - struct_payload.* = .{ .scope = &file_scope.root_container }; file_scope.* = .{ .sub_file_path = resolved_path, .source = .{ .unloaded = {} }, @@ -2543,7 +2542,7 @@ pub fn analyzeImport(self: *Module, scope: *Scope, src: usize, target_string: [] .root_container = .{ .file_scope = file_scope, .decls = .{}, - .ty = Type.initPayload(&struct_payload.base), + .ty = struct_ty, }, }; self.analyzeContainer(&file_scope.root_container) catch |err| switch (err) { @@ -2564,7 +2563,7 @@ pub fn cmpNumeric( lhs: *Inst, rhs: *Inst, op: std.math.CompareOperator, -) !*Inst { +) InnerError!*Inst { assert(lhs.ty.isNumeric()); assert(rhs.ty.isNumeric()); @@ -2738,15 +2737,14 @@ fn wrapOptional(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*In } fn makeIntType(self: *Module, scope: *Scope, signed: bool, bits: u16) !Type { - if (signed) { - const int_payload = try scope.arena().create(Type.Payload.IntSigned); - int_payload.* = .{ .bits = bits }; - return Type.initPayload(&int_payload.base); - } else { - const int_payload = try scope.arena().create(Type.Payload.IntUnsigned); - int_payload.* = .{ .bits = bits }; - return Type.initPayload(&int_payload.base); - } + const int_payload = try scope.arena().create(Type.Payload.Bits); + int_payload.* = .{ + .base = .{ + .tag = if (signed) .int_signed else .int_unsigned, + }, + .data = bits, + }; + return Type.initPayload(&int_payload.base); } pub fn resolvePeerTypes(self: *Module, scope: *Scope, instructions: []*Inst) !Type { @@ -2829,7 +2827,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst // T to ?T if (dest_type.zigTypeTag() == .Optional) { - var buf: Type.Payload.PointerSimple = undefined; + var buf: Type.Payload.ElemType = undefined; const child_type = dest_type.optionalChild(&buf); if (child_type.eql(inst.ty)) { return self.wrapOptional(scope, dest_type, inst); @@ -3225,7 +3223,7 @@ pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mu // TODO stage1 type inference bug const T = Type.Tag; - const type_payload = try scope.arena().create(Type.Payload.PointerSimple); + const type_payload = try scope.arena().create(Type.Payload.ElemType); type_payload.* = .{ .base = .{ .tag = switch (size) { @@ -3235,7 +3233,7 @@ pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mu .Slice => if (mutable) T.mut_slice else T.const_slice, }, }, - .pointee_type = elem_ty, + .data = elem_ty, }; return Type.initPayload(&type_payload.base); } @@ -3257,8 +3255,7 @@ pub fn ptrType( assert(host_size == 0 or bit_offset < host_size * 8); // TODO check if type can be represented by simplePtrType - const type_payload = try scope.arena().create(Type.Payload.Pointer); - type_payload.* = .{ + return Type.Tag.pointer.create(scope.arena(), .{ .pointee_type = elem_ty, .sentinel = sentinel, .@"align" = @"align", @@ -3268,95 +3265,73 @@ pub fn ptrType( .mutable = mutable, .@"volatile" = @"volatile", .size = size, - }; - return Type.initPayload(&type_payload.base); -} - -pub fn optionalType(self: *Module, scope: *Scope, child_type: Type) Allocator.Error!Type { - return Type.initPayload(switch (child_type.tag()) { - .single_const_pointer => blk: { - const payload = try scope.arena().create(Type.Payload.PointerSimple); - payload.* = .{ - .base = .{ .tag = .optional_single_const_pointer }, - .pointee_type = child_type.elemType(), - }; - break :blk &payload.base; - }, - .single_mut_pointer => blk: { - const payload = try scope.arena().create(Type.Payload.PointerSimple); - payload.* = .{ - .base = .{ .tag = .optional_single_mut_pointer }, - .pointee_type = child_type.elemType(), - }; - break :blk &payload.base; - }, - else => blk: { - const payload = try scope.arena().create(Type.Payload.Optional); - payload.* = .{ - .child_type = child_type, - }; - break :blk &payload.base; - }, }); } -pub fn arrayType(self: *Module, scope: *Scope, len: u64, sentinel: ?Value, elem_type: Type) Allocator.Error!Type { +pub fn optionalType(self: *Module, scope: *Scope, child_type: Type) Allocator.Error!Type { + switch (child_type.tag()) { + .single_const_pointer => return Type.Tag.optional_single_const_pointer.create( + scope.arena(), + child_type.elemType(), + ), + .single_mut_pointer => return Type.Tag.optional_single_mut_pointer.create( + scope.arena(), + child_type.elemType(), + ), + else => return Type.Tag.optional.create(scope.arena(), child_type), + } +} + +pub fn arrayType( + self: *Module, + scope: *Scope, + len: u64, + sentinel: ?Value, + elem_type: Type, +) Allocator.Error!Type { if (elem_type.eql(Type.initTag(.u8))) { if (sentinel) |some| { if (some.eql(Value.initTag(.zero))) { - const payload = try scope.arena().create(Type.Payload.Array_u8_Sentinel0); - payload.* = .{ - .len = len, - }; - return Type.initPayload(&payload.base); + return Type.Tag.array_u8_sentinel_0.create(scope.arena(), len); } } else { - const payload = try scope.arena().create(Type.Payload.Array_u8); - payload.* = .{ - .len = len, - }; - return Type.initPayload(&payload.base); + return Type.Tag.array_u8.create(scope.arena(), len); } } if (sentinel) |some| { - const payload = try scope.arena().create(Type.Payload.ArraySentinel); - payload.* = .{ + return Type.Tag.array_sentinel.create(scope.arena(), .{ .len = len, .sentinel = some, .elem_type = elem_type, - }; - return Type.initPayload(&payload.base); + }); } - const payload = try scope.arena().create(Type.Payload.Array); - payload.* = .{ + return Type.Tag.array.create(scope.arena(), .{ .len = len, .elem_type = elem_type, - }; - return Type.initPayload(&payload.base); + }); } -pub fn errorUnionType(self: *Module, scope: *Scope, error_set: Type, payload: Type) Allocator.Error!Type { +pub fn errorUnionType( + self: *Module, + scope: *Scope, + error_set: Type, + payload: Type, +) Allocator.Error!Type { assert(error_set.zigTypeTag() == .ErrorSet); if (error_set.eql(Type.initTag(.anyerror)) and payload.eql(Type.initTag(.void))) { return Type.initTag(.anyerror_void_error_union); } - const result = try scope.arena().create(Type.Payload.ErrorUnion); - result.* = .{ + return Type.Tag.error_union.create(scope.arena(), .{ .error_set = error_set, .payload = payload, - }; - return Type.initPayload(&result.base); + }); } pub fn anyframeType(self: *Module, scope: *Scope, return_type: Type) Allocator.Error!Type { - const result = try scope.arena().create(Type.Payload.AnyFrame); - result.* = .{ - .return_type = return_type, - }; - return Type.initPayload(&result.base); + return Type.Tag.anyframe_T.create(scope.arena(), return_type); } pub fn dumpInst(self: *Module, scope: *Scope, inst: *Inst) void { diff --git a/src/astgen.zig b/src/astgen.zig index 672fe343e2..1fc8a0d19e 100644 --- a/src/astgen.zig +++ b/src/astgen.zig @@ -2723,7 +2723,7 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr return mod.fail(scope, result.src, "TODO implement rlWrap .bitcasted_ptr", .{}); }, .inferred_ptr => |alloc| { - return mod.fail(scope, result.src, "TODO implement rlWrap .inferred_ptr", .{}); + return addZIRBinOp(mod, scope, result.src, .store, &alloc.base, result); }, .block_ptr => |block_ptr| { return mod.fail(scope, result.src, "TODO implement rlWrap .block_ptr", .{}); diff --git a/src/codegen.zig b/src/codegen.zig index 01deb13c0e..d98a87a440 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -3262,7 +3262,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { if (typed_value.val.isNull()) return MCValue{ .immediate = 0 }; - var buf: Type.Payload.PointerSimple = undefined; + var buf: Type.Payload.ElemType = undefined; return self.genTypedValue(src, .{ .ty = typed_value.ty.optionalChild(&buf), .val = typed_value.val, diff --git a/src/type.zig b/src/type.zig index f08408738a..ce237f89c7 100644 --- a/src/type.zig +++ b/src/type.zig @@ -112,18 +112,39 @@ pub const Type = extern union { } } + /// Prefer `castTag` to this. pub fn cast(self: Type, comptime T: type) ?*T { + if (@hasField(T, "base_tag")) { + return base.castTag(T.base_tag); + } + if (self.tag_if_small_enough < Tag.no_payload_count) { + return null; + } + inline for (@typeInfo(Tag).Enum.fields) |field| { + if (field.value < Tag.no_payload_count) + continue; + const t = @intToEnum(Tag, field.value); + if (self.ptr_otherwise.tag == t) { + if (T == t.Type()) { + return @fieldParentPtr(T, "base", self.ptr_otherwise); + } + return null; + } + } + unreachable; + } + + pub fn castTag(self: Type, comptime t: Tag) ?*t.Type() { if (self.tag_if_small_enough < Tag.no_payload_count) return null; - const expected_tag = std.meta.fieldInfo(T, "base").default_value.?.tag; - if (self.ptr_otherwise.tag != expected_tag) - return null; + if (self.ptr_otherwise.tag == t) + return @fieldParentPtr(t.Type(), "base", self.ptr_otherwise); - return @fieldParentPtr(T, "base", self.ptr_otherwise); + return null; } - pub fn castPointer(self: Type) ?*Payload.PointerSimple { + pub fn castPointer(self: Type) ?*Payload.ElemType { return switch (self.tag()) { .single_const_pointer, .single_mut_pointer, @@ -135,7 +156,8 @@ pub const Type = extern union { .mut_slice, .optional_single_const_pointer, .optional_single_mut_pointer, - => @fieldParentPtr(Payload.PointerSimple, "base", self.ptr_otherwise), + => self.cast(Payload.ElemType), + else => null, }; } @@ -165,7 +187,7 @@ pub const Type = extern union { // Hot path for common case: if (a.castPointer()) |a_payload| { if (b.castPointer()) |b_payload| { - return a.tag() == b.tag() and eql(a_payload.pointee_type, b_payload.pointee_type); + return a.tag() == b.tag() and eql(a_payload.data, b_payload.data); } } const is_slice_a = isSlice(a); @@ -230,8 +252,8 @@ pub const Type = extern union { return true; }, .Optional => { - var buf_a: Payload.PointerSimple = undefined; - var buf_b: Payload.PointerSimple = undefined; + var buf_a: Payload.ElemType = undefined; + var buf_b: Payload.ElemType = undefined; return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b)); }, .Float, @@ -294,7 +316,7 @@ pub const Type = extern union { } }, .Optional => { - var buf: Payload.PointerSimple = undefined; + var buf: Payload.ElemType = undefined; std.hash.autoHash(&hasher, self.optionalChild(&buf).hash()); }, .Float, @@ -364,47 +386,10 @@ pub const Type = extern union { .@"anyframe", => unreachable, - .array_u8_sentinel_0 => return self.copyPayloadShallow(allocator, Payload.Array_u8_Sentinel0), - .array_u8 => return self.copyPayloadShallow(allocator, Payload.Array_u8), - .array => { - const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise); - const new_payload = try allocator.create(Payload.Array); - new_payload.* = .{ - .base = payload.base, - .len = payload.len, - .elem_type = try payload.elem_type.copy(allocator), - }; - return Type{ .ptr_otherwise = &new_payload.base }; - }, - .array_sentinel => { - const payload = @fieldParentPtr(Payload.ArraySentinel, "base", self.ptr_otherwise); - const new_payload = try allocator.create(Payload.ArraySentinel); - new_payload.* = .{ - .base = payload.base, - .len = payload.len, - .sentinel = try payload.sentinel.copy(allocator), - .elem_type = try payload.elem_type.copy(allocator), - }; - return Type{ .ptr_otherwise = &new_payload.base }; - }, - .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned), - .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned), - .function => { - const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise); - const new_payload = try allocator.create(Payload.Function); - const param_types = try allocator.alloc(Type, payload.param_types.len); - for (payload.param_types) |param_type, i| { - param_types[i] = try param_type.copy(allocator); - } - new_payload.* = .{ - .base = payload.base, - .return_type = try payload.return_type.copy(allocator), - .param_types = param_types, - .cc = payload.cc, - }; - return Type{ .ptr_otherwise = &new_payload.base }; - }, - .optional => return self.copyPayloadSingleField(allocator, Payload.Optional, "child_type"), + .array_u8, + .array_u8_sentinel_0, + => return self.copyPayloadShallow(allocator, Payload.Len), + .single_const_pointer, .single_mut_pointer, .many_const_pointer, @@ -413,19 +398,52 @@ pub const Type = extern union { .c_mut_pointer, .const_slice, .mut_slice, + .optional, .optional_single_mut_pointer, .optional_single_const_pointer, - => return self.copyPayloadSingleField(allocator, Payload.PointerSimple, "pointee_type"), - .anyframe_T => return self.copyPayloadSingleField(allocator, Payload.AnyFrame, "return_type"), + .anyframe_T, + => return self.copyPayloadShallow(allocator, Payload.ElemType), + .int_signed, + .int_unsigned, + => return self.copyPayloadShallow(allocator, Payload.Bits), + + .array => { + const payload = self.castTag(.array).?.data; + return Tag.array.create(allocator, .{ + .len = payload.len, + .elem_type = try payload.elem_type.copy(allocator), + }); + }, + .array_sentinel => { + const payload = self.castTag(.array_sentinel).?.data; + return Tag.array_sentinel.create(allocator, .{ + .len = payload.len, + .sentinel = try payload.sentinel.copy(allocator), + .elem_type = try payload.elem_type.copy(allocator), + }); + }, + .function => { + const payload = self.castTag(.function).?.data; + const param_types = try allocator.alloc(Type, payload.param_types.len); + for (payload.param_types) |param_type, i| { + param_types[i] = try param_type.copy(allocator); + } + return Tag.function.create(allocator, .{ + .return_type = try payload.return_type.copy(allocator), + .param_types = param_types, + .cc = payload.cc, + }); + }, .pointer => { - const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise); - const new_payload = try allocator.create(Payload.Pointer); - new_payload.* = .{ - .base = payload.base, - + const payload = self.castTag(.pointer).?.data; + const sent: ?Value = if (payload.sentinel) |some| + try some.copy(allocator) + else + null; + return Tag.pointer.create(allocator, .{ .pointee_type = try payload.pointee_type.copy(allocator), - .sentinel = if (payload.sentinel) |some| try some.copy(allocator) else null, + .sentinel = sent, .@"align" = payload.@"align", .bit_offset = payload.bit_offset, .host_size = payload.host_size, @@ -433,41 +451,28 @@ pub const Type = extern union { .mutable = payload.mutable, .@"volatile" = payload.@"volatile", .size = payload.size, - }; - return Type{ .ptr_otherwise = &new_payload.base }; + }); }, .error_union => { - const payload = @fieldParentPtr(Payload.ErrorUnion, "base", self.ptr_otherwise); - const new_payload = try allocator.create(Payload.ErrorUnion); - new_payload.* = .{ - .base = payload.base, - + const payload = self.castTag(.error_union).?.data; + return Tag.error_union.create(allocator, .{ .error_set = try payload.error_set.copy(allocator), .payload = try payload.payload.copy(allocator), - }; - return Type{ .ptr_otherwise = &new_payload.base }; + }); }, - .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), - .error_set_single => return self.copyPayloadShallow(allocator, Payload.ErrorSetSingle), - .empty_struct => return self.copyPayloadShallow(allocator, Payload.EmptyStruct), + .error_set => return self.copyPayloadShallow(allocator, Payload.Decl), + .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name), + .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope), } } fn copyPayloadShallow(self: Type, allocator: *Allocator, comptime T: type) error{OutOfMemory}!Type { - const payload = @fieldParentPtr(T, "base", self.ptr_otherwise); + const payload = self.cast(T).?; const new_payload = try allocator.create(T); new_payload.* = payload.*; return Type{ .ptr_otherwise = &new_payload.base }; } - fn copyPayloadSingleField(self: Type, allocator: *Allocator, comptime T: type, comptime field_name: []const u8) error{OutOfMemory}!Type { - const payload = @fieldParentPtr(T, "base", self.ptr_otherwise); - const new_payload = try allocator.create(T); - new_payload.base = payload.base; - @field(new_payload, field_name) = try @field(payload, field_name).copy(allocator); - return Type{ .ptr_otherwise = &new_payload.base }; - } - pub fn format( self: Type, comptime fmt: []const u8, @@ -527,7 +532,7 @@ pub const Type = extern union { .fn_ccc_void_no_args => return out_stream.writeAll("fn() callconv(.C) void"), .single_const_pointer_to_comptime_int => return out_stream.writeAll("*const comptime_int"), .function => { - const payload = @fieldParentPtr(Payload.Function, "base", ty.ptr_otherwise); + const payload = ty.castTag(.function).?.data; try out_stream.writeAll("fn("); for (payload.param_types) |param_type, i| { if (i != 0) try out_stream.writeAll(", "); @@ -539,108 +544,108 @@ pub const Type = extern union { }, .anyframe_T => { - const payload = @fieldParentPtr(Payload.AnyFrame, "base", ty.ptr_otherwise); + const return_type = ty.castTag(.anyframe_T).?.data; try out_stream.print("anyframe->", .{}); - ty = payload.return_type; + ty = return_type; continue; }, .array_u8 => { - const payload = @fieldParentPtr(Payload.Array_u8, "base", ty.ptr_otherwise); - return out_stream.print("[{}]u8", .{payload.len}); + const len = ty.castTag(.array_u8).?.data; + return out_stream.print("[{}]u8", .{len}); }, .array_u8_sentinel_0 => { - const payload = @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", ty.ptr_otherwise); - return out_stream.print("[{}:0]u8", .{payload.len}); + const len = ty.castTag(.array_u8_sentinel_0).?.data; + return out_stream.print("[{}:0]u8", .{len}); }, .array => { - const payload = @fieldParentPtr(Payload.Array, "base", ty.ptr_otherwise); + const payload = ty.castTag(.array).?.data; try out_stream.print("[{}]", .{payload.len}); ty = payload.elem_type; continue; }, .array_sentinel => { - const payload = @fieldParentPtr(Payload.ArraySentinel, "base", ty.ptr_otherwise); + const payload = ty.castTag(.array_sentinel).?.data; try out_stream.print("[{}:{}]", .{ payload.len, payload.sentinel }); ty = payload.elem_type; continue; }, .single_const_pointer => { - const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); + const pointee_type = ty.castTag(.single_const_pointer).?.data; try out_stream.writeAll("*const "); - ty = payload.pointee_type; + ty = pointee_type; continue; }, .single_mut_pointer => { - const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); + const pointee_type = ty.castTag(.single_mut_pointer).?.data; try out_stream.writeAll("*"); - ty = payload.pointee_type; + ty = pointee_type; continue; }, .many_const_pointer => { - const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); + const pointee_type = ty.castTag(.many_const_pointer).?.data; try out_stream.writeAll("[*]const "); - ty = payload.pointee_type; + ty = pointee_type; continue; }, .many_mut_pointer => { - const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); + const pointee_type = ty.castTag(.many_mut_pointer).?.data; try out_stream.writeAll("[*]"); - ty = payload.pointee_type; + ty = pointee_type; continue; }, .c_const_pointer => { - const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); + const pointee_type = ty.castTag(.c_const_pointer).?.data; try out_stream.writeAll("[*c]const "); - ty = payload.pointee_type; + ty = pointee_type; continue; }, .c_mut_pointer => { - const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); + const pointee_type = ty.castTag(.c_mut_pointer).?.data; try out_stream.writeAll("[*c]"); - ty = payload.pointee_type; + ty = pointee_type; continue; }, .const_slice => { - const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); + const pointee_type = ty.castTag(.const_slice).?.data; try out_stream.writeAll("[]const "); - ty = payload.pointee_type; + ty = pointee_type; continue; }, .mut_slice => { - const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); + const pointee_type = ty.castTag(.mut_slice).?.data; try out_stream.writeAll("[]"); - ty = payload.pointee_type; + ty = pointee_type; continue; }, .int_signed => { - const payload = @fieldParentPtr(Payload.IntSigned, "base", ty.ptr_otherwise); - return out_stream.print("i{}", .{payload.bits}); + const bits = ty.castTag(.int_signed).?.data; + return out_stream.print("i{d}", .{bits}); }, .int_unsigned => { - const payload = @fieldParentPtr(Payload.IntUnsigned, "base", ty.ptr_otherwise); - return out_stream.print("u{}", .{payload.bits}); + const bits = ty.castTag(.int_unsigned).?.data; + return out_stream.print("u{d}", .{bits}); }, .optional => { - const payload = @fieldParentPtr(Payload.Optional, "base", ty.ptr_otherwise); + const child_type = ty.castTag(.optional).?.data; try out_stream.writeByte('?'); - ty = payload.child_type; + ty = child_type; continue; }, .optional_single_const_pointer => { - const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); + const pointee_type = ty.castTag(.optional_single_const_pointer).?.data; try out_stream.writeAll("?*const "); - ty = payload.pointee_type; + ty = pointee_type; continue; }, .optional_single_mut_pointer => { - const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); + const pointee_type = ty.castTag(.optional_single_mut_pointer).?.data; try out_stream.writeAll("?*"); - ty = payload.pointee_type; + ty = pointee_type; continue; }, .pointer => { - const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise); + const payload = ty.castTag(.pointer).?.data; if (payload.sentinel) |some| switch (payload.size) { .One, .C => unreachable, .Many => try out_stream.print("[*:{}]", .{some}), @@ -652,10 +657,10 @@ pub const Type = extern union { .Slice => try out_stream.writeAll("[]"), } if (payload.@"align" != 0) { - try out_stream.print("align({}", .{payload.@"align"}); + try out_stream.print("align({d}", .{payload.@"align"}); if (payload.bit_offset != 0) { - try out_stream.print(":{}:{}", .{ payload.bit_offset, payload.host_size }); + try out_stream.print(":{d}:{d}", .{ payload.bit_offset, payload.host_size }); } try out_stream.writeAll(") "); } @@ -667,19 +672,19 @@ pub const Type = extern union { continue; }, .error_union => { - const payload = @fieldParentPtr(Payload.ErrorUnion, "base", ty.ptr_otherwise); + const payload = ty.castTag(.error_union).?.data; try payload.error_set.format("", .{}, out_stream); try out_stream.writeAll("!"); ty = payload.payload; continue; }, .error_set => { - const payload = @fieldParentPtr(Payload.ErrorSet, "base", ty.ptr_otherwise); - return out_stream.writeAll(std.mem.spanZ(payload.decl.name)); + const decl = ty.castTag(.error_set).?.data; + return out_stream.writeAll(std.mem.spanZ(decl.name)); }, .error_set_single => { - const payload = @fieldParentPtr(Payload.ErrorSetSingle, "base", ty.ptr_otherwise); - return out_stream.print("error{{{}}}", .{payload.name}); + const name = ty.castTag(.error_set_single).?.data; + return out_stream.print("error{{{s}}}", .{name}); }, } unreachable; @@ -784,11 +789,10 @@ pub const Type = extern union { .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0, .array_u8 => self.arrayLen() != 0, .array_sentinel, .single_const_pointer, .single_mut_pointer, .many_const_pointer, .many_mut_pointer, .c_const_pointer, .c_mut_pointer, .const_slice, .mut_slice, .pointer => self.elemType().hasCodeGenBits(), - .int_signed => self.cast(Payload.IntSigned).?.bits != 0, - .int_unsigned => self.cast(Payload.IntUnsigned).?.bits != 0, + .int_signed, .int_unsigned => self.cast(Payload.Bits).?.data != 0, .error_union => { - const payload = self.cast(Payload.ErrorUnion).?; + const payload = self.castTag(.error_union).?.data; return payload.error_set.hasCodeGenBits() or payload.payload.hasCodeGenBits(); }, @@ -855,7 +859,7 @@ pub const Type = extern union { => return @divExact(target.cpu.arch.ptrBitWidth(), 8), .pointer => { - const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise); + const payload = self.castTag(.pointer).?.data; if (payload.@"align" != 0) return payload.@"align"; return @divExact(target.cpu.arch.ptrBitWidth(), 8); @@ -885,18 +889,12 @@ pub const Type = extern union { .array, .array_sentinel => return self.elemType().abiAlignment(target), .int_signed, .int_unsigned => { - const bits: u16 = if (self.cast(Payload.IntSigned)) |pl| - pl.bits - else if (self.cast(Payload.IntUnsigned)) |pl| - pl.bits - else - unreachable; - + const bits: u16 = self.cast(Payload.Bits).?.data; return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8); }, .optional => { - var buf: Payload.PointerSimple = undefined; + var buf: Payload.ElemType = undefined; const child_type = self.optionalChild(&buf); if (!child_type.hasCodeGenBits()) return 1; @@ -907,7 +905,7 @@ pub const Type = extern union { }, .error_union => { - const payload = self.cast(Payload.ErrorUnion).?; + const payload = self.castTag(.error_union).?.data; if (!payload.error_set.hasCodeGenBits()) { return payload.payload.abiAlignment(target); } else if (!payload.payload.hasCodeGenBits()) { @@ -955,16 +953,19 @@ pub const Type = extern union { .bool, => return 1, - .array_u8 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len, - .array_u8_sentinel_0 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len + 1, + .array_u8 => self.castTag(.array_u8).?.data, + .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data + 1, .array => { - const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise); + const payload = self.castTag(.array).?.data; const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target)); return payload.len * elem_size; }, .array_sentinel => { - const payload = @fieldParentPtr(Payload.ArraySentinel, "base", self.ptr_otherwise); - const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target)); + const payload = self.castTag(.array_sentinel).?.data; + const elem_size = std.math.max( + payload.elem_type.abiAlignment(target), + payload.elem_type.abiSize(target), + ); return (payload.len + 1) * elem_size; }, .i16, .u16 => return 2, @@ -1022,18 +1023,12 @@ pub const Type = extern union { => return 2, // TODO revisit this when we have the concept of the error tag type .int_signed, .int_unsigned => { - const bits: u16 = if (self.cast(Payload.IntSigned)) |pl| - pl.bits - else if (self.cast(Payload.IntUnsigned)) |pl| - pl.bits - else - unreachable; - + const bits: u16 = self.cast(Payload.Bits).?.data; return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8); }, .optional => { - var buf: Payload.PointerSimple = undefined; + var buf: Payload.ElemType = undefined; const child_type = self.optionalChild(&buf); if (!child_type.hasCodeGenBits()) return 1; @@ -1048,7 +1043,7 @@ pub const Type = extern union { }, .error_union => { - const payload = self.cast(Payload.ErrorUnion).?; + const payload = self.castTag(.error_union).?.data; if (!payload.error_set.hasCodeGenBits() and !payload.payload.hasCodeGenBits()) { return 0; } else if (!payload.error_set.hasCodeGenBits()) { @@ -1132,7 +1127,7 @@ pub const Type = extern union { .single_const_pointer_to_comptime_int, => true, - .pointer => self.cast(Payload.Pointer).?.size == .One, + .pointer => self.castTag(.pointer).?.data.size == .One, }; } @@ -1214,7 +1209,7 @@ pub const Type = extern union { .single_const_pointer_to_comptime_int, => .One, - .pointer => self.cast(Payload.Pointer).?.size, + .pointer => self.castTag(.pointer).?.data.size, }; } @@ -1289,7 +1284,7 @@ pub const Type = extern union { .const_slice_u8, => true, - .pointer => self.cast(Payload.Pointer).?.size == .Slice, + .pointer => self.castTag(.pointer).?.data.size == .Slice, }; } @@ -1364,7 +1359,7 @@ pub const Type = extern union { .const_slice, => true, - .pointer => !self.cast(Payload.Pointer).?.mutable, + .pointer => !self.castTag(.pointer).?.data.mutable, }; } @@ -1438,7 +1433,7 @@ pub const Type = extern union { => false, .pointer => { - const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise); + const payload = self.castTag(.pointer).?.data; return payload.@"volatile"; }, }; @@ -1514,7 +1509,7 @@ pub const Type = extern union { => false, .pointer => { - const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise); + const payload = self.castTag(.pointer).?.data; return payload.@"allowzero"; }, }; @@ -1525,7 +1520,7 @@ pub const Type = extern union { switch (self.tag()) { .optional_single_const_pointer, .optional_single_mut_pointer => return true, .optional => { - var buf: Payload.PointerSimple = undefined; + var buf: Payload.ElemType = undefined; const child_type = self.optionalChild(&buf); // optionals of zero sized pointers behave like bools if (!child_type.hasCodeGenBits()) return false; @@ -1563,7 +1558,7 @@ pub const Type = extern union { => return false, .Optional => { - var buf: Payload.PointerSimple = undefined; + var buf: Payload.ElemType = undefined; return ty.optionalChild(&buf).isValidVarType(is_extern); }, .Pointer, .Array => ty = ty.elemType(), @@ -1631,8 +1626,8 @@ pub const Type = extern union { .empty_struct, => unreachable, - .array => self.cast(Payload.Array).?.elem_type, - .array_sentinel => self.cast(Payload.ArraySentinel).?.elem_type, + .array => self.castTag(.array).?.data.elem_type, + .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type, .single_const_pointer, .single_mut_pointer, .many_const_pointer, @@ -1641,28 +1636,29 @@ pub const Type = extern union { .c_mut_pointer, .const_slice, .mut_slice, - => self.castPointer().?.pointee_type, + => self.castPointer().?.data, .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8), .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int), - .pointer => self.cast(Payload.Pointer).?.pointee_type, + .pointer => self.castTag(.pointer).?.data.pointee_type, }; } /// Asserts that the type is an optional. - pub fn optionalChild(self: Type, buf: *Payload.PointerSimple) Type { + /// Resulting `Type` will have inner memory referencing `buf`. + pub fn optionalChild(self: Type, buf: *Payload.ElemType) Type { return switch (self.tag()) { - .optional => self.cast(Payload.Optional).?.child_type, + .optional => self.castTag(.optional).?.data, .optional_single_mut_pointer => { buf.* = .{ .base = .{ .tag = .single_mut_pointer }, - .pointee_type = self.castPointer().?.pointee_type, + .data = self.castPointer().?.data, }; return Type.initPayload(&buf.base); }, .optional_single_const_pointer => { buf.* = .{ .base = .{ .tag = .single_const_pointer }, - .pointee_type = self.castPointer().?.pointee_type, + .data = self.castPointer().?.data, }; return Type.initPayload(&buf.base); }, @@ -1673,23 +1669,16 @@ pub const Type = extern union { /// Asserts that the type is an optional. /// Same as `optionalChild` but allocates the buffer if needed. pub fn optionalChildAlloc(self: Type, allocator: *Allocator) !Type { - return switch (self.tag()) { - .optional => self.cast(Payload.Optional).?.child_type, - .optional_single_mut_pointer, .optional_single_const_pointer => { - const payload = try allocator.create(Payload.PointerSimple); - payload.* = .{ - .base = .{ - .tag = if (self.tag() == .optional_single_const_pointer) - .single_const_pointer - else - .single_mut_pointer, - }, - .pointee_type = self.castPointer().?.pointee_type, - }; - return Type.initPayload(&payload.base); + switch (self.tag()) { + .optional => return self.castTag(.optional).?.data, + .optional_single_mut_pointer => { + return Tag.single_mut_pointer.create(allocator, self.castPointer().?.data); + }, + .optional_single_const_pointer => { + return Tag.single_const_pointer.create(allocator, self.castPointer().?.data); }, else => unreachable, - }; + } } /// Asserts the type is an array or vector. @@ -1759,10 +1748,10 @@ pub const Type = extern union { .empty_struct, => unreachable, - .array => self.cast(Payload.Array).?.len, - .array_sentinel => self.cast(Payload.ArraySentinel).?.len, - .array_u8 => self.cast(Payload.Array_u8).?.len, - .array_u8_sentinel_0 => self.cast(Payload.Array_u8_Sentinel0).?.len, + .array => self.castTag(.array).?.data.len, + .array_sentinel => self.castTag(.array_sentinel).?.data.len, + .array_u8 => self.castTag(.array_u8).?.data, + .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data, }; } @@ -1836,8 +1825,8 @@ pub const Type = extern union { .array_u8, => return null, - .pointer => return self.cast(Payload.Pointer).?.sentinel, - .array_sentinel => return self.cast(Payload.ArraySentinel).?.sentinel, + .pointer => return self.castTag(.pointer).?.data.sentinel, + .array_sentinel => return self.castTag(.array_sentinel).?.data.sentinel, .array_u8_sentinel_0 => return Value.initTag(.zero), }; } @@ -2048,8 +2037,14 @@ pub const Type = extern union { .empty_struct, => unreachable, - .int_unsigned => .{ .signedness = .unsigned, .bits = self.cast(Payload.IntUnsigned).?.bits }, - .int_signed => .{ .signedness = .signed, .bits = self.cast(Payload.IntSigned).?.bits }, + .int_unsigned => .{ + .signedness = .unsigned, + .bits = self.castTag(.int_unsigned).?.data, + }, + .int_signed => .{ + .signedness = .signed, + .bits = self.castTag(.int_signed).?.data, + }, .u8 => .{ .signedness = .unsigned, .bits = 8 }, .i8 => .{ .signedness = .signed, .bits = 8 }, .u16 => .{ .signedness = .unsigned, .bits = 16 }, @@ -2178,7 +2173,7 @@ pub const Type = extern union { .fn_void_no_args => 0, .fn_naked_noreturn_no_args => 0, .fn_ccc_void_no_args => 0, - .function => @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise).param_types.len, + .function => self.castTag(.function).?.data.param_types.len, .f16, .f32, @@ -2254,7 +2249,7 @@ pub const Type = extern union { .fn_naked_noreturn_no_args => return, .fn_ccc_void_no_args => return, .function => { - const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise); + const payload = self.castTag(.function).?.data; std.mem.copy(Type, types, payload.param_types); }, @@ -2327,7 +2322,7 @@ pub const Type = extern union { pub fn fnParamType(self: Type, index: usize) Type { switch (self.tag()) { .function => { - const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise); + const payload = self.castTag(.function).?.data; return payload.param_types[index]; }, @@ -2410,7 +2405,7 @@ pub const Type = extern union { .fn_ccc_void_no_args, => Type.initTag(.void), - .function => @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise).return_type, + .function => self.castTag(.function).?.data.return_type, .f16, .f32, @@ -2484,7 +2479,7 @@ pub const Type = extern union { .fn_void_no_args => .Unspecified, .fn_naked_noreturn_no_args => .Naked, .fn_ccc_void_no_args => .C, - .function => @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise).cc, + .function => self.castTag(.function).?.data.cc, .f16, .f32, @@ -2760,15 +2755,8 @@ pub const Type = extern union { .@"null" => return Value.initTag(.null_value), .@"undefined" => return Value.initTag(.undef), - .int_unsigned => { - if (ty.cast(Payload.IntUnsigned).?.bits == 0) { - return Value.initTag(.zero); - } else { - return null; - } - }, - .int_signed => { - if (ty.cast(Payload.IntSigned).?.bits == 0) { + .int_unsigned, .int_signed => { + if (ty.cast(Payload.Bits).?.data == 0) { return Value.initTag(.zero); } else { return null; @@ -2787,12 +2775,11 @@ pub const Type = extern union { .single_const_pointer, .single_mut_pointer, => { - const ptr = ty.castPointer().?; - ty = ptr.pointee_type; + ty = ty.castPointer().?.data; continue; }, .pointer => { - ty = ty.cast(Payload.Pointer).?.pointee_type; + ty = ty.castTag(.pointer).?.data.pointee_type; continue; }, }; @@ -2869,7 +2856,7 @@ pub const Type = extern union { .c_mut_pointer, => return true, - .pointer => self.cast(Payload.Pointer).?.size == .C, + .pointer => self.castTag(.pointer).?.data.size == .C, }; } @@ -2950,7 +2937,7 @@ pub const Type = extern union { .pointer, => unreachable, - .empty_struct => self.cast(Type.Payload.EmptyStruct).?.scope, + .empty_struct => self.castTag(.empty_struct).?.data, }; } @@ -3105,117 +3092,195 @@ pub const Type = extern union { pub const last_no_payload_tag = Tag.const_slice_u8; pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; + + pub fn Type(comptime t: Tag) type { + return switch (t) { + .u8, + .i8, + .u16, + .i16, + .u32, + .i32, + .u64, + .i64, + .usize, + .isize, + .c_short, + .c_ushort, + .c_int, + .c_uint, + .c_long, + .c_ulong, + .c_longlong, + .c_ulonglong, + .c_longdouble, + .f16, + .f32, + .f64, + .f128, + .c_void, + .bool, + .void, + .type, + .anyerror, + .comptime_int, + .comptime_float, + .noreturn, + .enum_literal, + .@"null", + .@"undefined", + .fn_noreturn_no_args, + .fn_void_no_args, + .fn_naked_noreturn_no_args, + .fn_ccc_void_no_args, + .single_const_pointer_to_comptime_int, + .anyerror_void_error_union, + .@"anyframe", + .const_slice_u8, + => @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, + + .int_signed, + .int_unsigned, + => Payload.Bits, + + .array => Payload.Array, + .array_sentinel => Payload.ArraySentinel, + .pointer => Payload.Pointer, + .function => Payload.Function, + .error_union => Payload.ErrorUnion, + .error_set => Payload.Decl, + .error_set_single => Payload.Name, + .empty_struct => Payload.ContainerScope, + }; + } + + pub fn create(comptime t: Tag, ally: *Allocator, data: Data(t)) error{OutOfMemory}!Type { + const ptr = try ally.create(t.Type()); + ptr.* = .{ + .base = .{ .tag = t }, + .data = data, + }; + return Type{ .ptr_otherwise = &ptr.base }; + } + + pub fn Data(comptime t: Tag) type { + return std.meta.fieldInfo(t.Type(), "data").field_type; + } }; + /// The sub-types are named after what fields they contain. pub const Payload = struct { tag: Tag, - pub const Array_u8_Sentinel0 = struct { - base: Payload = Payload{ .tag = .array_u8_sentinel_0 }, - - len: u64, - }; - - pub const Array_u8 = struct { - base: Payload = Payload{ .tag = .array_u8 }, - - len: u64, + pub const Len = struct { + base: Payload, + data: u64, }; pub const Array = struct { - base: Payload = Payload{ .tag = .array }, + pub const base_tag = Tag.array; - len: u64, - elem_type: Type, + base: Payload = Payload{ .tag = base_tag }, + data: struct { + len: u64, + elem_type: Type, + }, }; pub const ArraySentinel = struct { - base: Payload = Payload{ .tag = .array_sentinel }, + pub const base_tag = Tag.array_sentinel; - len: u64, - sentinel: Value, - elem_type: Type, + base: Payload = Payload{ .tag = base_tag }, + data: struct { + len: u64, + sentinel: Value, + elem_type: Type, + }, }; - pub const PointerSimple = struct { + pub const ElemType = struct { base: Payload, - - pointee_type: Type, + data: Type, }; - pub const IntSigned = struct { - base: Payload = Payload{ .tag = .int_signed }, - - bits: u16, - }; - - pub const IntUnsigned = struct { - base: Payload = Payload{ .tag = .int_unsigned }, - - bits: u16, + pub const Bits = struct { + base: Payload, + data: u16, }; pub const Function = struct { - base: Payload = Payload{ .tag = .function }, + pub const base_tag = Tag.function; - param_types: []Type, - return_type: Type, - cc: std.builtin.CallingConvention, - }; - - pub const Optional = struct { - base: Payload = Payload{ .tag = .optional }, - - child_type: Type, + base: Payload = Payload{ .tag = base_tag }, + data: struct { + param_types: []Type, + return_type: Type, + cc: std.builtin.CallingConvention, + }, }; pub const Pointer = struct { - base: Payload = .{ .tag = .pointer }, + pub const base_tag = Tag.pointer; - pointee_type: Type, - sentinel: ?Value, - /// If zero use pointee_type.AbiAlign() - @"align": u32, - bit_offset: u16, - host_size: u16, - @"allowzero": bool, - mutable: bool, - @"volatile": bool, - size: std.builtin.TypeInfo.Pointer.Size, + base: Payload = Payload{ .tag = base_tag }, + data: struct { + pointee_type: Type, + sentinel: ?Value, + /// If zero use pointee_type.AbiAlign() + @"align": u32, + bit_offset: u16, + host_size: u16, + @"allowzero": bool, + mutable: bool, + @"volatile": bool, + size: std.builtin.TypeInfo.Pointer.Size, + }, }; pub const ErrorUnion = struct { - base: Payload = .{ .tag = .error_union }, + pub const base_tag = Tag.error_union; - error_set: Type, - payload: Type, + base: Payload = Payload{ .tag = base_tag }, + data: struct { + error_set: Type, + payload: Type, + }, }; - pub const AnyFrame = struct { - base: Payload = .{ .tag = .anyframe_T }, - - return_type: Type, + pub const Decl = struct { + base: Payload, + data: *Module.Decl, }; - pub const ErrorSet = struct { - base: Payload = .{ .tag = .error_set }, - - decl: *Module.Decl, - }; - - pub const ErrorSetSingle = struct { - base: Payload = .{ .tag = .error_set_single }, - + pub const Name = struct { + base: Payload, /// memory is owned by `Module` - name: []const u8, + data: []const u8, }; /// Mostly used for namespace like structs with zero fields. /// Most commonly used for files. - pub const EmptyStruct = struct { - base: Payload = .{ .tag = .empty_struct }, - - scope: *Module.Scope.Container, + pub const ContainerScope = struct { + base: Payload, + data: *Module.Scope.Container, }; }; }; diff --git a/src/value.zig b/src/value.zig index 53c4b2d540..f26c8d8772 100644 --- a/src/value.zig +++ b/src/value.zig @@ -440,21 +440,18 @@ pub const Value = extern union { .int_type => { const payload = self.cast(Payload.IntType).?; - if (payload.signed) { - const new = try allocator.create(Type.Payload.IntSigned); - new.* = .{ .bits = payload.bits }; - return Type.initPayload(&new.base); - } else { - const new = try allocator.create(Type.Payload.IntUnsigned); - new.* = .{ .bits = payload.bits }; - return Type.initPayload(&new.base); - } + const new = try allocator.create(Type.Payload.Bits); + new.* = .{ + .base = .{ + .tag = if (payload.signed) .int_signed else .int_unsigned, + }, + .data = payload.bits, + }; + return Type.initPayload(&new.base); }, .error_set => { const payload = self.cast(Payload.ErrorSet).?; - const new = try allocator.create(Type.Payload.ErrorSet); - new.* = .{ .decl = payload.decl }; - return Type.initPayload(&new.base); + return Type.Tag.error_set.create(allocator, payload.decl); }, .undef, @@ -1321,13 +1318,13 @@ pub const Value = extern union { }, .int_type => { const payload = self.cast(Payload.IntType).?; - if (payload.signed) { - var new = Type.Payload.IntSigned{ .bits = payload.bits }; - return Type.initPayload(&new.base).hash(); - } else { - var new = Type.Payload.IntUnsigned{ .bits = payload.bits }; - return Type.initPayload(&new.base).hash(); - } + var int_payload = Type.Payload.Bits{ + .base = .{ + .tag = if (payload.signed) .int_signed else .int_unsigned, + }, + .data = payload.bits, + }; + return Type.initPayload(&int_payload.base).hash(); }, .empty_struct_value, diff --git a/src/zir.zig b/src/zir.zig index 47e1abc24b..bd9ab2c538 100644 --- a/src/zir.zig +++ b/src/zir.zig @@ -2785,7 +2785,7 @@ const EmitZIR = struct { } }, .Optional => { - var buf: Type.Payload.PointerSimple = undefined; + var buf: Type.Payload.ElemType = undefined; const inst = try self.arena.allocator.create(Inst.UnOp); inst.* = .{ .base = .{ diff --git a/src/zir_sema.zig b/src/zir_sema.zig index 3a9f511373..8960f3ba4d 100644 --- a/src/zir_sema.zig +++ b/src/zir_sema.zig @@ -480,14 +480,11 @@ fn analyzeInstStr(mod: *Module, scope: *Scope, str_inst: *zir.Inst.Str) InnerErr errdefer new_decl_arena.deinit(); const arena_bytes = try new_decl_arena.allocator.dupe(u8, str_inst.positionals.bytes); - const ty_payload = try scope.arena().create(Type.Payload.Array_u8_Sentinel0); - ty_payload.* = .{ .len = arena_bytes.len }; - const bytes_payload = try scope.arena().create(Value.Payload.Bytes); bytes_payload.* = .{ .data = arena_bytes }; const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{ - .ty = Type.initPayload(&ty_payload.base), + .ty = try Type.Tag.array_u8_sentinel_0.create(scope.arena(), arena_bytes.len), .val = Value.initPayload(&bytes_payload.base), }); return mod.analyzeDeclRef(scope, str_inst.base.src, new_decl); @@ -952,13 +949,12 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne param_types[i] = resolved; } - const payload = try arena.create(Type.Payload.Function); - payload.* = .{ + const fn_ty = try Type.Tag.function.create(arena, .{ .cc = fntype.kw_args.cc, .return_type = return_type, .param_types = param_types, - }; - return mod.constType(scope, fntype.base.src, Type.initPayload(&payload.base)); + }); + return mod.constType(scope, fntype.base.src, fn_ty); } fn analyzeInstPrimitive(mod: *Module, scope: *Scope, primitive: *zir.Inst.Primitive) InnerError!*Inst { @@ -1062,11 +1058,10 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr const ref_payload = try scope.arena().create(Value.Payload.RefVal); ref_payload.* = .{ .val = Value.initPayload(&error_payload.base) }; - const result_type = if (child_type.tag() == .anyerror) blk: { - const result_payload = try scope.arena().create(Type.Payload.ErrorSetSingle); - result_payload.* = .{ .name = entry.key }; - break :blk Type.initPayload(&result_payload.base); - } else child_type; + const result_type = if (child_type.tag() == .anyerror) + try Type.Tag.error_set_single.create(scope.arena(), entry.key) + else + child_type; return mod.constInst(scope, fieldptr.base.src, .{ .ty = try mod.simplePtrType(scope, fieldptr.base.src, result_type, false, .One), @@ -1195,15 +1190,10 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne // @intCast here because it would have been impossible to construct a value that // required a larger index. const elem_ptr = try array_ptr_val.elemPtr(scope.arena(), @intCast(usize, index_u64)); - - const type_payload = try scope.arena().create(Type.Payload.PointerSimple); - type_payload.* = .{ - .base = .{ .tag = .single_const_pointer }, - .pointee_type = elem_ty.elemType().elemType(), - }; + const pointee_type = elem_ty.elemType().elemType(); return mod.constInst(scope, inst.base.src, .{ - .ty = Type.initPayload(&type_payload.base), + .ty = try Type.Tag.single_const_pointer.create(scope.arena(), pointee_type), .val = elem_ptr, }); }