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(...@@ -22472,9 +22472,7 @@ fn analyzeMinMax(
22472 if (std.debug.runtime_safety) {22472 if (std.debug.runtime_safety) {
22473 assert(try sema.intFitsInType(val, refined_ty, null));22473 assert(try sema.intFitsInType(val, refined_ty, null));
22474 }22474 }
22475 cur_minmax = try sema.addConstant(refined_ty, (try sema.resolveMaybeUndefVal(22475 cur_minmax = try sema.coerceInMemory(block, val, orig_ty, refined_ty, src);
22476 try sema.coerceInMemory(block, val, orig_ty, refined_ty, src),
22477 )).?);
22478 }22476 }
2247922477
22480 break :refined refined_ty;22478 break :refined refined_ty;
...@@ -26659,16 +26657,16 @@ fn coerceExtra(...@@ -26659,16 +26657,16 @@ fn coerceExtra(
26659 return sema.failWithOwnedErrorMsg(msg);26657 return sema.failWithOwnedErrorMsg(msg);
26660}26658}
2666126659
26662fn coerceInMemory(26660fn coerceValueInMemory(
26663 sema: *Sema,26661 sema: *Sema,
26664 block: *Block,26662 block: *Block,
26665 val: Value,26663 val: Value,
26666 src_ty: Type,26664 src_ty: Type,
26667 dst_ty: Type,26665 dst_ty: Type,
26668 dst_ty_src: LazySrcLoc,26666 dst_ty_src: LazySrcLoc,
26669) CompileError!Air.Inst.Ref {26667) CompileError!Value {
26670 const mod = sema.mod;26668 const mod = sema.mod;
26671 switch (mod.intern_pool.indexToKey(val.toIntern())) {26669 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
26672 .aggregate => |aggregate| {26670 .aggregate => |aggregate| {
26673 const dst_ty_key = mod.intern_pool.indexToKey(dst_ty.toIntern());26671 const dst_ty_key = mod.intern_pool.indexToKey(dst_ty.toIntern());
26674 const dest_len = try sema.usizeCast(26672 const dest_len = try sema.usizeCast(
...@@ -26688,14 +26686,14 @@ fn coerceInMemory(...@@ -26688,14 +26686,14 @@ fn coerceInMemory(
26688 else => unreachable,26686 else => unreachable,
26689 };26687 };
26690 if (src_ty_child != dst_ty_child) break :direct;26688 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 = .{
26692 .ty = dst_ty.toIntern(),26690 .ty = dst_ty.toIntern(),
26693 .storage = switch (aggregate.storage) {26691 .storage = switch (aggregate.storage) {
26694 .bytes => |bytes| .{ .bytes = bytes[0..dest_len] },26692 .bytes => |bytes| .{ .bytes = bytes[0..dest_len] },
26695 .elems => |elems| .{ .elems = elems[0..dest_len] },26693 .elems => |elems| .{ .elems = elems[0..dest_len] },
26696 .repeated_elem => |elem| .{ .repeated_elem = elem },26694 .repeated_elem => |elem| .{ .repeated_elem = elem },
26697 },26695 },
26698 } })).toValue());26696 } })).toValue();
26699 }26697 }
26700 const dest_elems = try sema.arena.alloc(InternPool.Index, dest_len);26698 const dest_elems = try sema.arena.alloc(InternPool.Index, dest_len);
26701 for (dest_elems, 0..) |*dest_elem, i| {26699 for (dest_elems, 0..) |*dest_elem, i| {
...@@ -26712,17 +26710,28 @@ fn coerceInMemory(...@@ -26712,17 +26710,28 @@ fn coerceInMemory(
26712 .repeated_elem => |elem| elem,26710 .repeated_elem => |elem| elem,
26713 }, elem_ty);26711 }, elem_ty);
26714 }26712 }
26715 return sema.addConstant(dst_ty, (try mod.intern(.{ .aggregate = .{26713 return (try mod.intern(.{ .aggregate = .{
26716 .ty = dst_ty.toIntern(),26714 .ty = dst_ty.toIntern(),
26717 .storage = .{ .elems = dest_elems },26715 .storage = .{ .elems = dest_elems },
26718 } })).toValue());26716 } })).toValue();
26719 },26717 },
26720 .float => |float| return sema.addConstant(dst_ty, (try mod.intern(.{ .float = .{26718 .float => |float| (try mod.intern(.{ .float = .{
26721 .ty = dst_ty.toIntern(),26719 .ty = dst_ty.toIntern(),
26722 .storage = float.storage,26720 .storage = float.storage,
26723 } })).toValue()),26721 } })).toValue(),
26724 else => return sema.addConstant(dst_ty, try mod.getCoerced(val, dst_ty)),26722 else => try mod.getCoerced(val, dst_ty),
26725 }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));
26726}26735}
2672726736
26728const InMemoryCoercionResult = union(enum) {26737const InMemoryCoercionResult = union(enum) {
...@@ -33935,8 +33944,11 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value...@@ -33935,8 +33944,11 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value
33935 if (coerce_in_mem_ok) {33944 if (coerce_in_mem_ok) {
33936 // We have a Value that lines up in virtual memory exactly with what we want to load,33945 // We have a Value that lines up in virtual memory exactly with what we want to load,
33937 // and it is in-memory coercible to load_ty. It may be returned without modifications.33946 // 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.33947 // Move mutable decl values to the InternPool and assert other decls are already in
33939 return .{ .val = (if (deref.is_mutable) try tv.val.intern(tv.ty, mod) else tv.val.toIntern()).toValue() };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 };
33940 }33952 }
33941 }33953 }
3394233954
src/value.zig+1
...@@ -1842,6 +1842,7 @@ pub const Value = struct {...@@ -1842,6 +1842,7 @@ pub const Value = struct {
1842 pub fn elemValue(val: Value, mod: *Module, index: usize) Allocator.Error!Value {1842 pub fn elemValue(val: Value, mod: *Module, index: usize) Allocator.Error!Value {
1843 return switch (val.ip_index) {1843 return switch (val.ip_index) {
1844 .none => switch (val.tag()) {1844 .none => switch (val.tag()) {
1845 .bytes => try mod.intValue(Type.u8, val.castTag(.bytes).?.data[index]),
1845 .repeated => val.castTag(.repeated).?.data,1846 .repeated => val.castTag(.repeated).?.data,
1846 .aggregate => val.castTag(.aggregate).?.data[index],1847 .aggregate => val.castTag(.aggregate).?.data[index],
1847 .slice => val.castTag(.slice).?.data.ptr.elemValue(mod, index),1848 .slice => val.castTag(.slice).?.data.ptr.elemValue(mod, index),