| ... | ... | @@ -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 | 291 | pub fn eql(a: Type, b: Type) bool { |
| 173 | 292 | // As a shortcut, if the small tags / addresses match, we're done. |
| 174 | 293 | if (a.tag_if_small_enough == b.tag_if_small_enough) |
| ... | ... | @@ -191,25 +310,38 @@ pub const Type = extern union { |
| 191 | 310 | return a.elemType().eql(b.elemType()); |
| 192 | 311 | }, |
| 193 | 312 | .Pointer => { |
| 194 | | // Hot path for common case: |
| 195 | | if (a.castPointer()) |a_payload| { |
| 196 | | if (b.castPointer()) |b_payload| { |
| 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) |
| 313 | const info_a = a.ptrInfo().data; |
| 314 | const info_b = b.ptrInfo().data; |
| 315 | if (!info_a.pointee_type.eql(info_b.pointee_type)) |
| 203 | 316 | return false; |
| 204 | | |
| 205 | | const ptr_size_a = ptrSize(a); |
| 206 | | const ptr_size_b = ptrSize(b); |
| 207 | | if (ptr_size_a != ptr_size_b) |
| 317 | if (info_a.size != info_b.size) |
| 318 | return false; |
| 319 | if (info_a.mutable != info_b.mutable) |
| 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 | 328 | return false; |
| 209 | 329 | |
| 210 | | std.debug.panic("TODO implement more pointer Type equality comparison: {} and {}", .{ |
| 211 | | a, b, |
| 212 | | }); |
| 330 | const sentinel_a = info_a.sentinel; |
| 331 | const sentinel_b = info_b.sentinel; |
| 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 | 346 | .Int => { |
| 215 | 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 | 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 | 1008 | /// Asserts that hasCodeGenBits() is true. |
| 848 | 1009 | pub fn abiAlignment(self: Type, target: Target) u32 { |
| 849 | 1010 | return switch (self.tag()) { |
| ... | ... | @@ -885,15 +1046,9 @@ pub const Type = extern union { |
| 885 | 1046 | .mut_slice, |
| 886 | 1047 | .optional_single_const_pointer, |
| 887 | 1048 | .optional_single_mut_pointer, |
| 1049 | .pointer, |
| 888 | 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 | 1052 | .c_short => return @divExact(CType.short.sizeInBits(target), 8), |
| 898 | 1053 | .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8), |
| 899 | 1054 | .c_int => return @divExact(CType.int.sizeInBits(target), 8), |