| ... | @@ -721,6 +721,9 @@ pub const Tag = enum(u8) { | ... | @@ -721,6 +721,9 @@ pub const Tag = enum(u8) { |
| 721 | /// only an enum tag, but will be presented via the API with a different Key. | 721 | /// only an enum tag, but will be presented via the API with a different Key. |
| 722 | /// data is SimpleInternal enum value. | 722 | /// data is SimpleInternal enum value. |
| 723 | simple_internal, | 723 | simple_internal, |
| | 724 | /// Type: u16 |
| | 725 | /// data is integer value |
| | 726 | int_u16, |
| 724 | /// Type: u32 | 727 | /// Type: u32 |
| 725 | /// data is integer value | 728 | /// data is integer value |
| 726 | int_u32, | 729 | int_u32, |
| ... | @@ -1053,6 +1056,10 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { | ... | @@ -1053,6 +1056,10 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1053 | .type_error_union => @panic("TODO"), | 1056 | .type_error_union => @panic("TODO"), |
| 1054 | .type_enum_simple => @panic("TODO"), | 1057 | .type_enum_simple => @panic("TODO"), |
| 1055 | .simple_internal => @panic("TODO"), | 1058 | .simple_internal => @panic("TODO"), |
| | 1059 | .int_u16 => .{ .int = .{ |
| | 1060 | .ty = .u16_type, |
| | 1061 | .storage = .{ .u64 = data }, |
| | 1062 | } }, |
| 1056 | .int_u32 => .{ .int = .{ | 1063 | .int_u32 => .{ .int = .{ |
| 1057 | .ty = .u32_type, | 1064 | .ty = .u32_type, |
| 1058 | .storage = .{ .u64 = data }, | 1065 | .storage = .{ .u64 = data }, |
| ... | @@ -1219,6 +1226,26 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -1219,6 +1226,26 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1219 | .int => |int| b: { | 1226 | .int => |int| b: { |
| 1220 | switch (int.ty) { | 1227 | switch (int.ty) { |
| 1221 | .none => unreachable, | 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 | .u32_type => switch (int.storage) { | 1249 | .u32_type => switch (int.storage) { |
| 1223 | .big_int => |big_int| { | 1250 | .big_int => |big_int| { |
| 1224 | if (big_int.to(u32)) |casted| { | 1251 | if (big_int.to(u32)) |casted| { |
| ... | @@ -1252,7 +1279,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -1252,7 +1279,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1252 | inline .u64, .i64 => |x| { | 1279 | inline .u64, .i64 => |x| { |
| 1253 | if (std.math.cast(i32, x)) |casted| { | 1280 | if (std.math.cast(i32, x)) |casted| { |
| 1254 | ip.items.appendAssumeCapacity(.{ | 1281 | ip.items.appendAssumeCapacity(.{ |
| 1255 | .tag = .int_u32, | 1282 | .tag = .int_i32, |
| 1256 | .data = @bitCast(u32, casted), | 1283 | .data = @bitCast(u32, casted), |
| 1257 | }); | 1284 | }); |
| 1258 | break :b; | 1285 | break :b; |
| ... | @@ -1466,6 +1493,7 @@ fn limbData(ip: InternPool, comptime T: type, index: usize) T { | ... | @@ -1466,6 +1493,7 @@ fn limbData(ip: InternPool, comptime T: type, index: usize) T { |
| 1466 | return result; | 1493 | return result; |
| 1467 | } | 1494 | } |
| 1468 | | 1495 | |
| | 1496 | /// This function returns the Limb slice that is trailing data after a payload. |
| 1469 | fn limbSlice(ip: InternPool, comptime S: type, limb_index: u32, len: u32) []const Limb { | 1497 | fn limbSlice(ip: InternPool, comptime S: type, limb_index: u32, len: u32) []const Limb { |
| 1470 | const field_count = @typeInfo(S).Struct.fields.len; | 1498 | const field_count = @typeInfo(S).Struct.fields.len; |
| 1471 | switch (@sizeOf(Limb)) { | 1499 | switch (@sizeOf(Limb)) { |
| ... | @@ -1481,6 +1509,33 @@ fn limbSlice(ip: InternPool, comptime S: type, limb_index: u32, len: u32) []cons | ... | @@ -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 | test "basic usage" { | 1539 | test "basic usage" { |
| 1485 | const gpa = std.testing.allocator; | 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,15 +1599,30 @@ pub fn getCoercedInt(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) |
| 1544 | // Here we pre-reserve the limbs to ensure that the logic in `addInt` will | 1599 | // Here we pre-reserve the limbs to ensure that the logic in `addInt` will |
| 1545 | // not use an invalidated limbs pointer. | 1600 | // not use an invalidated limbs pointer. |
| 1546 | switch (key.int.storage) { | 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 | .big_int => |big_int| { | 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 | try reserveLimbs(ip, gpa, @typeInfo(Int).Struct.fields.len + big_int.limbs.len); | 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 | pub fn dump(ip: InternPool) void { | 1628 | pub fn dump(ip: InternPool) void { |
| ... | @@ -1608,6 +1678,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { | ... | @@ -1608,6 +1678,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 1608 | .simple_type => 0, | 1678 | .simple_type => 0, |
| 1609 | .simple_value => 0, | 1679 | .simple_value => 0, |
| 1610 | .simple_internal => 0, | 1680 | .simple_internal => 0, |
| | 1681 | .int_u16 => 0, |
| 1611 | .int_u32 => 0, | 1682 | .int_u32 => 0, |
| 1612 | .int_i32 => 0, | 1683 | .int_i32 => 0, |
| 1613 | .int_usize => 0, | 1684 | .int_usize => 0, |