authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-06 20:00:47-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:42:29-07:00
log9d9e1a29911c0ecf92eb9db10027cf691cd4b07e
treecf0eec299b3daf3c1e1804e9e47abcc9f955b8bd
parent6c713b40f76a2df9c06f875026f628a99a5088f0

InternPool: implement indexToKey and equality for int values


1 files changed, 55 insertions(+), 12 deletions(-)

src/InternPool.zig+55-12
...@@ -5,6 +5,8 @@ items: std.MultiArrayList(Item) = .{},...@@ -5,6 +5,8 @@ items: std.MultiArrayList(Item) = .{},
5extra: std.ArrayListUnmanaged(u32) = .{},5extra: std.ArrayListUnmanaged(u32) = .{},
6/// On 32-bit systems, this array is ignored and extra is used for everything.6/// On 32-bit systems, this array is ignored and extra is used for everything.
7/// On 64-bit systems, this array is used for big integers and associated metadata.7/// On 64-bit systems, this array is used for big integers and associated metadata.
8/// Use the helper methods instead of accessing this directly in order to not
9/// violate the above mechanism.
8limbs: std.ArrayListUnmanaged(u64) = .{},10limbs: std.ArrayListUnmanaged(u64) = .{},
911
10const std = @import("std");12const std = @import("std");
...@@ -12,6 +14,7 @@ const Allocator = std.mem.Allocator;...@@ -12,6 +14,7 @@ const Allocator = std.mem.Allocator;
12const assert = std.debug.assert;14const assert = std.debug.assert;
13const BigIntConst = std.math.big.int.Const;15const BigIntConst = std.math.big.int.Const;
14const BigIntMutable = std.math.big.int.Mutable;16const BigIntMutable = std.math.big.int.Mutable;
17const Limb = std.math.big.Limb;
1518
16const InternPool = @This();19const InternPool = @This();
17const DeclIndex = enum(u32) { _ };20const DeclIndex = enum(u32) { _ };
...@@ -233,9 +236,23 @@ pub const Key = union(enum) {...@@ -233,9 +236,23 @@ pub const Key = union(enum) {
233236
234 .int => |a_info| {237 .int => |a_info| {
235 const b_info = b.int;238 const b_info = b.int;
236 _ = a_info;239 return switch (a_info.storage) {
237 _ = b_info;240 .u64 => |aa| switch (b_info.storage) {
238 @panic("TODO");241 .u64 => |bb| aa == bb,
242 .i64 => |bb| aa == bb,
243 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq,
244 },
245 .i64 => |aa| switch (b_info.storage) {
246 .u64 => |bb| aa == bb,
247 .i64 => |bb| aa == bb,
248 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq,
249 },
250 .big_int => |aa| switch (b_info.storage) {
251 .u64 => |bb| aa.orderAgainstScalar(bb) == .eq,
252 .i64 => |bb| aa.orderAgainstScalar(bb) == .eq,
253 .big_int => |bb| aa.eq(bb),
254 },
255 };
239 },256 },
240257
241 .enum_tag => |a_info| {258 .enum_tag => |a_info| {
...@@ -1056,8 +1073,8 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -1056,8 +1073,8 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
1056 .ty = .comptime_int_type,1073 .ty = .comptime_int_type,
1057 .storage = .{ .i64 = @bitCast(i32, data) },1074 .storage = .{ .i64 = @bitCast(i32, data) },
1058 } },1075 } },
1059 .int_positive => @panic("TODO"),1076 .int_positive => indexToKeyBigInt(ip, data, true),
1060 .int_negative => @panic("TODO"),1077 .int_negative => indexToKeyBigInt(ip, data, false),
1061 .enum_tag_positive => @panic("TODO"),1078 .enum_tag_positive => @panic("TODO"),
1062 .enum_tag_negative => @panic("TODO"),1079 .enum_tag_negative => @panic("TODO"),
1063 .float_f32 => @panic("TODO"),1080 .float_f32 => @panic("TODO"),
...@@ -1068,6 +1085,17 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -1068,6 +1085,17 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
1068 };1085 };
1069}1086}
10701087
1088fn indexToKeyBigInt(ip: InternPool, limb_index: u32, positive: bool) Key {
1089 const int_info = ip.limbData(Int, limb_index);
1090 return .{ .int = .{
1091 .ty = int_info.ty,
1092 .storage = .{ .big_int = .{
1093 .limbs = ip.limbSlice(Int, limb_index, int_info.limbs_len),
1094 .positive = positive,
1095 } },
1096 } };
1097}
1098
1071pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {1099pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
1072 const adapter: KeyAdapter = .{ .intern_pool = ip };1100 const adapter: KeyAdapter = .{ .intern_pool = ip };
1073 const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);1101 const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);
...@@ -1293,7 +1321,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -1293,7 +1321,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
1293 try addInt(ip, gpa, int.ty, tag, big_int.limbs);1321 try addInt(ip, gpa, int.ty, tag, big_int.limbs);
1294 },1322 },
1295 inline .i64, .u64 => |x| {1323 inline .i64, .u64 => |x| {
1296 var buf: [2]usize = undefined;1324 var buf: [2]Limb = undefined;
1297 const big_int = BigIntMutable.init(&buf, x).toConst();1325 const big_int = BigIntMutable.init(&buf, x).toConst();
1298 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;1326 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;
1299 try addInt(ip, gpa, int.ty, tag, big_int.limbs);1327 try addInt(ip, gpa, int.ty, tag, big_int.limbs);
...@@ -1324,7 +1352,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -1324,7 +1352,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
1324 return @intToEnum(Index, ip.items.len - 1);1352 return @intToEnum(Index, ip.items.len - 1);
1325}1353}
13261354
1327fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const usize) !void {1355fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void {
1328 const limbs_len = @intCast(u32, limbs.len);1356 const limbs_len = @intCast(u32, limbs.len);
1329 try ip.reserveLimbs(gpa, @typeInfo(Int).Struct.fields.len + limbs_len);1357 try ip.reserveLimbs(gpa, @typeInfo(Int).Struct.fields.len + limbs_len);
1330 ip.items.appendAssumeCapacity(.{1358 ip.items.appendAssumeCapacity(.{
...@@ -1360,7 +1388,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {...@@ -1360,7 +1388,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
1360}1388}
13611389
1362fn reserveLimbs(ip: *InternPool, gpa: Allocator, n: usize) !void {1390fn reserveLimbs(ip: *InternPool, gpa: Allocator, n: usize) !void {
1363 switch (@sizeOf(usize)) {1391 switch (@sizeOf(Limb)) {
1364 @sizeOf(u32) => try ip.extra.ensureUnusedCapacity(gpa, n),1392 @sizeOf(u32) => try ip.extra.ensureUnusedCapacity(gpa, n),
1365 @sizeOf(u64) => try ip.limbs.ensureUnusedCapacity(gpa, n),1393 @sizeOf(u64) => try ip.limbs.ensureUnusedCapacity(gpa, n),
1366 else => @compileError("unsupported host"),1394 else => @compileError("unsupported host"),
...@@ -1368,7 +1396,7 @@ fn reserveLimbs(ip: *InternPool, gpa: Allocator, n: usize) !void {...@@ -1368,7 +1396,7 @@ fn reserveLimbs(ip: *InternPool, gpa: Allocator, n: usize) !void {
1368}1396}
13691397
1370fn addLimbsExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {1398fn addLimbsExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
1371 switch (@sizeOf(usize)) {1399 switch (@sizeOf(Limb)) {
1372 @sizeOf(u32) => return addExtraAssumeCapacity(ip, extra),1400 @sizeOf(u32) => return addExtraAssumeCapacity(ip, extra),
1373 @sizeOf(u64) => {},1401 @sizeOf(u64) => {},
1374 else => @compileError("unsupported host"),1402 else => @compileError("unsupported host"),
...@@ -1389,8 +1417,8 @@ fn addLimbsExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {...@@ -1389,8 +1417,8 @@ fn addLimbsExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
1389 return result;1417 return result;
1390}1418}
13911419
1392fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const usize) void {1420fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const Limb) void {
1393 switch (@sizeOf(usize)) {1421 switch (@sizeOf(Limb)) {
1394 @sizeOf(u32) => ip.extra.appendSliceAssumeCapacity(limbs),1422 @sizeOf(u32) => ip.extra.appendSliceAssumeCapacity(limbs),
1395 @sizeOf(u64) => ip.limbs.appendSliceAssumeCapacity(limbs),1423 @sizeOf(u64) => ip.limbs.appendSliceAssumeCapacity(limbs),
1396 else => @compileError("unsupported host"),1424 else => @compileError("unsupported host"),
...@@ -1416,7 +1444,7 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T {...@@ -1416,7 +1444,7 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T {
14161444
1417/// Asserts the struct has 32-bit fields and the number of fields is evenly divisible by 2.1445/// Asserts the struct has 32-bit fields and the number of fields is evenly divisible by 2.
1418fn limbData(ip: InternPool, comptime T: type, index: usize) T {1446fn limbData(ip: InternPool, comptime T: type, index: usize) T {
1419 switch (@sizeOf(usize)) {1447 switch (@sizeOf(Limb)) {
1420 @sizeOf(u32) => return extraData(ip, T, index),1448 @sizeOf(u32) => return extraData(ip, T, index),
1421 @sizeOf(u64) => {},1449 @sizeOf(u64) => {},
1422 else => @compileError("unsupported host"),1450 else => @compileError("unsupported host"),
...@@ -1438,6 +1466,21 @@ fn limbData(ip: InternPool, comptime T: type, index: usize) T {...@@ -1438,6 +1466,21 @@ fn limbData(ip: InternPool, comptime T: type, index: usize) T {
1438 return result;1466 return result;
1439}1467}
14401468
1469fn limbSlice(ip: InternPool, comptime S: type, limb_index: u32, len: u32) []const Limb {
1470 const field_count = @typeInfo(S).Struct.fields.len;
1471 switch (@sizeOf(Limb)) {
1472 @sizeOf(u32) => {
1473 const start = limb_index + field_count;
1474 return ip.extra.items[start..][0..len];
1475 },
1476 @sizeOf(u64) => {
1477 const start = limb_index + @divExact(field_count, 2);
1478 return ip.limbs.items[start..][0..len];
1479 },
1480 else => @compileError("unsupported host"),
1481 }
1482}
1483
1441test "basic usage" {1484test "basic usage" {
1442 const gpa = std.testing.allocator;1485 const gpa = std.testing.allocator;
14431486