| ... | @@ -169,6 +169,125 @@ pub const Type = extern union { | ... | @@ -169,6 +169,125 @@ pub const Type = extern union { |
| 169 | }; | 169 | }; |
| 170 | } | 170 | } |
| 171 | | 171 | |
| | 172 | pub fn ptrInfo(self: Type) Payload.Pointer { |
| | 173 | switch (self.tag()) { |
| | 174 | .single_const_pointer_to_comptime_int => return .{ .data = .{ |
| | 175 | .pointee_type = Type.initTag(.comptime_int), |
| | 176 | .sentinel = null, |
| | 177 | .@"align" = 0, |
| | 178 | .bit_offset = 0, |
| | 179 | .host_size = 0, |
| | 180 | .@"allowzero" = false, |
| | 181 | .mutable = false, |
| | 182 | .@"volatile" = false, |
| | 183 | .size = .One, |
| | 184 | } }, |
| | 185 | .const_slice_u8 => return .{ .data = .{ |
| | 186 | .pointee_type = Type.initTag(.u8), |
| | 187 | .sentinel = null, |
| | 188 | .@"align" = 0, |
| | 189 | .bit_offset = 0, |
| | 190 | .host_size = 0, |
| | 191 | .@"allowzero" = false, |
| | 192 | .mutable = false, |
| | 193 | .@"volatile" = false, |
| | 194 | .size = .Slice, |
| | 195 | } }, |
| | 196 | .single_const_pointer => return .{ .data = .{ |
| | 197 | .pointee_type = self.castPointer().?.data, |
| | 198 | .sentinel = null, |
| | 199 | .@"align" = 0, |
| | 200 | .bit_offset = 0, |
| | 201 | .host_size = 0, |
| | 202 | .@"allowzero" = false, |
| | 203 | .mutable = false, |
| | 204 | .@"volatile" = false, |
| | 205 | .size = .One, |
| | 206 | } }, |
| | 207 | .single_mut_pointer => return .{ .data = .{ |
| | 208 | .pointee_type = self.castPointer().?.data, |
| | 209 | .sentinel = null, |
| | 210 | .@"align" = 0, |
| | 211 | .bit_offset = 0, |
| | 212 | .host_size = 0, |
| | 213 | .@"allowzero" = false, |
| | 214 | .mutable = true, |
| | 215 | .@"volatile" = false, |
| | 216 | .size = .One, |
| | 217 | } }, |
| | 218 | .many_const_pointer => return .{ .data = .{ |
| | 219 | .pointee_type = self.castPointer().?.data, |
| | 220 | .sentinel = null, |
| | 221 | .@"align" = 0, |
| | 222 | .bit_offset = 0, |
| | 223 | .host_size = 0, |
| | 224 | .@"allowzero" = false, |
| | 225 | .mutable = false, |
| | 226 | .@"volatile" = false, |
| | 227 | .size = .Many, |
| | 228 | } }, |
| | 229 | .many_mut_pointer => return .{ .data = .{ |
| | 230 | .pointee_type = self.castPointer().?.data, |
| | 231 | .sentinel = null, |
| | 232 | .@"align" = 0, |
| | 233 | .bit_offset = 0, |
| | 234 | .host_size = 0, |
| | 235 | .@"allowzero" = false, |
| | 236 | .mutable = true, |
| | 237 | .@"volatile" = false, |
| | 238 | .size = .Many, |
| | 239 | } }, |
| | 240 | .c_const_pointer => return .{ .data = .{ |
| | 241 | .pointee_type = self.castPointer().?.data, |
| | 242 | .sentinel = null, |
| | 243 | .@"align" = 0, |
| | 244 | .bit_offset = 0, |
| | 245 | .host_size = 0, |
| | 246 | .@"allowzero" = false, |
| | 247 | .mutable = false, |
| | 248 | .@"volatile" = false, |
| | 249 | .size = .C, |
| | 250 | } }, |
| | 251 | .c_mut_pointer => return .{ .data = .{ |
| | 252 | .pointee_type = self.castPointer().?.data, |
| | 253 | .sentinel = null, |
| | 254 | .@"align" = 0, |
| | 255 | .bit_offset = 0, |
| | 256 | .host_size = 0, |
| | 257 | .@"allowzero" = false, |
| | 258 | .mutable = true, |
| | 259 | .@"volatile" = false, |
| | 260 | .size = .C, |
| | 261 | } }, |
| | 262 | .const_slice => return .{ .data = .{ |
| | 263 | .pointee_type = self.castPointer().?.data, |
| | 264 | .sentinel = null, |
| | 265 | .@"align" = 0, |
| | 266 | .bit_offset = 0, |
| | 267 | .host_size = 0, |
| | 268 | .@"allowzero" = false, |
| | 269 | .mutable = false, |
| | 270 | .@"volatile" = false, |
| | 271 | .size = .Slice, |
| | 272 | } }, |
| | 273 | .mut_slice => return .{ .data = .{ |
| | 274 | .pointee_type = self.castPointer().?.data, |
| | 275 | .sentinel = null, |
| | 276 | .@"align" = 0, |
| | 277 | .bit_offset = 0, |
| | 278 | .host_size = 0, |
| | 279 | .@"allowzero" = false, |
| | 280 | .mutable = true, |
| | 281 | .@"volatile" = false, |
| | 282 | .size = .Slice, |
| | 283 | } }, |
| | 284 | |
| | 285 | .pointer => return self.castTag(.pointer).?.*, |
| | 286 | |
| | 287 | else => unreachable, |
| | 288 | } |
| | 289 | } |
| | 290 | |
| 172 | pub fn eql(a: Type, b: Type) bool { | 291 | pub fn eql(a: Type, b: Type) bool { |
| 173 | // As a shortcut, if the small tags / addresses match, we're done. | 292 | // As a shortcut, if the small tags / addresses match, we're done. |
| 174 | if (a.tag_if_small_enough == b.tag_if_small_enough) | 293 | if (a.tag_if_small_enough == b.tag_if_small_enough) |
| ... | @@ -191,25 +310,38 @@ pub const Type = extern union { | ... | @@ -191,25 +310,38 @@ pub const Type = extern union { |
| 191 | return a.elemType().eql(b.elemType()); | 310 | return a.elemType().eql(b.elemType()); |
| 192 | }, | 311 | }, |
| 193 | .Pointer => { | 312 | .Pointer => { |
| 194 | // Hot path for common case: | 313 | const info_a = a.ptrInfo().data; |
| 195 | if (a.castPointer()) |a_payload| { | 314 | const info_b = b.ptrInfo().data; |
| 196 | if (b.castPointer()) |b_payload| { | 315 | if (!info_a.pointee_type.eql(info_b.pointee_type)) |
| 197 | return a.tag() == b.tag() and eql(a_payload.data, b_payload.data); | | |
| 198 | } | | |
| 199 | } | | |
| 200 | const is_slice_a = isSlice(a); | | |
| 201 | const is_slice_b = isSlice(b); | | |
| 202 | if (is_slice_a != is_slice_b) | | |
| 203 | return false; | 316 | return false; |
| 204 | | 317 | if (info_a.size != info_b.size) |
| 205 | const ptr_size_a = ptrSize(a); | 318 | return false; |
| 206 | const ptr_size_b = ptrSize(b); | 319 | if (info_a.mutable != info_b.mutable) |
| 207 | if (ptr_size_a != ptr_size_b) | 320 | return false; |
| | 321 | if (info_a.@"volatile" != info_b.@"volatile") |
| | 322 | return false; |
| | 323 | if (info_a.@"allowzero" != info_b.@"allowzero") |
| | 324 | return false; |
| | 325 | if (info_a.bit_offset != info_b.bit_offset) |
| | 326 | return false; |
| | 327 | if (info_a.host_size != info_b.host_size) |
| 208 | return false; | 328 | return false; |
| 209 | | 329 | |
| 210 | std.debug.panic("TODO implement more pointer Type equality comparison: {} and {}", .{ | 330 | const sentinel_a = info_a.sentinel; |
| 211 | a, b, | 331 | const sentinel_b = info_b.sentinel; |
| 212 | }); | 332 | if (sentinel_a) |sa| { |
| | 333 | if (sentinel_b) |sb| { |
| | 334 | if (!sa.eql(sb)) |
| | 335 | return false; |
| | 336 | } else { |
| | 337 | return false; |
| | 338 | } |
| | 339 | } else { |
| | 340 | if (sentinel_b != null) |
| | 341 | return false; |
| | 342 | } |
| | 343 | |
| | 344 | return true; |
| 213 | }, | 345 | }, |
| 214 | .Int => { | 346 | .Int => { |
| 215 | // Detect that e.g. u64 != usize, even if the bits match on a particular target. | 347 | // Detect that e.g. u64 != usize, even if the bits match on a particular target. |
| ... | @@ -844,6 +976,35 @@ pub const Type = extern union { | ... | @@ -844,6 +976,35 @@ pub const Type = extern union { |
| 844 | return fast_result; | 976 | return fast_result; |
| 845 | } | 977 | } |
| 846 | | 978 | |
| | 979 | pub fn ptrAlignment(self: Type, target: Target) u32 { |
| | 980 | switch (self.tag()) { |
| | 981 | .single_const_pointer, |
| | 982 | .single_mut_pointer, |
| | 983 | .many_const_pointer, |
| | 984 | .many_mut_pointer, |
| | 985 | .c_const_pointer, |
| | 986 | .c_mut_pointer, |
| | 987 | .const_slice, |
| | 988 | .mut_slice, |
| | 989 | .optional_single_const_pointer, |
| | 990 | .optional_single_mut_pointer, |
| | 991 | => return self.cast(Payload.ElemType).?.data.abiAlignment(target), |
| | 992 | |
| | 993 | .const_slice_u8 => return 1, |
| | 994 | |
| | 995 | .pointer => { |
| | 996 | const ptr_info = self.castTag(.pointer).?.data; |
| | 997 | if (ptr_info.@"align" != 0) { |
| | 998 | return ptr_info.@"align"; |
| | 999 | } else { |
| | 1000 | return ptr_info.pointee_type.abiAlignment(); |
| | 1001 | } |
| | 1002 | }, |
| | 1003 | |
| | 1004 | else => unreachable, |
| | 1005 | } |
| | 1006 | } |
| | 1007 | |
| 847 | /// Asserts that hasCodeGenBits() is true. | 1008 | /// Asserts that hasCodeGenBits() is true. |
| 848 | pub fn abiAlignment(self: Type, target: Target) u32 { | 1009 | pub fn abiAlignment(self: Type, target: Target) u32 { |
| 849 | return switch (self.tag()) { | 1010 | return switch (self.tag()) { |
| ... | @@ -885,15 +1046,9 @@ pub const Type = extern union { | ... | @@ -885,15 +1046,9 @@ pub const Type = extern union { |
| 885 | .mut_slice, | 1046 | .mut_slice, |
| 886 | .optional_single_const_pointer, | 1047 | .optional_single_const_pointer, |
| 887 | .optional_single_mut_pointer, | 1048 | .optional_single_mut_pointer, |
| | 1049 | .pointer, |
| 888 | => return @divExact(target.cpu.arch.ptrBitWidth(), 8), | 1050 | => return @divExact(target.cpu.arch.ptrBitWidth(), 8), |
| 889 | | 1051 | |
| 890 | .pointer => { | | |
| 891 | const payload = self.castTag(.pointer).?.data; | | |
| 892 | | | |
| 893 | if (payload.@"align" != 0) return payload.@"align"; | | |
| 894 | return @divExact(target.cpu.arch.ptrBitWidth(), 8); | | |
| 895 | }, | | |
| 896 | | | |
| 897 | .c_short => return @divExact(CType.short.sizeInBits(target), 8), | 1052 | .c_short => return @divExact(CType.short.sizeInBits(target), 8), |
| 898 | .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8), | 1053 | .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8), |
| 899 | .c_int => return @divExact(CType.int.sizeInBits(target), 8), | 1054 | .c_int => return @divExact(CType.int.sizeInBits(target), 8), |