authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-06-01 21:03:53-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:58-07:00
loge8bcdca044603fb5ea93fc94028dfd8bdd22fcf3
treefb7beba9bb2b2264b94369d7be9ad058462ae537
parentdc18739a738adc7fd549f9d43db2314275c51c03

Sema: fix in-memory coercion during comptime load


2 files changed, 29 insertions(+), 16 deletions(-)

src/Sema.zig+28-16
......@@ -22472,9 +22472,7 @@ fn analyzeMinMax(
2247222472 if (std.debug.runtime_safety) {
2247322473 assert(try sema.intFitsInType(val, refined_ty, null));
2247422474 }
22475 cur_minmax = try sema.addConstant(refined_ty, (try sema.resolveMaybeUndefVal(
22476 try sema.coerceInMemory(block, val, orig_ty, refined_ty, src),
22477 )).?);
22475 cur_minmax = try sema.coerceInMemory(block, val, orig_ty, refined_ty, src);
2247822476 }
2247922477
2248022478 break :refined refined_ty;
......@@ -26659,16 +26657,16 @@ fn coerceExtra(
2665926657 return sema.failWithOwnedErrorMsg(msg);
2666026658}
2666126659
26662fn coerceInMemory(
26660fn coerceValueInMemory(
2666326661 sema: *Sema,
2666426662 block: *Block,
2666526663 val: Value,
2666626664 src_ty: Type,
2666726665 dst_ty: Type,
2666826666 dst_ty_src: LazySrcLoc,
26669) CompileError!Air.Inst.Ref {
26667) CompileError!Value {
2667026668 const mod = sema.mod;
26671 switch (mod.intern_pool.indexToKey(val.toIntern())) {
26669 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2667226670 .aggregate => |aggregate| {
2667326671 const dst_ty_key = mod.intern_pool.indexToKey(dst_ty.toIntern());
2667426672 const dest_len = try sema.usizeCast(
......@@ -26688,14 +26686,14 @@ fn coerceInMemory(
2668826686 else => unreachable,
2668926687 };
2669026688 if (src_ty_child != dst_ty_child) break :direct;
26691 return try sema.addConstant(dst_ty, (try mod.intern(.{ .aggregate = .{
26689 return (try mod.intern(.{ .aggregate = .{
2669226690 .ty = dst_ty.toIntern(),
2669326691 .storage = switch (aggregate.storage) {
2669426692 .bytes => |bytes| .{ .bytes = bytes[0..dest_len] },
2669526693 .elems => |elems| .{ .elems = elems[0..dest_len] },
2669626694 .repeated_elem => |elem| .{ .repeated_elem = elem },
2669726695 },
26698 } })).toValue());
26696 } })).toValue();
2669926697 }
2670026698 const dest_elems = try sema.arena.alloc(InternPool.Index, dest_len);
2670126699 for (dest_elems, 0..) |*dest_elem, i| {
......@@ -26712,17 +26710,28 @@ fn coerceInMemory(
2671226710 .repeated_elem => |elem| elem,
2671326711 }, elem_ty);
2671426712 }
26715 return sema.addConstant(dst_ty, (try mod.intern(.{ .aggregate = .{
26713 return (try mod.intern(.{ .aggregate = .{
2671626714 .ty = dst_ty.toIntern(),
2671726715 .storage = .{ .elems = dest_elems },
26718 } })).toValue());
26716 } })).toValue();
2671926717 },
26720 .float => |float| return sema.addConstant(dst_ty, (try mod.intern(.{ .float = .{
26718 .float => |float| (try mod.intern(.{ .float = .{
2672126719 .ty = dst_ty.toIntern(),
2672226720 .storage = float.storage,
26723 } })).toValue()),
26724 else => return sema.addConstant(dst_ty, try mod.getCoerced(val, dst_ty)),
26725 }
26721 } })).toValue(),
26722 else => try mod.getCoerced(val, dst_ty),
26723 };
26724}
26725
26726fn coerceInMemory(
26727 sema: *Sema,
26728 block: *Block,
26729 val: Value,
26730 src_ty: Type,
26731 dst_ty: Type,
26732 dst_ty_src: LazySrcLoc,
26733) CompileError!Air.Inst.Ref {
26734 return sema.addConstant(dst_ty, try sema.coerceValueInMemory(block, val, src_ty, dst_ty, dst_ty_src));
2672626735}
2672726736
2672826737const InMemoryCoercionResult = union(enum) {
......@@ -33935,8 +33944,11 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value
3393533944 if (coerce_in_mem_ok) {
3393633945 // We have a Value that lines up in virtual memory exactly with what we want to load,
3393733946 // and it is in-memory coercible to load_ty. It may be returned without modifications.
33938 // Move mutable decl values to the InternPool and assert other decls are already in the InternPool.
33939 return .{ .val = (if (deref.is_mutable) try tv.val.intern(tv.ty, mod) else tv.val.toIntern()).toValue() };
33947 // Move mutable decl values to the InternPool and assert other decls are already in
33948 // the InternPool.
33949 const uncoerced_val = if (deref.is_mutable) try tv.val.intern(tv.ty, mod) else tv.val.toIntern();
33950 const coerced_val = try sema.coerceValueInMemory(block, uncoerced_val.toValue(), tv.ty, load_ty, src);
33951 return .{ .val = coerced_val };
3394033952 }
3394133953 }
3394233954
src/value.zig+1
......@@ -1842,6 +1842,7 @@ pub const Value = struct {
18421842 pub fn elemValue(val: Value, mod: *Module, index: usize) Allocator.Error!Value {
18431843 return switch (val.ip_index) {
18441844 .none => switch (val.tag()) {
1845 .bytes => try mod.intValue(Type.u8, val.castTag(.bytes).?.data[index]),
18451846 .repeated => val.castTag(.repeated).?.data,
18461847 .aggregate => val.castTag(.aggregate).?.data[index],
18471848 .slice => val.castTag(.slice).?.data.ptr.elemValue(mod, index),