| author | |
| committer | |
| log | 4c3c605e5f53c91430efac821ce1b863cbb5bf06 |
| tree | 14ec529e00b720650b3531c6defa9fc3c03e73f0 |
| parent | c1ca16d779a3f3201a5a35a88eff188290b2091a |
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 | } |
| 1537 | 1537 | ||
| 1538 | /// Given an existing integer value, returns the same numerical value but with | ||
| 1539 | /// the supplied type. | ||
| 1540 | pub 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 | |||
| 1538 | pub fn dump(ip: InternPool) void { | 1558 | pub 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) { |