| ... | ... | @@ -721,6 +721,9 @@ pub const Tag = enum(u8) { |
| 721 | 721 | /// only an enum tag, but will be presented via the API with a different Key. |
| 722 | 722 | /// data is SimpleInternal enum value. |
| 723 | 723 | simple_internal, |
| 724 | /// Type: u16 |
| 725 | /// data is integer value |
| 726 | int_u16, |
| 724 | 727 | /// Type: u32 |
| 725 | 728 | /// data is integer value |
| 726 | 729 | int_u32, |
| ... | ... | @@ -1053,6 +1056,10 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1053 | 1056 | .type_error_union => @panic("TODO"), |
| 1054 | 1057 | .type_enum_simple => @panic("TODO"), |
| 1055 | 1058 | .simple_internal => @panic("TODO"), |
| 1059 | .int_u16 => .{ .int = .{ |
| 1060 | .ty = .u16_type, |
| 1061 | .storage = .{ .u64 = data }, |
| 1062 | } }, |
| 1056 | 1063 | .int_u32 => .{ .int = .{ |
| 1057 | 1064 | .ty = .u32_type, |
| 1058 | 1065 | .storage = .{ .u64 = data }, |
| ... | ... | @@ -1219,6 +1226,26 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1219 | 1226 | .int => |int| b: { |
| 1220 | 1227 | switch (int.ty) { |
| 1221 | 1228 | .none => unreachable, |
| 1229 | .u16_type => switch (int.storage) { |
| 1230 | .big_int => |big_int| { |
| 1231 | if (big_int.to(u32)) |casted| { |
| 1232 | ip.items.appendAssumeCapacity(.{ |
| 1233 | .tag = .int_u16, |
| 1234 | .data = casted, |
| 1235 | }); |
| 1236 | break :b; |
| 1237 | } else |_| {} |
| 1238 | }, |
| 1239 | inline .u64, .i64 => |x| { |
| 1240 | if (std.math.cast(u32, x)) |casted| { |
| 1241 | ip.items.appendAssumeCapacity(.{ |
| 1242 | .tag = .int_u16, |
| 1243 | .data = casted, |
| 1244 | }); |
| 1245 | break :b; |
| 1246 | } |
| 1247 | }, |
| 1248 | }, |
| 1222 | 1249 | .u32_type => switch (int.storage) { |
| 1223 | 1250 | .big_int => |big_int| { |
| 1224 | 1251 | if (big_int.to(u32)) |casted| { |
| ... | ... | @@ -1252,7 +1279,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1252 | 1279 | inline .u64, .i64 => |x| { |
| 1253 | 1280 | if (std.math.cast(i32, x)) |casted| { |
| 1254 | 1281 | ip.items.appendAssumeCapacity(.{ |
| 1255 | | .tag = .int_u32, |
| 1282 | .tag = .int_i32, |
| 1256 | 1283 | .data = @bitCast(u32, casted), |
| 1257 | 1284 | }); |
| 1258 | 1285 | break :b; |
| ... | ... | @@ -1466,6 +1493,7 @@ fn limbData(ip: InternPool, comptime T: type, index: usize) T { |
| 1466 | 1493 | return result; |
| 1467 | 1494 | } |
| 1468 | 1495 | |
| 1496 | /// This function returns the Limb slice that is trailing data after a payload. |
| 1469 | 1497 | fn limbSlice(ip: InternPool, comptime S: type, limb_index: u32, len: u32) []const Limb { |
| 1470 | 1498 | const field_count = @typeInfo(S).Struct.fields.len; |
| 1471 | 1499 | switch (@sizeOf(Limb)) { |
| ... | ... | @@ -1481,6 +1509,33 @@ fn limbSlice(ip: InternPool, comptime S: type, limb_index: u32, len: u32) []cons |
| 1481 | 1509 | } |
| 1482 | 1510 | } |
| 1483 | 1511 | |
| 1512 | const LimbsAsIndexes = struct { |
| 1513 | start: u32, |
| 1514 | len: u32, |
| 1515 | }; |
| 1516 | |
| 1517 | fn limbsSliceToIndex(ip: InternPool, limbs: []const Limb) LimbsAsIndexes { |
| 1518 | const host_slice = switch (@sizeOf(Limb)) { |
| 1519 | @sizeOf(u32) => ip.extra.items, |
| 1520 | @sizeOf(u64) => ip.limbs.items, |
| 1521 | else => @compileError("unsupported host"), |
| 1522 | }; |
| 1523 | // TODO: https://github.com/ziglang/zig/issues/1738 |
| 1524 | return .{ |
| 1525 | .start = @intCast(u32, @divExact(@ptrToInt(limbs.ptr) - @ptrToInt(host_slice.ptr), @sizeOf(Limb))), |
| 1526 | .len = @intCast(u32, limbs.len), |
| 1527 | }; |
| 1528 | } |
| 1529 | |
| 1530 | /// This function converts Limb array indexes to a primitive slice type. |
| 1531 | fn limbsIndexToSlice(ip: InternPool, limbs: LimbsAsIndexes) []const Limb { |
| 1532 | return switch (@sizeOf(Limb)) { |
| 1533 | @sizeOf(u32) => ip.extra.items[limbs.start..][0..limbs.len], |
| 1534 | @sizeOf(u64) => ip.limbs.items[limbs.start..][0..limbs.len], |
| 1535 | else => @compileError("unsupported host"), |
| 1536 | }; |
| 1537 | } |
| 1538 | |
| 1484 | 1539 | test "basic usage" { |
| 1485 | 1540 | const gpa = std.testing.allocator; |
| 1486 | 1541 | |
| ... | ... | @@ -1544,15 +1599,30 @@ pub fn getCoercedInt(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) |
| 1544 | 1599 | // Here we pre-reserve the limbs to ensure that the logic in `addInt` will |
| 1545 | 1600 | // not use an invalidated limbs pointer. |
| 1546 | 1601 | switch (key.int.storage) { |
| 1547 | | .u64, .i64 => {}, |
| 1602 | .u64 => |x| return ip.get(gpa, .{ .int = .{ |
| 1603 | .ty = new_ty, |
| 1604 | .storage = .{ .u64 = x }, |
| 1605 | } }), |
| 1606 | .i64 => |x| return ip.get(gpa, .{ .int = .{ |
| 1607 | .ty = new_ty, |
| 1608 | .storage = .{ .i64 = x }, |
| 1609 | } }), |
| 1610 | |
| 1548 | 1611 | .big_int => |big_int| { |
| 1612 | const positive = big_int.positive; |
| 1613 | const limbs = ip.limbsSliceToIndex(big_int.limbs); |
| 1614 | // This line invalidates the limbs slice, but the indexes computed in the |
| 1615 | // previous line are still correct. |
| 1549 | 1616 | try reserveLimbs(ip, gpa, @typeInfo(Int).Struct.fields.len + big_int.limbs.len); |
| 1617 | return ip.get(gpa, .{ .int = .{ |
| 1618 | .ty = new_ty, |
| 1619 | .storage = .{ .big_int = .{ |
| 1620 | .limbs = ip.limbsIndexToSlice(limbs), |
| 1621 | .positive = positive, |
| 1622 | } }, |
| 1623 | } }); |
| 1550 | 1624 | }, |
| 1551 | 1625 | } |
| 1552 | | return ip.get(gpa, .{ .int = .{ |
| 1553 | | .ty = new_ty, |
| 1554 | | .storage = key.int.storage, |
| 1555 | | } }); |
| 1556 | 1626 | } |
| 1557 | 1627 | |
| 1558 | 1628 | pub fn dump(ip: InternPool) void { |
| ... | ... | @@ -1608,6 +1678,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 1608 | 1678 | .simple_type => 0, |
| 1609 | 1679 | .simple_value => 0, |
| 1610 | 1680 | .simple_internal => 0, |
| 1681 | .int_u16 => 0, |
| 1611 | 1682 | .int_u32 => 0, |
| 1612 | 1683 | .int_i32 => 0, |
| 1613 | 1684 | .int_usize => 0, |