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) = .{},
55extra: std.ArrayListUnmanaged(u32) = .{},
66/// On 32-bit systems, this array is ignored and extra is used for everything.
77/// 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.
810limbs: std.ArrayListUnmanaged(u64) = .{},
911
1012const std = @import("std");
......@@ -12,6 +14,7 @@ const Allocator = std.mem.Allocator;
1214const assert = std.debug.assert;
1315const BigIntConst = std.math.big.int.Const;
1416const BigIntMutable = std.math.big.int.Mutable;
17const Limb = std.math.big.Limb;
1518
1619const InternPool = @This();
1720const DeclIndex = enum(u32) { _ };
......@@ -233,9 +236,23 @@ pub const Key = union(enum) {
233236
234237 .int => |a_info| {
235238 const b_info = b.int;
236 _ = a_info;
237 _ = b_info;
238 @panic("TODO");
239 return switch (a_info.storage) {
240 .u64 => |aa| switch (b_info.storage) {
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 };
239256 },
240257
241258 .enum_tag => |a_info| {
......@@ -1056,8 +1073,8 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
10561073 .ty = .comptime_int_type,
10571074 .storage = .{ .i64 = @bitCast(i32, data) },
10581075 } },
1059 .int_positive => @panic("TODO"),
1060 .int_negative => @panic("TODO"),
1076 .int_positive => indexToKeyBigInt(ip, data, true),
1077 .int_negative => indexToKeyBigInt(ip, data, false),
10611078 .enum_tag_positive => @panic("TODO"),
10621079 .enum_tag_negative => @panic("TODO"),
10631080 .float_f32 => @panic("TODO"),
......@@ -1068,6 +1085,17 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
10681085 };
10691086}
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
10711099pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
10721100 const adapter: KeyAdapter = .{ .intern_pool = ip };
10731101 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 {
12931321 try addInt(ip, gpa, int.ty, tag, big_int.limbs);
12941322 },
12951323 inline .i64, .u64 => |x| {
1296 var buf: [2]usize = undefined;
1324 var buf: [2]Limb = undefined;
12971325 const big_int = BigIntMutable.init(&buf, x).toConst();
12981326 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;
12991327 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 {
13241352 return @intToEnum(Index, ip.items.len - 1);
13251353}
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 {
13281356 const limbs_len = @intCast(u32, limbs.len);
13291357 try ip.reserveLimbs(gpa, @typeInfo(Int).Struct.fields.len + limbs_len);
13301358 ip.items.appendAssumeCapacity(.{
......@@ -1360,7 +1388,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
13601388}
13611389
13621390fn reserveLimbs(ip: *InternPool, gpa: Allocator, n: usize) !void {
1363 switch (@sizeOf(usize)) {
1391 switch (@sizeOf(Limb)) {
13641392 @sizeOf(u32) => try ip.extra.ensureUnusedCapacity(gpa, n),
13651393 @sizeOf(u64) => try ip.limbs.ensureUnusedCapacity(gpa, n),
13661394 else => @compileError("unsupported host"),
......@@ -1368,7 +1396,7 @@ fn reserveLimbs(ip: *InternPool, gpa: Allocator, n: usize) !void {
13681396}
13691397
13701398fn addLimbsExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
1371 switch (@sizeOf(usize)) {
1399 switch (@sizeOf(Limb)) {
13721400 @sizeOf(u32) => return addExtraAssumeCapacity(ip, extra),
13731401 @sizeOf(u64) => {},
13741402 else => @compileError("unsupported host"),
......@@ -1389,8 +1417,8 @@ fn addLimbsExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
13891417 return result;
13901418}
13911419
1392fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const usize) void {
1393 switch (@sizeOf(usize)) {
1420fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const Limb) void {
1421 switch (@sizeOf(Limb)) {
13941422 @sizeOf(u32) => ip.extra.appendSliceAssumeCapacity(limbs),
13951423 @sizeOf(u64) => ip.limbs.appendSliceAssumeCapacity(limbs),
13961424 else => @compileError("unsupported host"),
......@@ -1416,7 +1444,7 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T {
14161444
14171445/// Asserts the struct has 32-bit fields and the number of fields is evenly divisible by 2.
14181446fn limbData(ip: InternPool, comptime T: type, index: usize) T {
1419 switch (@sizeOf(usize)) {
1447 switch (@sizeOf(Limb)) {
14201448 @sizeOf(u32) => return extraData(ip, T, index),
14211449 @sizeOf(u64) => {},
14221450 else => @compileError("unsupported host"),
......@@ -1438,6 +1466,21 @@ fn limbData(ip: InternPool, comptime T: type, index: usize) T {
14381466 return result;
14391467}
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
14411484test "basic usage" {
14421485 const gpa = std.testing.allocator;
14431486