authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-23 15:10:18-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-25 11:23:41-07:00
log482a0f648c90e8a61dac3a95313e0519bc5f4b5f
tree967a2952ea15e6d543224f64ad7b61a9828a6787
parent83a7303bbf92fcada2e61f2906f84ccf53e50ff0

Sema: implement comptime `@memcpy`


2 files changed, 37 insertions(+), 6 deletions(-)

src/Sema.zig+36-4
......@@ -21828,6 +21828,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2182821828 const src_ptr = try sema.resolveInst(extra.rhs);
2182921829 const dest_len = try indexablePtrLenOrNone(sema, block, dest_src, dest_ptr);
2183021830 const src_len = try indexablePtrLenOrNone(sema, block, src_src, src_ptr);
21831 const target = sema.mod.getTarget();
2183121832
2183221833 if (dest_len == .none and src_len == .none) {
2183321834 const msg = msg: {
......@@ -21879,9 +21880,41 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2187921880
2188021881 const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: {
2188121882 if (!dest_ptr_val.isComptimeMutablePtr()) break :rs dest_src;
21882 if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |src_ptr_val| {
21883 _ = src_ptr_val;
21884 return sema.fail(block, src, "TODO: @memcpy at comptime", .{});
21883 if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |_| {
21884 const len_u64 = (try len_val.?.getUnsignedIntAdvanced(target, sema)).?;
21885 const len = try sema.usizeCast(block, dest_src, len_u64);
21886 for (0..len) |i| {
21887 const elem_index = try sema.addIntUnsigned(Type.usize, i);
21888 const dest_elem_ptr = try sema.elemPtr(
21889 block,
21890 src,
21891 dest_ptr,
21892 elem_index,
21893 src,
21894 true, // init
21895 false, // oob_safety
21896 );
21897 const src_elem_ptr = try sema.elemPtr(
21898 block,
21899 src,
21900 src_ptr,
21901 elem_index,
21902 src,
21903 false, // init
21904 false, // oob_safety
21905 );
21906 const uncoerced_elem = try sema.analyzeLoad(block, src, src_elem_ptr, src_src);
21907 try sema.storePtr2(
21908 block,
21909 src,
21910 dest_elem_ptr,
21911 dest_src,
21912 uncoerced_elem,
21913 src_src,
21914 .store,
21915 );
21916 }
21917 return;
2188521918 } else break :rs src_src;
2188621919 } else dest_src;
2188721920
......@@ -21902,7 +21935,6 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2190221935
2190321936 const dest_elem_ty = dest_ty.elemType2();
2190421937 const src_elem_ty = src_ty.elemType2();
21905 const target = sema.mod.getTarget();
2190621938 if (.ok != try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, true, target, dest_src, src_src)) {
2190721939 return sema.fail(block, src, "TODO: lower @memcpy to a for loop because the element types have different ABI sizes", .{});
2190821940 }
test/behavior/basic.zig+1-2
......@@ -387,8 +387,7 @@ test "memcpy and memset intrinsics" {
387387 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
388388
389389 try testMemcpyMemset();
390 // TODO add comptime test coverage
391 //comptime try testMemcpyMemset();
390 try comptime testMemcpyMemset();
392391}
393392
394393fn testMemcpyMemset() !void {