| ... | ... | @@ -70,6 +70,11 @@ pub const Type = extern union { |
| 70 | 70 | .single_mut_pointer => return .Pointer, |
| 71 | 71 | .single_const_pointer_to_comptime_int => return .Pointer, |
| 72 | 72 | .const_slice_u8 => return .Pointer, |
| 73 | |
| 74 | .optional, |
| 75 | .optional_single_const_pointer, |
| 76 | .optional_single_mut_pointer, |
| 77 | => return .Optional, |
| 73 | 78 | } |
| 74 | 79 | } |
| 75 | 80 | |
| ... | ... | @@ -179,9 +184,13 @@ pub const Type = extern union { |
| 179 | 184 | } |
| 180 | 185 | return true; |
| 181 | 186 | }, |
| 187 | .Optional => { |
| 188 | if (a.tag() != b.tag()) |
| 189 | return false; |
| 190 | return a.elemType().eql(b.elemType()); |
| 191 | }, |
| 182 | 192 | .Float, |
| 183 | 193 | .Struct, |
| 184 | | .Optional, |
| 185 | 194 | .ErrorUnion, |
| 186 | 195 | .ErrorSet, |
| 187 | 196 | .Enum, |
| ... | ... | @@ -241,9 +250,11 @@ pub const Type = extern union { |
| 241 | 250 | std.hash.autoHash(&hasher, self.fnParamType(i).hash()); |
| 242 | 251 | } |
| 243 | 252 | }, |
| 253 | .Optional => { |
| 254 | std.hash.autoHash(&hasher, self.elemType().hash()); |
| 255 | }, |
| 244 | 256 | .Float, |
| 245 | 257 | .Struct, |
| 246 | | .Optional, |
| 247 | 258 | .ErrorUnion, |
| 248 | 259 | .ErrorSet, |
| 249 | 260 | .Enum, |
| ... | ... | @@ -317,24 +328,8 @@ pub const Type = extern union { |
| 317 | 328 | }; |
| 318 | 329 | return Type{ .ptr_otherwise = &new_payload.base }; |
| 319 | 330 | }, |
| 320 | | .single_const_pointer => { |
| 321 | | const payload = @fieldParentPtr(Payload.SingleConstPointer, "base", self.ptr_otherwise); |
| 322 | | const new_payload = try allocator.create(Payload.SingleConstPointer); |
| 323 | | new_payload.* = .{ |
| 324 | | .base = payload.base, |
| 325 | | .pointee_type = try payload.pointee_type.copy(allocator), |
| 326 | | }; |
| 327 | | return Type{ .ptr_otherwise = &new_payload.base }; |
| 328 | | }, |
| 329 | | .single_mut_pointer => { |
| 330 | | const payload = @fieldParentPtr(Payload.SingleMutPointer, "base", self.ptr_otherwise); |
| 331 | | const new_payload = try allocator.create(Payload.SingleMutPointer); |
| 332 | | new_payload.* = .{ |
| 333 | | .base = payload.base, |
| 334 | | .pointee_type = try payload.pointee_type.copy(allocator), |
| 335 | | }; |
| 336 | | return Type{ .ptr_otherwise = &new_payload.base }; |
| 337 | | }, |
| 331 | .single_const_pointer => return self.copyPayloadSingleField(allocator, Payload.SingleConstPointer, "pointee_type"), |
| 332 | .single_mut_pointer => return self.copyPayloadSingleField(allocator, Payload.SingleMutPointer, "pointee_type"), |
| 338 | 333 | .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned), |
| 339 | 334 | .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned), |
| 340 | 335 | .function => { |
| ... | ... | @@ -352,6 +347,9 @@ pub const Type = extern union { |
| 352 | 347 | }; |
| 353 | 348 | return Type{ .ptr_otherwise = &new_payload.base }; |
| 354 | 349 | }, |
| 350 | .optional => return self.copyPayloadSingleField(allocator, Payload.Optional, "child_type"), |
| 351 | .optional_single_mut_pointer => return self.copyPayloadSingleField(allocator, Payload.OptionalSingleMutPointer, "pointee_type"), |
| 352 | .optional_single_const_pointer => return self.copyPayloadSingleField(allocator, Payload.OptionalSingleConstPointer, "pointee_type"), |
| 355 | 353 | } |
| 356 | 354 | } |
| 357 | 355 | |
| ... | ... | @@ -362,6 +360,14 @@ pub const Type = extern union { |
| 362 | 360 | return Type{ .ptr_otherwise = &new_payload.base }; |
| 363 | 361 | } |
| 364 | 362 | |
| 363 | fn copyPayloadSingleField(self: Type, allocator: *Allocator, comptime T: type, comptime field_name: []const u8) error{OutOfMemory}!Type { |
| 364 | const payload = @fieldParentPtr(T, "base", self.ptr_otherwise); |
| 365 | const new_payload = try allocator.create(T); |
| 366 | new_payload.base = payload.base; |
| 367 | @field(new_payload, field_name) = try @field(payload, field_name).copy(allocator); |
| 368 | return Type{ .ptr_otherwise = &new_payload.base }; |
| 369 | } |
| 370 | |
| 365 | 371 | pub fn format( |
| 366 | 372 | self: Type, |
| 367 | 373 | comptime fmt: []const u8, |
| ... | ... | @@ -456,6 +462,24 @@ pub const Type = extern union { |
| 456 | 462 | const payload = @fieldParentPtr(Payload.IntUnsigned, "base", ty.ptr_otherwise); |
| 457 | 463 | return out_stream.print("u{}", .{payload.bits}); |
| 458 | 464 | }, |
| 465 | .optional => { |
| 466 | const payload = @fieldParentPtr(Payload.Optional, "base", ty.ptr_otherwise); |
| 467 | try out_stream.writeByte('?'); |
| 468 | ty = payload.child_type; |
| 469 | continue; |
| 470 | }, |
| 471 | .optional_single_const_pointer => { |
| 472 | const payload = @fieldParentPtr(Payload.OptionalSingleConstPointer, "base", ty.ptr_otherwise); |
| 473 | try out_stream.writeAll("?*const "); |
| 474 | ty = payload.pointee_type; |
| 475 | continue; |
| 476 | }, |
| 477 | .optional_single_mut_pointer => { |
| 478 | const payload = @fieldParentPtr(Payload.OptionalSingleMutPointer, "base", ty.ptr_otherwise); |
| 479 | try out_stream.writeAll("?*"); |
| 480 | ty = payload.pointee_type; |
| 481 | continue; |
| 482 | }, |
| 459 | 483 | } |
| 460 | 484 | unreachable; |
| 461 | 485 | } |
| ... | ... | @@ -545,11 +569,15 @@ pub const Type = extern union { |
| 545 | 569 | .single_const_pointer_to_comptime_int, |
| 546 | 570 | .const_slice_u8, |
| 547 | 571 | .array_u8_sentinel_0, |
| 548 | | .array, // TODO check for zero bits |
| 549 | | .single_const_pointer, |
| 550 | | .single_mut_pointer, |
| 551 | | .int_signed, // TODO check for zero bits |
| 552 | | .int_unsigned, // TODO check for zero bits |
| 572 | // TODO lazy types |
| 573 | .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0, |
| 574 | .single_const_pointer => self.elemType().hasCodeGenBits(), |
| 575 | .single_mut_pointer => self.elemType().hasCodeGenBits(), |
| 576 | .int_signed => self.cast(Payload.IntSigned).?.bits == 0, |
| 577 | .int_unsigned => self.cast(Payload.IntUnsigned).?.bits == 0, |
| 578 | .optional, |
| 579 | .optional_single_mut_pointer, |
| 580 | .optional_single_const_pointer, |
| 553 | 581 | => true, |
| 554 | 582 | |
| 555 | 583 | .c_void, |
| ... | ... | @@ -597,6 +625,8 @@ pub const Type = extern union { |
| 597 | 625 | .const_slice_u8, |
| 598 | 626 | .single_const_pointer, |
| 599 | 627 | .single_mut_pointer, |
| 628 | .optional_single_const_pointer, |
| 629 | .optional_single_mut_pointer, |
| 600 | 630 | => return @divExact(target.cpu.arch.ptrBitWidth(), 8), |
| 601 | 631 | |
| 602 | 632 | .c_short => return @divExact(CType.short.sizeInBits(target), 8), |
| ... | ... | @@ -629,6 +659,12 @@ pub const Type = extern union { |
| 629 | 659 | return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8); |
| 630 | 660 | }, |
| 631 | 661 | |
| 662 | .optional => { |
| 663 | const child_type = self.cast(Payload.Optional).?.child_type; |
| 664 | if (!child_type.hasCodeGenBits()) return 1; |
| 665 | return child_type.abiAlignment(target); |
| 666 | }, |
| 667 | |
| 632 | 668 | .c_void, |
| 633 | 669 | .void, |
| 634 | 670 | .type, |
| ... | ... | @@ -679,6 +715,8 @@ pub const Type = extern union { |
| 679 | 715 | .const_slice_u8, |
| 680 | 716 | .single_const_pointer, |
| 681 | 717 | .single_mut_pointer, |
| 718 | .optional_single_const_pointer, |
| 719 | .optional_single_mut_pointer, |
| 682 | 720 | => return @divExact(target.cpu.arch.ptrBitWidth(), 8), |
| 683 | 721 | |
| 684 | 722 | .c_short => return @divExact(CType.short.sizeInBits(target), 8), |
| ... | ... | @@ -708,6 +746,16 @@ pub const Type = extern union { |
| 708 | 746 | |
| 709 | 747 | return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8); |
| 710 | 748 | }, |
| 749 | |
| 750 | .optional => { |
| 751 | const child_type = self.cast(Payload.Optional).?.child_type; |
| 752 | if (!child_type.hasCodeGenBits()) return 1; |
| 753 | // Optional types are represented as a struct with the child type as the first |
| 754 | // field and a boolean as the second. Since the child type's abi alignment is |
| 755 | // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal |
| 756 | // to the child type's ABI alignment. |
| 757 | return child_type.abiAlignment(target) + child_type.abiSize(target); |
| 758 | }, |
| 711 | 759 | }; |
| 712 | 760 | } |
| 713 | 761 | |
| ... | ... | @@ -756,6 +804,9 @@ pub const Type = extern union { |
| 756 | 804 | .function, |
| 757 | 805 | .int_unsigned, |
| 758 | 806 | .int_signed, |
| 807 | .optional, |
| 808 | .optional_single_mut_pointer, |
| 809 | .optional_single_const_pointer, |
| 759 | 810 | => false, |
| 760 | 811 | |
| 761 | 812 | .single_const_pointer, |
| ... | ... | @@ -812,6 +863,9 @@ pub const Type = extern union { |
| 812 | 863 | .function, |
| 813 | 864 | .int_unsigned, |
| 814 | 865 | .int_signed, |
| 866 | .optional, |
| 867 | .optional_single_mut_pointer, |
| 868 | .optional_single_const_pointer, |
| 815 | 869 | => false, |
| 816 | 870 | |
| 817 | 871 | .const_slice_u8 => true, |
| ... | ... | @@ -863,6 +917,9 @@ pub const Type = extern union { |
| 863 | 917 | .int_unsigned, |
| 864 | 918 | .int_signed, |
| 865 | 919 | .single_mut_pointer, |
| 920 | .optional, |
| 921 | .optional_single_mut_pointer, |
| 922 | .optional_single_const_pointer, |
| 866 | 923 | => false, |
| 867 | 924 | |
| 868 | 925 | .single_const_pointer, |
| ... | ... | @@ -920,11 +977,14 @@ pub const Type = extern union { |
| 920 | 977 | .single_const_pointer, |
| 921 | 978 | .single_const_pointer_to_comptime_int, |
| 922 | 979 | .const_slice_u8, |
| 980 | .optional, |
| 981 | .optional_single_mut_pointer, |
| 982 | .optional_single_const_pointer, |
| 923 | 983 | => false, |
| 924 | 984 | }; |
| 925 | 985 | } |
| 926 | 986 | |
| 927 | | /// Asserts the type is a pointer or array type. |
| 987 | /// Asserts the type is a pointer, optional or array type. |
| 928 | 988 | pub fn elemType(self: Type) Type { |
| 929 | 989 | return switch (self.tag()) { |
| 930 | 990 | .u8, |
| ... | ... | @@ -974,6 +1034,9 @@ pub const Type = extern union { |
| 974 | 1034 | .single_mut_pointer => self.cast(Payload.SingleMutPointer).?.pointee_type, |
| 975 | 1035 | .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8), |
| 976 | 1036 | .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int), |
| 1037 | .optional => self.cast(Payload.Optional).?.child_type, |
| 1038 | .optional_single_mut_pointer => self.cast(Payload.OptionalSingleMutPointer).?.pointee_type, |
| 1039 | .optional_single_const_pointer => self.cast(Payload.OptionalSingleConstPointer).?.pointee_type, |
| 977 | 1040 | }; |
| 978 | 1041 | } |
| 979 | 1042 | |
| ... | ... | @@ -1024,6 +1087,9 @@ pub const Type = extern union { |
| 1024 | 1087 | .const_slice_u8, |
| 1025 | 1088 | .int_unsigned, |
| 1026 | 1089 | .int_signed, |
| 1090 | .optional, |
| 1091 | .optional_single_mut_pointer, |
| 1092 | .optional_single_const_pointer, |
| 1027 | 1093 | => unreachable, |
| 1028 | 1094 | |
| 1029 | 1095 | .array => self.cast(Payload.Array).?.len, |
| ... | ... | @@ -1078,6 +1144,9 @@ pub const Type = extern union { |
| 1078 | 1144 | .const_slice_u8, |
| 1079 | 1145 | .int_unsigned, |
| 1080 | 1146 | .int_signed, |
| 1147 | .optional, |
| 1148 | .optional_single_mut_pointer, |
| 1149 | .optional_single_const_pointer, |
| 1081 | 1150 | => unreachable, |
| 1082 | 1151 | |
| 1083 | 1152 | .array => return null, |
| ... | ... | @@ -1129,6 +1198,9 @@ pub const Type = extern union { |
| 1129 | 1198 | .u16, |
| 1130 | 1199 | .u32, |
| 1131 | 1200 | .u64, |
| 1201 | .optional, |
| 1202 | .optional_single_mut_pointer, |
| 1203 | .optional_single_const_pointer, |
| 1132 | 1204 | => false, |
| 1133 | 1205 | |
| 1134 | 1206 | .int_signed, |
| ... | ... | @@ -1184,6 +1256,9 @@ pub const Type = extern union { |
| 1184 | 1256 | .i16, |
| 1185 | 1257 | .i32, |
| 1186 | 1258 | .i64, |
| 1259 | .optional, |
| 1260 | .optional_single_mut_pointer, |
| 1261 | .optional_single_const_pointer, |
| 1187 | 1262 | => false, |
| 1188 | 1263 | |
| 1189 | 1264 | .int_unsigned, |
| ... | ... | @@ -1229,6 +1304,9 @@ pub const Type = extern union { |
| 1229 | 1304 | .single_const_pointer_to_comptime_int, |
| 1230 | 1305 | .array_u8_sentinel_0, |
| 1231 | 1306 | .const_slice_u8, |
| 1307 | .optional, |
| 1308 | .optional_single_mut_pointer, |
| 1309 | .optional_single_const_pointer, |
| 1232 | 1310 | => unreachable, |
| 1233 | 1311 | |
| 1234 | 1312 | .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits }, |
| ... | ... | @@ -1292,6 +1370,9 @@ pub const Type = extern union { |
| 1292 | 1370 | .i32, |
| 1293 | 1371 | .u64, |
| 1294 | 1372 | .i64, |
| 1373 | .optional, |
| 1374 | .optional_single_mut_pointer, |
| 1375 | .optional_single_const_pointer, |
| 1295 | 1376 | => false, |
| 1296 | 1377 | |
| 1297 | 1378 | .usize, |
| ... | ... | @@ -1384,6 +1465,9 @@ pub const Type = extern union { |
| 1384 | 1465 | .c_ulonglong, |
| 1385 | 1466 | .int_unsigned, |
| 1386 | 1467 | .int_signed, |
| 1468 | .optional, |
| 1469 | .optional_single_mut_pointer, |
| 1470 | .optional_single_const_pointer, |
| 1387 | 1471 | => unreachable, |
| 1388 | 1472 | }; |
| 1389 | 1473 | } |
| ... | ... | @@ -1442,6 +1526,9 @@ pub const Type = extern union { |
| 1442 | 1526 | .c_ulonglong, |
| 1443 | 1527 | .int_unsigned, |
| 1444 | 1528 | .int_signed, |
| 1529 | .optional, |
| 1530 | .optional_single_mut_pointer, |
| 1531 | .optional_single_const_pointer, |
| 1445 | 1532 | => unreachable, |
| 1446 | 1533 | } |
| 1447 | 1534 | } |
| ... | ... | @@ -1499,6 +1586,9 @@ pub const Type = extern union { |
| 1499 | 1586 | .c_ulonglong, |
| 1500 | 1587 | .int_unsigned, |
| 1501 | 1588 | .int_signed, |
| 1589 | .optional, |
| 1590 | .optional_single_mut_pointer, |
| 1591 | .optional_single_const_pointer, |
| 1502 | 1592 | => unreachable, |
| 1503 | 1593 | } |
| 1504 | 1594 | } |
| ... | ... | @@ -1556,6 +1646,9 @@ pub const Type = extern union { |
| 1556 | 1646 | .c_ulonglong, |
| 1557 | 1647 | .int_unsigned, |
| 1558 | 1648 | .int_signed, |
| 1649 | .optional, |
| 1650 | .optional_single_mut_pointer, |
| 1651 | .optional_single_const_pointer, |
| 1559 | 1652 | => unreachable, |
| 1560 | 1653 | }; |
| 1561 | 1654 | } |
| ... | ... | @@ -1610,6 +1703,9 @@ pub const Type = extern union { |
| 1610 | 1703 | .c_ulonglong, |
| 1611 | 1704 | .int_unsigned, |
| 1612 | 1705 | .int_signed, |
| 1706 | .optional, |
| 1707 | .optional_single_mut_pointer, |
| 1708 | .optional_single_const_pointer, |
| 1613 | 1709 | => unreachable, |
| 1614 | 1710 | }; |
| 1615 | 1711 | } |
| ... | ... | @@ -1664,6 +1760,9 @@ pub const Type = extern union { |
| 1664 | 1760 | .c_ulonglong, |
| 1665 | 1761 | .int_unsigned, |
| 1666 | 1762 | .int_signed, |
| 1763 | .optional, |
| 1764 | .optional_single_mut_pointer, |
| 1765 | .optional_single_const_pointer, |
| 1667 | 1766 | => unreachable, |
| 1668 | 1767 | }; |
| 1669 | 1768 | } |
| ... | ... | @@ -1718,6 +1817,9 @@ pub const Type = extern union { |
| 1718 | 1817 | .single_const_pointer_to_comptime_int, |
| 1719 | 1818 | .array_u8_sentinel_0, |
| 1720 | 1819 | .const_slice_u8, |
| 1820 | .optional, |
| 1821 | .optional_single_mut_pointer, |
| 1822 | .optional_single_const_pointer, |
| 1721 | 1823 | => false, |
| 1722 | 1824 | }; |
| 1723 | 1825 | } |
| ... | ... | @@ -1762,6 +1864,9 @@ pub const Type = extern union { |
| 1762 | 1864 | .array_u8_sentinel_0, |
| 1763 | 1865 | .const_slice_u8, |
| 1764 | 1866 | .c_void, |
| 1867 | .optional, |
| 1868 | .optional_single_mut_pointer, |
| 1869 | .optional_single_const_pointer, |
| 1765 | 1870 | => return null, |
| 1766 | 1871 | |
| 1767 | 1872 | .void => return Value.initTag(.void_value), |
| ... | ... | @@ -1851,6 +1956,9 @@ pub const Type = extern union { |
| 1851 | 1956 | .array, |
| 1852 | 1957 | .single_const_pointer, |
| 1853 | 1958 | .single_mut_pointer, |
| 1959 | .optional, |
| 1960 | .optional_single_mut_pointer, |
| 1961 | .optional_single_const_pointer, |
| 1854 | 1962 | => return false, |
| 1855 | 1963 | }; |
| 1856 | 1964 | } |
| ... | ... | @@ -1911,6 +2019,9 @@ pub const Type = extern union { |
| 1911 | 2019 | int_signed, |
| 1912 | 2020 | int_unsigned, |
| 1913 | 2021 | function, |
| 2022 | optional, |
| 2023 | optional_single_mut_pointer, |
| 2024 | optional_single_const_pointer, |
| 1914 | 2025 | |
| 1915 | 2026 | pub const last_no_payload_tag = Tag.const_slice_u8; |
| 1916 | 2027 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; |
| ... | ... | @@ -1963,6 +2074,24 @@ pub const Type = extern union { |
| 1963 | 2074 | return_type: Type, |
| 1964 | 2075 | cc: std.builtin.CallingConvention, |
| 1965 | 2076 | }; |
| 2077 | |
| 2078 | pub const Optional = struct { |
| 2079 | base: Payload = Payload{ .tag = .optional }, |
| 2080 | |
| 2081 | child_type: Type, |
| 2082 | }; |
| 2083 | |
| 2084 | pub const OptionalSingleConstPointer = struct { |
| 2085 | base: Payload = Payload{ .tag = .optional_single_const_pointer }, |
| 2086 | |
| 2087 | pointee_type: Type, |
| 2088 | }; |
| 2089 | |
| 2090 | pub const OptionalSingleMutPointer = struct { |
| 2091 | base: Payload = Payload{ .tag = .optional_single_mut_pointer }, |
| 2092 | |
| 2093 | pointee_type: Type, |
| 2094 | }; |
| 1966 | 2095 | }; |
| 1967 | 2096 | }; |
| 1968 | 2097 | |