| author | |
| committer | |
| log | e94a81c951905a6b5bcf2a6028589ac1e33d1edd |
| tree | cc31783591b1b07257831563f46dfb83802b8489 |
| parent | 68b95a39b1fe734b938ec02fa2b16bbb63170f87 |
5 files changed, 122 insertions(+), 45 deletions(-)
src/InternPool.zig+75-43| ... | ... | @@ -55,7 +55,8 @@ pub const Key = union(enum) { |
| 55 | 55 | lib_name: u32, |
| 56 | 56 | }, |
| 57 | 57 | int: Key.Int, |
| 58 | ptr: Key.Ptr, | |
| 58 | ptr: Ptr, | |
| 59 | opt: Opt, | |
| 59 | 60 | enum_tag: struct { |
| 60 | 61 | ty: Index, |
| 61 | 62 | tag: BigIntConst, |
| ... | ... | @@ -151,6 +152,13 @@ pub const Key = union(enum) { |
| 151 | 152 | }; |
| 152 | 153 | }; |
| 153 | 154 | |
| 155 | /// `null` is represented by the `val` field being `none`. | |
| 156 | pub const Opt = struct { | |
| 157 | ty: Index, | |
| 158 | /// This could be `none`, indicating the optional is `null`. | |
| 159 | val: Index, | |
| 160 | }; | |
| 161 | ||
| 154 | 162 | pub fn hash32(key: Key) u32 { |
| 155 | 163 | return @truncate(u32, key.hash64()); |
| 156 | 164 | } |
| ... | ... | @@ -175,6 +183,7 @@ pub const Key = union(enum) { |
| 175 | 183 | .simple_type, |
| 176 | 184 | .simple_value, |
| 177 | 185 | .extern_func, |
| 186 | .opt, | |
| 178 | 187 | => |info| std.hash.autoHash(hasher, info), |
| 179 | 188 | |
| 180 | 189 | .int => |int| { |
| ... | ... | @@ -257,6 +266,10 @@ pub const Key = union(enum) { |
| 257 | 266 | const b_info = b.extern_func; |
| 258 | 267 | return std.meta.eql(a_info, b_info); |
| 259 | 268 | }, |
| 269 | .opt => |a_info| { | |
| 270 | const b_info = b.opt; | |
| 271 | return std.meta.eql(a_info, b_info); | |
| 272 | }, | |
| 260 | 273 | |
| 261 | 274 | .ptr => |a_info| { |
| 262 | 275 | const b_info = b.ptr; |
| ... | ... | @@ -343,6 +356,7 @@ pub const Key = union(enum) { |
| 343 | 356 | |
| 344 | 357 | inline .ptr, |
| 345 | 358 | .int, |
| 359 | .opt, | |
| 346 | 360 | .extern_func, |
| 347 | 361 | .enum_tag, |
| 348 | 362 | => |x| return x.ty, |
| ... | ... | @@ -771,7 +785,15 @@ pub const Tag = enum(u8) { |
| 771 | 785 | simple_internal, |
| 772 | 786 | /// A pointer to an integer value. |
| 773 | 787 | /// data is extra index of PtrInt, which contains the type and address. |
| 788 | /// Only pointer types are allowed to have this encoding. Optional types must use | |
| 789 | /// `opt_payload` or `opt_null`. | |
| 774 | 790 | ptr_int, |
| 791 | /// An optional value that is non-null. | |
| 792 | /// data is Index of the payload value. | |
| 793 | opt_payload, | |
| 794 | /// An optional value that is null. | |
| 795 | /// data is Index of the payload type. | |
| 796 | opt_null, | |
| 775 | 797 | /// Type: u8 |
| 776 | 798 | /// data is integer value |
| 777 | 799 | int_u8, |
| ... | ... | @@ -1129,6 +1151,14 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1129 | 1151 | .fields_len = 0, |
| 1130 | 1152 | } }, |
| 1131 | 1153 | }, |
| 1154 | .opt_null => .{ .opt = .{ | |
| 1155 | .ty = @intToEnum(Index, data), | |
| 1156 | .val = .none, | |
| 1157 | } }, | |
| 1158 | .opt_payload => .{ .opt = .{ | |
| 1159 | .ty = indexToKey(ip, @intToEnum(Index, data)).typeOf(), | |
| 1160 | .val = @intToEnum(Index, data), | |
| 1161 | } }, | |
| 1132 | 1162 | .ptr_int => { |
| 1133 | 1163 | const info = ip.extraData(PtrInt, data); |
| 1134 | 1164 | return .{ .ptr = .{ |
| ... | ... | @@ -1321,6 +1351,17 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1321 | 1351 | }, |
| 1322 | 1352 | }, |
| 1323 | 1353 | |
| 1354 | .opt => |opt| { | |
| 1355 | assert(opt.ty != .none); | |
| 1356 | ip.items.appendAssumeCapacity(if (opt.val == .none) .{ | |
| 1357 | .tag = .opt_null, | |
| 1358 | .data = @enumToInt(opt.ty), | |
| 1359 | } else .{ | |
| 1360 | .tag = .opt_payload, | |
| 1361 | .data = @enumToInt(opt.val), | |
| 1362 | }); | |
| 1363 | }, | |
| 1364 | ||
| 1324 | 1365 | .int => |int| b: { |
| 1325 | 1366 | switch (int.ty) { |
| 1326 | 1367 | .none => unreachable, |
| ... | ... | @@ -1342,62 +1383,51 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1342 | 1383 | }, |
| 1343 | 1384 | .u16_type => switch (int.storage) { |
| 1344 | 1385 | .big_int => |big_int| { |
| 1345 | if (big_int.to(u32)) |casted| { | |
| 1346 | ip.items.appendAssumeCapacity(.{ | |
| 1347 | .tag = .int_u16, | |
| 1348 | .data = casted, | |
| 1349 | }); | |
| 1350 | break :b; | |
| 1351 | } else |_| {} | |
| 1386 | ip.items.appendAssumeCapacity(.{ | |
| 1387 | .tag = .int_u16, | |
| 1388 | .data = big_int.to(u16) catch unreachable, | |
| 1389 | }); | |
| 1390 | break :b; | |
| 1352 | 1391 | }, |
| 1353 | 1392 | inline .u64, .i64 => |x| { |
| 1354 | if (std.math.cast(u32, x)) |casted| { | |
| 1355 | ip.items.appendAssumeCapacity(.{ | |
| 1356 | .tag = .int_u16, | |
| 1357 | .data = casted, | |
| 1358 | }); | |
| 1359 | break :b; | |
| 1360 | } | |
| 1393 | ip.items.appendAssumeCapacity(.{ | |
| 1394 | .tag = .int_u16, | |
| 1395 | .data = @intCast(u16, x), | |
| 1396 | }); | |
| 1397 | break :b; | |
| 1361 | 1398 | }, |
| 1362 | 1399 | }, |
| 1363 | 1400 | .u32_type => switch (int.storage) { |
| 1364 | 1401 | .big_int => |big_int| { |
| 1365 | if (big_int.to(u32)) |casted| { | |
| 1366 | ip.items.appendAssumeCapacity(.{ | |
| 1367 | .tag = .int_u32, | |
| 1368 | .data = casted, | |
| 1369 | }); | |
| 1370 | break :b; | |
| 1371 | } else |_| {} | |
| 1402 | ip.items.appendAssumeCapacity(.{ | |
| 1403 | .tag = .int_u32, | |
| 1404 | .data = big_int.to(u32) catch unreachable, | |
| 1405 | }); | |
| 1406 | break :b; | |
| 1372 | 1407 | }, |
| 1373 | 1408 | inline .u64, .i64 => |x| { |
| 1374 | if (std.math.cast(u32, x)) |casted| { | |
| 1375 | ip.items.appendAssumeCapacity(.{ | |
| 1376 | .tag = .int_u32, | |
| 1377 | .data = casted, | |
| 1378 | }); | |
| 1379 | break :b; | |
| 1380 | } | |
| 1409 | ip.items.appendAssumeCapacity(.{ | |
| 1410 | .tag = .int_u32, | |
| 1411 | .data = @intCast(u32, x), | |
| 1412 | }); | |
| 1413 | break :b; | |
| 1381 | 1414 | }, |
| 1382 | 1415 | }, |
| 1383 | 1416 | .i32_type => switch (int.storage) { |
| 1384 | 1417 | .big_int => |big_int| { |
| 1385 | if (big_int.to(i32)) |casted| { | |
| 1386 | ip.items.appendAssumeCapacity(.{ | |
| 1387 | .tag = .int_i32, | |
| 1388 | .data = @bitCast(u32, casted), | |
| 1389 | }); | |
| 1390 | break :b; | |
| 1391 | } else |_| {} | |
| 1418 | const casted = big_int.to(i32) catch unreachable; | |
| 1419 | ip.items.appendAssumeCapacity(.{ | |
| 1420 | .tag = .int_i32, | |
| 1421 | .data = @bitCast(u32, casted), | |
| 1422 | }); | |
| 1423 | break :b; | |
| 1392 | 1424 | }, |
| 1393 | 1425 | inline .u64, .i64 => |x| { |
| 1394 | if (std.math.cast(i32, x)) |casted| { | |
| 1395 | ip.items.appendAssumeCapacity(.{ | |
| 1396 | .tag = .int_i32, | |
| 1397 | .data = @bitCast(u32, casted), | |
| 1398 | }); | |
| 1399 | break :b; | |
| 1400 | } | |
| 1426 | ip.items.appendAssumeCapacity(.{ | |
| 1427 | .tag = .int_i32, | |
| 1428 | .data = @bitCast(u32, @intCast(i32, x)), | |
| 1429 | }); | |
| 1430 | break :b; | |
| 1401 | 1431 | }, |
| 1402 | 1432 | }, |
| 1403 | 1433 | .usize_type => switch (int.storage) { |
| ... | ... | @@ -1798,6 +1828,8 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 1798 | 1828 | .simple_value => 0, |
| 1799 | 1829 | .simple_internal => 0, |
| 1800 | 1830 | .ptr_int => @sizeOf(PtrInt), |
| 1831 | .opt_null => 0, | |
| 1832 | .opt_payload => 0, | |
| 1801 | 1833 | .int_u8 => 0, |
| 1802 | 1834 | .int_u16 => 0, |
| 1803 | 1835 | .int_u32 => 0, |
src/Module.zig+21-1| ... | ... | @@ -6887,12 +6887,32 @@ pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type { |
| 6887 | 6887 | return ptrType(mod, .{ .elem_type = child_type.ip_index, .is_const = true }); |
| 6888 | 6888 | } |
| 6889 | 6889 | |
| 6890 | /// Supports optionals in addition to pointers. | |
| 6890 | 6891 | pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value { |
| 6892 | if (ty.isPtrLikeOptional(mod)) { | |
| 6893 | const i = try intern(mod, .{ .opt = .{ | |
| 6894 | .ty = ty.ip_index, | |
| 6895 | .val = try intern(mod, .{ .ptr = .{ | |
| 6896 | .ty = ty.childType(mod).ip_index, | |
| 6897 | .addr = .{ .int = try intern(mod, .{ .int = .{ | |
| 6898 | .ty = .usize_type, | |
| 6899 | .storage = .{ .u64 = x }, | |
| 6900 | } }) }, | |
| 6901 | } }), | |
| 6902 | } }); | |
| 6903 | return i.toValue(); | |
| 6904 | } else { | |
| 6905 | return ptrIntValue_ptronly(mod, ty, x); | |
| 6906 | } | |
| 6907 | } | |
| 6908 | ||
| 6909 | /// Supports only pointers. See `ptrIntValue` for pointer-like optional support. | |
| 6910 | pub fn ptrIntValue_ptronly(mod: *Module, ty: Type, x: u64) Allocator.Error!Value { | |
| 6891 | 6911 | assert(ty.zigTypeTag(mod) == .Pointer); |
| 6892 | 6912 | const i = try intern(mod, .{ .ptr = .{ |
| 6893 | 6913 | .ty = ty.ip_index, |
| 6894 | 6914 | .addr = .{ .int = try intern(mod, .{ .int = .{ |
| 6895 | .ty = ty.ip_index, | |
| 6915 | .ty = .usize_type, | |
| 6896 | 6916 | .storage = .{ .u64 = x }, |
| 6897 | 6917 | } }) }, |
| 6898 | 6918 | } }); |
src/Sema.zig+3| ... | ... | @@ -31684,6 +31684,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31684 | 31684 | .extern_func => unreachable, |
| 31685 | 31685 | .int => unreachable, |
| 31686 | 31686 | .ptr => unreachable, |
| 31687 | .opt => unreachable, | |
| 31687 | 31688 | .enum_tag => unreachable, |
| 31688 | 31689 | }, |
| 31689 | 31690 | }; |
| ... | ... | @@ -33207,6 +33208,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33207 | 33208 | .extern_func => unreachable, |
| 33208 | 33209 | .int => unreachable, |
| 33209 | 33210 | .ptr => unreachable, |
| 33211 | .opt => unreachable, | |
| 33210 | 33212 | .enum_tag => unreachable, |
| 33211 | 33213 | }, |
| 33212 | 33214 | } |
| ... | ... | @@ -33776,6 +33778,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33776 | 33778 | .extern_func => unreachable, |
| 33777 | 33779 | .int => unreachable, |
| 33778 | 33780 | .ptr => unreachable, |
| 33781 | .opt => unreachable, | |
| 33779 | 33782 | .enum_tag => unreachable, |
| 33780 | 33783 | }, |
| 33781 | 33784 | }; |
src/type.zig+15-1| ... | ... | @@ -146,6 +146,7 @@ pub const Type = struct { |
| 146 | 146 | .extern_func => unreachable, |
| 147 | 147 | .int => unreachable, |
| 148 | 148 | .ptr => unreachable, |
| 149 | .opt => unreachable, | |
| 149 | 150 | .enum_tag => unreachable, |
| 150 | 151 | .simple_value => unreachable, |
| 151 | 152 | }, |
| ... | ... | @@ -1574,10 +1575,13 @@ pub const Type = struct { |
| 1574 | 1575 | .simple_type => |s| return writer.writeAll(@tagName(s)), |
| 1575 | 1576 | .struct_type => @panic("TODO"), |
| 1576 | 1577 | .union_type => @panic("TODO"), |
| 1578 | ||
| 1579 | // values, not types | |
| 1577 | 1580 | .simple_value => unreachable, |
| 1578 | 1581 | .extern_func => unreachable, |
| 1579 | 1582 | .int => unreachable, |
| 1580 | 1583 | .ptr => unreachable, |
| 1584 | .opt => unreachable, | |
| 1581 | 1585 | .enum_tag => unreachable, |
| 1582 | 1586 | }, |
| 1583 | 1587 | } |
| ... | ... | @@ -1850,6 +1854,7 @@ pub const Type = struct { |
| 1850 | 1854 | .extern_func => unreachable, |
| 1851 | 1855 | .int => unreachable, |
| 1852 | 1856 | .ptr => unreachable, |
| 1857 | .opt => unreachable, | |
| 1853 | 1858 | .enum_tag => unreachable, |
| 1854 | 1859 | }, |
| 1855 | 1860 | } |
| ... | ... | @@ -1961,6 +1966,7 @@ pub const Type = struct { |
| 1961 | 1966 | .extern_func => unreachable, |
| 1962 | 1967 | .int => unreachable, |
| 1963 | 1968 | .ptr => unreachable, |
| 1969 | .opt => unreachable, | |
| 1964 | 1970 | .enum_tag => unreachable, |
| 1965 | 1971 | }, |
| 1966 | 1972 | }; |
| ... | ... | @@ -2362,6 +2368,7 @@ pub const Type = struct { |
| 2362 | 2368 | .extern_func => unreachable, |
| 2363 | 2369 | .int => unreachable, |
| 2364 | 2370 | .ptr => unreachable, |
| 2371 | .opt => unreachable, | |
| 2365 | 2372 | .enum_tag => unreachable, |
| 2366 | 2373 | }, |
| 2367 | 2374 | } |
| ... | ... | @@ -2776,6 +2783,7 @@ pub const Type = struct { |
| 2776 | 2783 | .extern_func => unreachable, |
| 2777 | 2784 | .int => unreachable, |
| 2778 | 2785 | .ptr => unreachable, |
| 2786 | .opt => unreachable, | |
| 2779 | 2787 | .enum_tag => unreachable, |
| 2780 | 2788 | }, |
| 2781 | 2789 | } |
| ... | ... | @@ -2946,6 +2954,7 @@ pub const Type = struct { |
| 2946 | 2954 | .extern_func => unreachable, |
| 2947 | 2955 | .int => unreachable, |
| 2948 | 2956 | .ptr => unreachable, |
| 2957 | .opt => unreachable, | |
| 2949 | 2958 | .enum_tag => unreachable, |
| 2950 | 2959 | }; |
| 2951 | 2960 | |
| ... | ... | @@ -3803,6 +3812,7 @@ pub const Type = struct { |
| 3803 | 3812 | .extern_func => unreachable, |
| 3804 | 3813 | .int => unreachable, |
| 3805 | 3814 | .ptr => unreachable, |
| 3815 | .opt => unreachable, | |
| 3806 | 3816 | .enum_tag => unreachable, |
| 3807 | 3817 | }, |
| 3808 | 3818 | }; |
| ... | ... | @@ -4178,6 +4188,7 @@ pub const Type = struct { |
| 4178 | 4188 | .extern_func => unreachable, |
| 4179 | 4189 | .int => unreachable, |
| 4180 | 4190 | .ptr => unreachable, |
| 4191 | .opt => unreachable, | |
| 4181 | 4192 | .enum_tag => unreachable, |
| 4182 | 4193 | }, |
| 4183 | 4194 | }; |
| ... | ... | @@ -4339,11 +4350,14 @@ pub const Type = struct { |
| 4339 | 4350 | }, |
| 4340 | 4351 | .struct_type => @panic("TODO"), |
| 4341 | 4352 | .union_type => @panic("TODO"), |
| 4353 | ||
| 4354 | // values, not types | |
| 4342 | 4355 | .simple_value => unreachable, |
| 4343 | 4356 | .extern_func => unreachable, |
| 4344 | 4357 | .int => unreachable, |
| 4345 | 4358 | .ptr => unreachable, |
| 4346 | .enum_tag => unreachable, // it's a value, not a type | |
| 4359 | .opt => unreachable, | |
| 4360 | .enum_tag => unreachable, | |
| 4347 | 4361 | }, |
| 4348 | 4362 | }; |
| 4349 | 4363 | } |
src/value.zig+8| ... | ... | @@ -2336,6 +2336,14 @@ pub const Value = struct { |
| 2336 | 2336 | // The value is runtime-known and shouldn't affect the hash. |
| 2337 | 2337 | if (val.isRuntimeValue()) return; |
| 2338 | 2338 | |
| 2339 | if (val.ip_index != .none) { | |
| 2340 | // The InternPool data structure hashes based on Key to make interned objects | |
| 2341 | // unique. An Index can be treated simply as u32 value for the | |
| 2342 | // purpose of Type/Value hashing and equality. | |
| 2343 | std.hash.autoHash(hasher, val.ip_index); | |
| 2344 | return; | |
| 2345 | } | |
| 2346 | ||
| 2339 | 2347 | switch (ty.zigTypeTag(mod)) { |
| 2340 | 2348 | .Opaque => unreachable, // Cannot hash opaque types |
| 2341 | 2349 | .Void, |