authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-12 16:00:29+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-13 08:12:17-07:00
log75eaf15740bc42167592f3bdd7205236828191c7
tree49edad088171ff45d6265ad88147c89f1a90298b
parentcb06d62603c764a91aeb9bcedc0b9472d746f9e5

stage2: add optional types


1 files changed, 155 insertions(+), 26 deletions(-)

src-self-hosted/type.zig+155-26
...@@ -70,6 +70,11 @@ pub const Type = extern union {...@@ -70,6 +70,11 @@ pub const Type = extern union {
70 .single_mut_pointer => return .Pointer,70 .single_mut_pointer => return .Pointer,
71 .single_const_pointer_to_comptime_int => return .Pointer,71 .single_const_pointer_to_comptime_int => return .Pointer,
72 .const_slice_u8 => return .Pointer,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 }
7580
...@@ -179,9 +184,13 @@ pub const Type = extern union {...@@ -179,9 +184,13 @@ pub const Type = extern union {
179 }184 }
180 return true;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 .Float,192 .Float,
183 .Struct,193 .Struct,
184 .Optional,
185 .ErrorUnion,194 .ErrorUnion,
186 .ErrorSet,195 .ErrorSet,
187 .Enum,196 .Enum,
...@@ -241,9 +250,11 @@ pub const Type = extern union {...@@ -241,9 +250,11 @@ pub const Type = extern union {
241 std.hash.autoHash(&hasher, self.fnParamType(i).hash());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 .Float,256 .Float,
245 .Struct,257 .Struct,
246 .Optional,
247 .ErrorUnion,258 .ErrorUnion,
248 .ErrorSet,259 .ErrorSet,
249 .Enum,260 .Enum,
...@@ -317,24 +328,8 @@ pub const Type = extern union {...@@ -317,24 +328,8 @@ pub const Type = extern union {
317 };328 };
318 return Type{ .ptr_otherwise = &new_payload.base };329 return Type{ .ptr_otherwise = &new_payload.base };
319 },330 },
320 .single_const_pointer => {331 .single_const_pointer => return self.copyPayloadSingleField(allocator, Payload.SingleConstPointer, "pointee_type"),
321 const payload = @fieldParentPtr(Payload.SingleConstPointer, "base", self.ptr_otherwise);332 .single_mut_pointer => return self.copyPayloadSingleField(allocator, Payload.SingleMutPointer, "pointee_type"),
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 },
338 .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned),333 .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned),
339 .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned),334 .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned),
340 .function => {335 .function => {
...@@ -352,6 +347,9 @@ pub const Type = extern union {...@@ -352,6 +347,9 @@ pub const Type = extern union {
352 };347 };
353 return Type{ .ptr_otherwise = &new_payload.base };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 }
357355
...@@ -362,6 +360,14 @@ pub const Type = extern union {...@@ -362,6 +360,14 @@ pub const Type = extern union {
362 return Type{ .ptr_otherwise = &new_payload.base };360 return Type{ .ptr_otherwise = &new_payload.base };
363 }361 }
364362
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 pub fn format(371 pub fn format(
366 self: Type,372 self: Type,
367 comptime fmt: []const u8,373 comptime fmt: []const u8,
...@@ -456,6 +462,24 @@ pub const Type = extern union {...@@ -456,6 +462,24 @@ pub const Type = extern union {
456 const payload = @fieldParentPtr(Payload.IntUnsigned, "base", ty.ptr_otherwise);462 const payload = @fieldParentPtr(Payload.IntUnsigned, "base", ty.ptr_otherwise);
457 return out_stream.print("u{}", .{payload.bits});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 unreachable;484 unreachable;
461 }485 }
...@@ -545,11 +569,15 @@ pub const Type = extern union {...@@ -545,11 +569,15 @@ pub const Type = extern union {
545 .single_const_pointer_to_comptime_int,569 .single_const_pointer_to_comptime_int,
546 .const_slice_u8,570 .const_slice_u8,
547 .array_u8_sentinel_0,571 .array_u8_sentinel_0,
548 .array, // TODO check for zero bits572 // TODO lazy types
549 .single_const_pointer,573 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
550 .single_mut_pointer,574 .single_const_pointer => self.elemType().hasCodeGenBits(),
551 .int_signed, // TODO check for zero bits575 .single_mut_pointer => self.elemType().hasCodeGenBits(),
552 .int_unsigned, // TODO check for zero bits576 .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 => true,581 => true,
554582
555 .c_void,583 .c_void,
...@@ -597,6 +625,8 @@ pub const Type = extern union {...@@ -597,6 +625,8 @@ pub const Type = extern union {
597 .const_slice_u8,625 .const_slice_u8,
598 .single_const_pointer,626 .single_const_pointer,
599 .single_mut_pointer,627 .single_mut_pointer,
628 .optional_single_const_pointer,
629 .optional_single_mut_pointer,
600 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),630 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
601631
602 .c_short => return @divExact(CType.short.sizeInBits(target), 8),632 .c_short => return @divExact(CType.short.sizeInBits(target), 8),
...@@ -629,6 +659,12 @@ pub const Type = extern union {...@@ -629,6 +659,12 @@ pub const Type = extern union {
629 return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);659 return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);
630 },660 },
631661
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 .c_void,668 .c_void,
633 .void,669 .void,
634 .type,670 .type,
...@@ -679,6 +715,8 @@ pub const Type = extern union {...@@ -679,6 +715,8 @@ pub const Type = extern union {
679 .const_slice_u8,715 .const_slice_u8,
680 .single_const_pointer,716 .single_const_pointer,
681 .single_mut_pointer,717 .single_mut_pointer,
718 .optional_single_const_pointer,
719 .optional_single_mut_pointer,
682 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),720 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
683721
684 .c_short => return @divExact(CType.short.sizeInBits(target), 8),722 .c_short => return @divExact(CType.short.sizeInBits(target), 8),
...@@ -708,6 +746,16 @@ pub const Type = extern union {...@@ -708,6 +746,16 @@ pub const Type = extern union {
708746
709 return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);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 }
713761
...@@ -756,6 +804,9 @@ pub const Type = extern union {...@@ -756,6 +804,9 @@ pub const Type = extern union {
756 .function,804 .function,
757 .int_unsigned,805 .int_unsigned,
758 .int_signed,806 .int_signed,
807 .optional,
808 .optional_single_mut_pointer,
809 .optional_single_const_pointer,
759 => false,810 => false,
760811
761 .single_const_pointer,812 .single_const_pointer,
...@@ -812,6 +863,9 @@ pub const Type = extern union {...@@ -812,6 +863,9 @@ pub const Type = extern union {
812 .function,863 .function,
813 .int_unsigned,864 .int_unsigned,
814 .int_signed,865 .int_signed,
866 .optional,
867 .optional_single_mut_pointer,
868 .optional_single_const_pointer,
815 => false,869 => false,
816870
817 .const_slice_u8 => true,871 .const_slice_u8 => true,
...@@ -863,6 +917,9 @@ pub const Type = extern union {...@@ -863,6 +917,9 @@ pub const Type = extern union {
863 .int_unsigned,917 .int_unsigned,
864 .int_signed,918 .int_signed,
865 .single_mut_pointer,919 .single_mut_pointer,
920 .optional,
921 .optional_single_mut_pointer,
922 .optional_single_const_pointer,
866 => false,923 => false,
867924
868 .single_const_pointer,925 .single_const_pointer,
...@@ -920,11 +977,14 @@ pub const Type = extern union {...@@ -920,11 +977,14 @@ pub const Type = extern union {
920 .single_const_pointer,977 .single_const_pointer,
921 .single_const_pointer_to_comptime_int,978 .single_const_pointer_to_comptime_int,
922 .const_slice_u8,979 .const_slice_u8,
980 .optional,
981 .optional_single_mut_pointer,
982 .optional_single_const_pointer,
923 => false,983 => false,
924 };984 };
925 }985 }
926986
927 /// Asserts the type is a pointer or array type.987 /// Asserts the type is a pointer, optional or array type.
928 pub fn elemType(self: Type) Type {988 pub fn elemType(self: Type) Type {
929 return switch (self.tag()) {989 return switch (self.tag()) {
930 .u8,990 .u8,
...@@ -974,6 +1034,9 @@ pub const Type = extern union {...@@ -974,6 +1034,9 @@ pub const Type = extern union {
974 .single_mut_pointer => self.cast(Payload.SingleMutPointer).?.pointee_type,1034 .single_mut_pointer => self.cast(Payload.SingleMutPointer).?.pointee_type,
975 .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),1035 .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),
976 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),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 }
9791042
...@@ -1024,6 +1087,9 @@ pub const Type = extern union {...@@ -1024,6 +1087,9 @@ pub const Type = extern union {
1024 .const_slice_u8,1087 .const_slice_u8,
1025 .int_unsigned,1088 .int_unsigned,
1026 .int_signed,1089 .int_signed,
1090 .optional,
1091 .optional_single_mut_pointer,
1092 .optional_single_const_pointer,
1027 => unreachable,1093 => unreachable,
10281094
1029 .array => self.cast(Payload.Array).?.len,1095 .array => self.cast(Payload.Array).?.len,
...@@ -1078,6 +1144,9 @@ pub const Type = extern union {...@@ -1078,6 +1144,9 @@ pub const Type = extern union {
1078 .const_slice_u8,1144 .const_slice_u8,
1079 .int_unsigned,1145 .int_unsigned,
1080 .int_signed,1146 .int_signed,
1147 .optional,
1148 .optional_single_mut_pointer,
1149 .optional_single_const_pointer,
1081 => unreachable,1150 => unreachable,
10821151
1083 .array => return null,1152 .array => return null,
...@@ -1129,6 +1198,9 @@ pub const Type = extern union {...@@ -1129,6 +1198,9 @@ pub const Type = extern union {
1129 .u16,1198 .u16,
1130 .u32,1199 .u32,
1131 .u64,1200 .u64,
1201 .optional,
1202 .optional_single_mut_pointer,
1203 .optional_single_const_pointer,
1132 => false,1204 => false,
11331205
1134 .int_signed,1206 .int_signed,
...@@ -1184,6 +1256,9 @@ pub const Type = extern union {...@@ -1184,6 +1256,9 @@ pub const Type = extern union {
1184 .i16,1256 .i16,
1185 .i32,1257 .i32,
1186 .i64,1258 .i64,
1259 .optional,
1260 .optional_single_mut_pointer,
1261 .optional_single_const_pointer,
1187 => false,1262 => false,
11881263
1189 .int_unsigned,1264 .int_unsigned,
...@@ -1229,6 +1304,9 @@ pub const Type = extern union {...@@ -1229,6 +1304,9 @@ pub const Type = extern union {
1229 .single_const_pointer_to_comptime_int,1304 .single_const_pointer_to_comptime_int,
1230 .array_u8_sentinel_0,1305 .array_u8_sentinel_0,
1231 .const_slice_u8,1306 .const_slice_u8,
1307 .optional,
1308 .optional_single_mut_pointer,
1309 .optional_single_const_pointer,
1232 => unreachable,1310 => unreachable,
12331311
1234 .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits },1312 .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits },
...@@ -1292,6 +1370,9 @@ pub const Type = extern union {...@@ -1292,6 +1370,9 @@ pub const Type = extern union {
1292 .i32,1370 .i32,
1293 .u64,1371 .u64,
1294 .i64,1372 .i64,
1373 .optional,
1374 .optional_single_mut_pointer,
1375 .optional_single_const_pointer,
1295 => false,1376 => false,
12961377
1297 .usize,1378 .usize,
...@@ -1384,6 +1465,9 @@ pub const Type = extern union {...@@ -1384,6 +1465,9 @@ pub const Type = extern union {
1384 .c_ulonglong,1465 .c_ulonglong,
1385 .int_unsigned,1466 .int_unsigned,
1386 .int_signed,1467 .int_signed,
1468 .optional,
1469 .optional_single_mut_pointer,
1470 .optional_single_const_pointer,
1387 => unreachable,1471 => unreachable,
1388 };1472 };
1389 }1473 }
...@@ -1442,6 +1526,9 @@ pub const Type = extern union {...@@ -1442,6 +1526,9 @@ pub const Type = extern union {
1442 .c_ulonglong,1526 .c_ulonglong,
1443 .int_unsigned,1527 .int_unsigned,
1444 .int_signed,1528 .int_signed,
1529 .optional,
1530 .optional_single_mut_pointer,
1531 .optional_single_const_pointer,
1445 => unreachable,1532 => unreachable,
1446 }1533 }
1447 }1534 }
...@@ -1499,6 +1586,9 @@ pub const Type = extern union {...@@ -1499,6 +1586,9 @@ pub const Type = extern union {
1499 .c_ulonglong,1586 .c_ulonglong,
1500 .int_unsigned,1587 .int_unsigned,
1501 .int_signed,1588 .int_signed,
1589 .optional,
1590 .optional_single_mut_pointer,
1591 .optional_single_const_pointer,
1502 => unreachable,1592 => unreachable,
1503 }1593 }
1504 }1594 }
...@@ -1556,6 +1646,9 @@ pub const Type = extern union {...@@ -1556,6 +1646,9 @@ pub const Type = extern union {
1556 .c_ulonglong,1646 .c_ulonglong,
1557 .int_unsigned,1647 .int_unsigned,
1558 .int_signed,1648 .int_signed,
1649 .optional,
1650 .optional_single_mut_pointer,
1651 .optional_single_const_pointer,
1559 => unreachable,1652 => unreachable,
1560 };1653 };
1561 }1654 }
...@@ -1610,6 +1703,9 @@ pub const Type = extern union {...@@ -1610,6 +1703,9 @@ pub const Type = extern union {
1610 .c_ulonglong,1703 .c_ulonglong,
1611 .int_unsigned,1704 .int_unsigned,
1612 .int_signed,1705 .int_signed,
1706 .optional,
1707 .optional_single_mut_pointer,
1708 .optional_single_const_pointer,
1613 => unreachable,1709 => unreachable,
1614 };1710 };
1615 }1711 }
...@@ -1664,6 +1760,9 @@ pub const Type = extern union {...@@ -1664,6 +1760,9 @@ pub const Type = extern union {
1664 .c_ulonglong,1760 .c_ulonglong,
1665 .int_unsigned,1761 .int_unsigned,
1666 .int_signed,1762 .int_signed,
1763 .optional,
1764 .optional_single_mut_pointer,
1765 .optional_single_const_pointer,
1667 => unreachable,1766 => unreachable,
1668 };1767 };
1669 }1768 }
...@@ -1718,6 +1817,9 @@ pub const Type = extern union {...@@ -1718,6 +1817,9 @@ pub const Type = extern union {
1718 .single_const_pointer_to_comptime_int,1817 .single_const_pointer_to_comptime_int,
1719 .array_u8_sentinel_0,1818 .array_u8_sentinel_0,
1720 .const_slice_u8,1819 .const_slice_u8,
1820 .optional,
1821 .optional_single_mut_pointer,
1822 .optional_single_const_pointer,
1721 => false,1823 => false,
1722 };1824 };
1723 }1825 }
...@@ -1762,6 +1864,9 @@ pub const Type = extern union {...@@ -1762,6 +1864,9 @@ pub const Type = extern union {
1762 .array_u8_sentinel_0,1864 .array_u8_sentinel_0,
1763 .const_slice_u8,1865 .const_slice_u8,
1764 .c_void,1866 .c_void,
1867 .optional,
1868 .optional_single_mut_pointer,
1869 .optional_single_const_pointer,
1765 => return null,1870 => return null,
17661871
1767 .void => return Value.initTag(.void_value),1872 .void => return Value.initTag(.void_value),
...@@ -1851,6 +1956,9 @@ pub const Type = extern union {...@@ -1851,6 +1956,9 @@ pub const Type = extern union {
1851 .array,1956 .array,
1852 .single_const_pointer,1957 .single_const_pointer,
1853 .single_mut_pointer,1958 .single_mut_pointer,
1959 .optional,
1960 .optional_single_mut_pointer,
1961 .optional_single_const_pointer,
1854 => return false,1962 => return false,
1855 };1963 };
1856 }1964 }
...@@ -1911,6 +2019,9 @@ pub const Type = extern union {...@@ -1911,6 +2019,9 @@ pub const Type = extern union {
1911 int_signed,2019 int_signed,
1912 int_unsigned,2020 int_unsigned,
1913 function,2021 function,
2022 optional,
2023 optional_single_mut_pointer,
2024 optional_single_const_pointer,
19142025
1915 pub const last_no_payload_tag = Tag.const_slice_u8;2026 pub const last_no_payload_tag = Tag.const_slice_u8;
1916 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;2027 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
...@@ -1963,6 +2074,24 @@ pub const Type = extern union {...@@ -1963,6 +2074,24 @@ pub const Type = extern union {
1963 return_type: Type,2074 return_type: Type,
1964 cc: std.builtin.CallingConvention,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};
19682097