From 68f4eb0f67b6e5f7c20332e79c8e8decb07748ee Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 27 Mar 2021 23:55:19 -0700 Subject: stage2: fully implement Type.eql for pointers Also fixed abiAlignment - for pointers it was returning the abi alignment inside the type, rather than of the pointer itself. There is now `ptrAlignment` for getting the alignment inside the type of pointers. --- src/type.zig | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 178 insertions(+), 23 deletions(-) (limited to 'src/type.zig') diff --git a/src/type.zig b/src/type.zig index 331994fe1e..817fe171cc 100644 --- a/src/type.zig +++ b/src/type.zig @@ -169,6 +169,125 @@ pub const Type = extern union { }; } + pub fn ptrInfo(self: Type) Payload.Pointer { + switch (self.tag()) { + .single_const_pointer_to_comptime_int => return .{ .data = .{ + .pointee_type = Type.initTag(.comptime_int), + .sentinel = null, + .@"align" = 0, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = false, + .@"volatile" = false, + .size = .One, + } }, + .const_slice_u8 => return .{ .data = .{ + .pointee_type = Type.initTag(.u8), + .sentinel = null, + .@"align" = 0, + .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, + .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, + .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, + .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, + .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, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = false, + .@"volatile" = false, + .size = .C, + } }, + .c_mut_pointer => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = true, + .@"volatile" = false, + .size = .C, + } }, + .const_slice => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .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, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = true, + .@"volatile" = false, + .size = .Slice, + } }, + + .pointer => return self.castTag(.pointer).?.*, + + else => unreachable, + } + } + pub fn eql(a: Type, b: Type) bool { // As a shortcut, if the small tags / addresses match, we're done. if (a.tag_if_small_enough == b.tag_if_small_enough) @@ -191,25 +310,38 @@ pub const Type = extern union { return a.elemType().eql(b.elemType()); }, .Pointer => { - // Hot path for common case: - if (a.castPointer()) |a_payload| { - if (b.castPointer()) |b_payload| { - return a.tag() == b.tag() and eql(a_payload.data, b_payload.data); - } - } - const is_slice_a = isSlice(a); - const is_slice_b = isSlice(b); - if (is_slice_a != is_slice_b) + const info_a = a.ptrInfo().data; + const info_b = b.ptrInfo().data; + if (!info_a.pointee_type.eql(info_b.pointee_type)) return false; - - const ptr_size_a = ptrSize(a); - const ptr_size_b = ptrSize(b); - if (ptr_size_a != ptr_size_b) + if (info_a.size != info_b.size) + return false; + if (info_a.mutable != info_b.mutable) + return false; + if (info_a.@"volatile" != info_b.@"volatile") + return false; + if (info_a.@"allowzero" != info_b.@"allowzero") + return false; + if (info_a.bit_offset != info_b.bit_offset) + return false; + if (info_a.host_size != info_b.host_size) return false; - std.debug.panic("TODO implement more pointer Type equality comparison: {} and {}", .{ - a, b, - }); + const sentinel_a = info_a.sentinel; + const sentinel_b = info_b.sentinel; + if (sentinel_a) |sa| { + if (sentinel_b) |sb| { + if (!sa.eql(sb)) + return false; + } else { + return false; + } + } else { + if (sentinel_b != null) + return false; + } + + return true; }, .Int => { // Detect that e.g. u64 != usize, even if the bits match on a particular target. @@ -844,6 +976,35 @@ pub const Type = extern union { return fast_result; } + pub fn ptrAlignment(self: Type, target: Target) u32 { + 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, + => return self.cast(Payload.ElemType).?.data.abiAlignment(target), + + .const_slice_u8 => return 1, + + .pointer => { + const ptr_info = self.castTag(.pointer).?.data; + if (ptr_info.@"align" != 0) { + return ptr_info.@"align"; + } else { + return ptr_info.pointee_type.abiAlignment(); + } + }, + + else => unreachable, + } + } + /// Asserts that hasCodeGenBits() is true. pub fn abiAlignment(self: Type, target: Target) u32 { return switch (self.tag()) { @@ -885,15 +1046,9 @@ pub const Type = extern union { .mut_slice, .optional_single_const_pointer, .optional_single_mut_pointer, + .pointer, => return @divExact(target.cpu.arch.ptrBitWidth(), 8), - .pointer => { - const payload = self.castTag(.pointer).?.data; - - if (payload.@"align" != 0) return payload.@"align"; - return @divExact(target.cpu.arch.ptrBitWidth(), 8); - }, - .c_short => return @divExact(CType.short.sizeInBits(target), 8), .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8), .c_int => return @divExact(CType.int.sizeInBits(target), 8), -- cgit v1.2.3