authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-07 12:53:14-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:42:29-07:00
log4c3c605e5f53c91430efac821ce1b863cbb5bf06
tree14ec529e00b720650b3531c6defa9fc3c03e73f0
parentc1ca16d779a3f3201a5a35a88eff188290b2091a

InternPool: add getCoercedInt to avoid copy in Sema


2 files changed, 21 insertions(+), 14 deletions(-)

src/InternPool.zig+20
...@@ -1535,6 +1535,26 @@ pub fn slicePtrType(ip: InternPool, i: Index) Index {...@@ -1535,6 +1535,26 @@ pub fn slicePtrType(ip: InternPool, i: Index) Index {
1535 }1535 }
1536}1536}
15371537
1538/// Given an existing integer value, returns the same numerical value but with
1539/// the supplied type.
1540pub fn getCoercedInt(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
1541 const key = ip.indexToKey(val);
1542 // The key cannot be passed directly to `get`, otherwise in the case of
1543 // big_int storage, the limbs would be invalidated before they are read.
1544 // Here we pre-reserve the limbs to ensure that the logic in `addInt` will
1545 // not use an invalidated limbs pointer.
1546 switch (key.int.storage) {
1547 .u64, .i64 => {},
1548 .big_int => |big_int| {
1549 try reserveLimbs(ip, gpa, @typeInfo(Int).Struct.fields.len + big_int.limbs.len);
1550 },
1551 }
1552 return ip.get(gpa, .{ .int = .{
1553 .ty = new_ty,
1554 .storage = key.int.storage,
1555 } });
1556}
1557
1538pub fn dump(ip: InternPool) void {1558pub fn dump(ip: InternPool) void {
1539 dumpFallible(ip, std.heap.page_allocator) catch return;1559 dumpFallible(ip, std.heap.page_allocator) catch return;
1540}1560}
src/Sema.zig+1-14
...@@ -25957,20 +25957,7 @@ fn coerceExtra(...@@ -25957,20 +25957,7 @@ fn coerceExtra(
25957 if (!opts.report_err) return error.NotCoercible;25957 if (!opts.report_err) return error.NotCoercible;
25958 return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(sema.mod), val.fmtValue(inst_ty, sema.mod) });25958 return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(sema.mod), val.fmtValue(inst_ty, sema.mod) });
25959 }25959 }
25960 const key = mod.intern_pool.indexToKey(val.ip_index);25960 const new_val = try mod.intern_pool.getCoercedInt(sema.gpa, val.ip_index, dest_ty.ip_index);
25961 // If the int is represented as a bigint, copy it so we can safely pass it to `mod.intern`
25962 const int_storage: InternPool.Key.Int.Storage = switch (key.int.storage) {
25963 .u64 => |x| .{ .u64 = x },
25964 .i64 => |x| .{ .i64 = x },
25965 .big_int => |big_int| .{ .big_int = .{
25966 .limbs = try sema.arena.dupe(std.math.big.Limb, big_int.limbs),
25967 .positive = big_int.positive,
25968 } },
25969 };
25970 const new_val = try mod.intern(.{ .int = .{
25971 .ty = dest_ty.ip_index,
25972 .storage = int_storage,
25973 } });
25974 return try sema.addConstant(dest_ty, new_val.toValue());25961 return try sema.addConstant(dest_ty, new_val.toValue());
25975 }25962 }
25976 if (dest_ty.zigTypeTag(mod) == .ComptimeInt) {25963 if (dest_ty.zigTypeTag(mod) == .ComptimeInt) {