authorgravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2025-01-23 00:13:23+11:00
committergravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2025-04-26 13:34:16+10:00
log898ca824585e78306bb0137dbae1fbf859b762b6
tree49934715689d33a7544b56e229e42b0d2e2063ef
parentb9f440620d969204e8196ae6c226f939eb194d5e

compiler: add @memmove builtin


29 files changed, 215 insertions(+), 14 deletions(-)

lib/std/debug.zig+4
......@@ -134,6 +134,10 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type {
134134 @branchHint(.cold);
135135 call("@memcpy arguments alias", @returnAddress());
136136 }
137 pub fn memmoveLenMismatch() noreturn {
138 @branchHint(.cold);
139 call("@memmove arguments have non-equal lengths", @returnAddress());
140 }
137141 pub fn noreturnReturned() noreturn {
138142 @branchHint(.cold);
139143 call("'noreturn' function returned", @returnAddress());
lib/std/debug/no_panic.zig+5
......@@ -135,6 +135,11 @@ pub fn memcpyAlias() noreturn {
135135 @trap();
136136}
137137
138pub fn memmoveLenMismatch() noreturn {
139 @branchHint(.cold);
140 @trap();
141}
142
138143pub fn noreturnReturned() noreturn {
139144 @branchHint(.cold);
140145 @trap();
lib/std/debug/simple_panic.zig+4
......@@ -128,6 +128,10 @@ pub fn memcpyAlias() noreturn {
128128 call("@memcpy arguments alias", null);
129129}
130130
131pub fn memmoveLenMismatch() noreturn {
132 call("@memmove arguments have non-equal lengths", null);
133}
134
131135pub fn noreturnReturned() noreturn {
132136 call("'noreturn' function returned", null);
133137}
lib/std/zig/AstGen.zig+8
......@@ -2919,6 +2919,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
29192919 .set_runtime_safety,
29202920 .memcpy,
29212921 .memset,
2922 .memmove,
29222923 .validate_deref,
29232924 .validate_destructure,
29242925 .save_err_ret_index,
......@@ -9717,6 +9718,13 @@ fn builtinCall(
97179718 });
97189719 return rvalue(gz, ri, .void_value, node);
97199720 },
9721 .memmove => {
9722 _ = try gz.addPlNode(.memmove, node, Zir.Inst.Bin{
9723 .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
9724 .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]),
9725 });
9726 return rvalue(gz, ri, .void_value, node);
9727 },
97209728 .shuffle => {
97219729 const result = try gz.addPlNode(.shuffle, node, Zir.Inst.Shuffle{
97229730 .elem_type = try typeExpr(gz, scope, params[0]),
lib/std/zig/AstRlAnnotate.zig+1-1
......@@ -1055,7 +1055,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
10551055 _ = try astrl.expr(args[2], block, ResultInfo.none);
10561056 return false;
10571057 },
1058 .memcpy => {
1058 .memcpy, .memmove => {
10591059 _ = try astrl.expr(args[0], block, ResultInfo.none);
10601060 _ = try astrl.expr(args[1], block, ResultInfo.none);
10611061 return false;
lib/std/zig/BuiltinFn.zig+8
......@@ -68,6 +68,7 @@ pub const Tag = enum {
6868 max,
6969 memcpy,
7070 memset,
71 memmove,
7172 min,
7273 wasm_memory_size,
7374 wasm_memory_grow,
......@@ -641,6 +642,13 @@ pub const list = list: {
641642 .param_count = 2,
642643 },
643644 },
645 .{
646 "@memmove",
647 .{
648 .tag = .memmove,
649 .param_count = 2,
650 },
651 },
644652 .{
645653 "@min",
646654 .{
lib/std/zig/Zir.zig+7
......@@ -986,6 +986,9 @@ pub const Inst = struct {
986986 /// Implements the `@memset` builtin.
987987 /// Uses the `pl_node` union field with payload `Bin`.
988988 memset,
989 /// Implements the `@memmove` builtin.
990 /// Uses the `pl_node` union field with payload `Bin`.
991 memmove,
989992 /// Implements the `@min` builtin for 2 args.
990993 /// Uses the `pl_node` union field with payload `Bin`
991994 min,
......@@ -1272,6 +1275,7 @@ pub const Inst = struct {
12721275 .max,
12731276 .memcpy,
12741277 .memset,
1278 .memmove,
12751279 .min,
12761280 .c_import,
12771281 .@"resume",
......@@ -1355,6 +1359,7 @@ pub const Inst = struct {
13551359 .set_runtime_safety,
13561360 .memcpy,
13571361 .memset,
1362 .memmove,
13581363 .check_comptime_control_flow,
13591364 .@"defer",
13601365 .defer_err_code,
......@@ -1832,6 +1837,7 @@ pub const Inst = struct {
18321837 .max = .pl_node,
18331838 .memcpy = .pl_node,
18341839 .memset = .pl_node,
1840 .memmove = .pl_node,
18351841 .min = .pl_node,
18361842 .c_import = .pl_node,
18371843
......@@ -4291,6 +4297,7 @@ fn findTrackableInner(
42914297 .mul_add,
42924298 .memcpy,
42934299 .memset,
4300 .memmove,
42944301 .min,
42954302 .max,
42964303 .alloc,
lib/std/zig/llvm/Builder.zig+30
......@@ -6125,6 +6125,36 @@ pub const WipFunction = struct {
61256125 return value.unwrap().instruction;
61266126 }
61276127
6128 pub fn callMemMove(
6129 self: *WipFunction,
6130 dst: Value,
6131 dst_align: Alignment,
6132 src: Value,
6133 src_align: Alignment,
6134 len: Value,
6135 kind: MemoryAccessKind,
6136 ) Allocator.Error!Instruction.Index {
6137 var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })};
6138 var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = src_align })};
6139 const value = try self.callIntrinsic(
6140 .normal,
6141 try self.builder.fnAttrs(&.{
6142 .none,
6143 .none,
6144 try self.builder.attrs(&dst_attrs),
6145 try self.builder.attrs(&src_attrs),
6146 }),
6147 .memmove,
6148 &.{ dst.typeOfWip(self), src.typeOfWip(self), len.typeOfWip(self) },
6149 &.{ dst, src, len, switch (kind) {
6150 .normal => Value.false,
6151 .@"volatile" => Value.true,
6152 } },
6153 undefined,
6154 );
6155 return value.unwrap().instruction;
6156 }
6157
61286158 pub fn callMemSet(
61296159 self: *WipFunction,
61306160 dst: Value,
lib/zig.h+1
......@@ -481,6 +481,7 @@
481481
482482zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t);
483483zig_extern void *memset (void *, int, size_t);
484zig_extern void *memmove (void *, void const *, size_t);
484485
485486/* ================ Bool and 8/16/32/64-bit Integer Support ================= */
486487
src/Air.zig+14
......@@ -730,6 +730,18 @@ pub const Inst = struct {
730730 /// source being a pointer-to-array), then it is guaranteed to be
731731 /// greater than zero.
732732 memcpy,
733 /// Given dest pointer and source pointer, copy elements from source to dest.
734 /// Dest pointer is either a slice or a pointer to array.
735 /// The dest element type may be any type.
736 /// Source pointer must have same element type as dest element type.
737 /// Dest slice may have any alignment; source pointer may have any alignment.
738 /// The two memory regions may overlap.
739 /// Result type is always void.
740 /// Uses the `bin_op` field. LHS is the dest slice. RHS is the source pointer.
741 /// If the length is compile-time known (due to the destination or
742 /// source being a pointer-to-array), then it is guaranteed to be
743 /// greater than zero.
744 memmove,
733745
734746 /// Uses the `ty_pl` field with payload `Cmpxchg`.
735747 cmpxchg_weak,
......@@ -1533,6 +1545,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
15331545 .memset,
15341546 .memset_safe,
15351547 .memcpy,
1548 .memmove,
15361549 .set_union_tag,
15371550 .prefetch,
15381551 .set_err_return_trace,
......@@ -1696,6 +1709,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
16961709 .memset,
16971710 .memset_safe,
16981711 .memcpy,
1712 .memmove,
16991713 .cmpxchg_weak,
17001714 .cmpxchg_strong,
17011715 .atomic_store_unordered,
src/Air/types_resolved.zig+1
......@@ -83,6 +83,7 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool {
8383 .memset,
8484 .memset_safe,
8585 .memcpy,
86 .memmove,
8687 .atomic_store_unordered,
8788 .atomic_store_monotonic,
8889 .atomic_store_release,
src/Liveness.zig+2
......@@ -300,6 +300,7 @@ pub fn categorizeOperand(
300300 .memset,
301301 .memset_safe,
302302 .memcpy,
303 .memmove,
303304 => {
304305 const o = air_datas[@intFromEnum(inst)].bin_op;
305306 if (o.lhs == operand_ref) return matchOperandSmallIndex(l, inst, 0, .write);
......@@ -936,6 +937,7 @@ fn analyzeInst(
936937 .memset,
937938 .memset_safe,
938939 .memcpy,
940 .memmove,
939941 => {
940942 const o = inst_datas[@intFromEnum(inst)].bin_op;
941943 return analyzeOperands(a, pass, data, inst, .{ o.lhs, o.rhs, .none });
src/Liveness/Verify.zig+1
......@@ -267,6 +267,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
267267 .memset,
268268 .memset_safe,
269269 .memcpy,
270 .memmove,
270271 => {
271272 const bin_op = data[@intFromEnum(inst)].bin_op;
272273 try self.verifyInstOperands(inst, .{ bin_op.lhs, bin_op.rhs, .none });
src/Sema.zig+45-12
......@@ -1583,6 +1583,11 @@ fn analyzeBodyInner(
15831583 i += 1;
15841584 continue;
15851585 },
1586 .memmove => {
1587 try sema.zirMemmove(block, inst);
1588 i += 1;
1589 continue;
1590 },
15861591 .check_comptime_control_flow => {
15871592 if (!block.isComptime()) {
15881593 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
......@@ -25610,6 +25615,19 @@ fn upgradeToArrayPtr(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, len: u64) !A
2561025615}
2561125616
2561225617fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
25618 return sema.analyzeCopy(block, inst, .memcpy);
25619}
25620
25621fn zirMemmove(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
25622 return sema.analyzeCopy(block, inst, .memmove);
25623}
25624
25625fn analyzeCopy(
25626 sema: *Sema,
25627 block: *Block,
25628 inst: Zir.Inst.Index,
25629 op: enum { memcpy, memmove },
25630) CompileError!void {
2561325631 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2561425632 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2561525633 const src = block.nodeOffset(inst_data.src_node);
......@@ -25625,12 +25643,12 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2562525643 const zcu = pt.zcu;
2562625644
2562725645 if (dest_ty.isConstPtr(zcu)) {
25628 return sema.fail(block, dest_src, "cannot memcpy to constant pointer", .{});
25646 return sema.fail(block, dest_src, "cannot {s} to constant pointer", .{@tagName(op)});
2562925647 }
2563025648
2563125649 if (dest_len == .none and src_len == .none) {
2563225650 const msg = msg: {
25633 const msg = try sema.errMsg(src, "unknown @memcpy length", .{});
25651 const msg = try sema.errMsg(src, "unknown @{s} length", .{@tagName(op)});
2563425652 errdefer msg.destroy(sema.gpa);
2563525653 try sema.errNote(dest_src, msg, "destination type '{}' provides no length", .{
2563625654 dest_ty.fmt(pt),
......@@ -25676,7 +25694,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2567625694 if (try sema.resolveDefinedValue(block, src_src, src_len)) |src_len_val| {
2567725695 if (!(try sema.valuesEqual(dest_len_val, src_len_val, Type.usize))) {
2567825696 const msg = msg: {
25679 const msg = try sema.errMsg(src, "non-matching @memcpy lengths", .{});
25697 const msg = try sema.errMsg(src, "non-matching @{s} lengths", .{@tagName(op)});
2568025698 errdefer msg.destroy(sema.gpa);
2568125699 try sema.errNote(dest_src, msg, "length {} here", .{
2568225700 dest_len_val.fmtValueSema(pt, sema),
......@@ -25696,7 +25714,11 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2569625714
2569725715 if (block.wantSafety()) {
2569825716 const ok = try block.addBinOp(.cmp_eq, dest_len, src_len);
25699 try sema.addSafetyCheck(block, src, ok, .memcpy_len_mismatch);
25717 const panic_id: Zcu.SimplePanicId = switch (op) {
25718 .memcpy => .memcpy_len_mismatch,
25719 .memmove => .memmove_len_mismatch,
25720 };
25721 try sema.addSafetyCheck(block, src, ok, panic_id);
2570025722 }
2570125723 } else if (dest_len != .none) {
2570225724 if (try sema.resolveDefinedValue(block, dest_src, dest_len)) |dest_len_val| {
......@@ -25724,6 +25746,11 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2572425746 return;
2572525747 }
2572625748
25749 const check_aliasing = switch (op) {
25750 .memcpy => true,
25751 .memmove => false,
25752 };
25753
2572725754 const runtime_src = rs: {
2572825755 const dest_ptr_val = try sema.resolveDefinedValue(block, dest_src, dest_ptr) orelse break :rs dest_src;
2572925756 const src_ptr_val = try sema.resolveDefinedValue(block, src_src, src_ptr) orelse break :rs src_src;
......@@ -25733,12 +25760,14 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2573325760
2573425761 const len_u64 = try len_val.?.toUnsignedIntSema(pt);
2573525762
25736 if (Value.doPointersOverlap(
25737 raw_src_ptr,
25738 raw_dest_ptr,
25739 len_u64,
25740 zcu,
25741 )) return sema.fail(block, src, "'@memcpy' arguments alias", .{});
25763 if (check_aliasing) {
25764 if (Value.doPointersOverlap(
25765 raw_src_ptr,
25766 raw_dest_ptr,
25767 len_u64,
25768 zcu,
25769 )) return sema.fail(block, src, "'@memcpy' arguments alias", .{});
25770 }
2574225771
2574325772 if (!sema.isComptimeMutablePtr(dest_ptr_val)) break :rs dest_src;
2574425773
......@@ -25810,7 +25839,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2581025839 try sema.validateRuntimeValue(block, src_src, src_ptr);
2581125840
2581225841 // Aliasing safety check.
25813 if (block.wantSafety()) {
25842 if (check_aliasing and block.wantSafety()) {
2581425843 const len = if (len_val) |v|
2581525844 Air.internedToRef(v.toIntern())
2581625845 else if (dest_len != .none)
......@@ -25853,7 +25882,10 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2585325882 }
2585425883
2585525884 _ = try block.addInst(.{
25856 .tag = .memcpy,
25885 .tag = switch (op) {
25886 .memcpy => .memcpy,
25887 .memmove => .memmove,
25888 },
2585725889 .data = .{ .bin_op = .{
2585825890 .lhs = new_dest_ptr,
2585925891 .rhs = new_src_ptr,
......@@ -38078,6 +38110,7 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Typ
3807838110 .@"panic.forLenMismatch",
3807938111 .@"panic.memcpyLenMismatch",
3808038112 .@"panic.memcpyAlias",
38113 .@"panic.memmoveLenMismatch",
3808138114 .@"panic.noreturnReturned",
3808238115 => try pt.funcType(.{
3808338116 .param_types = &.{},
src/Zcu.zig+4
......@@ -302,6 +302,7 @@ pub const BuiltinDecl = enum {
302302 @"panic.forLenMismatch",
303303 @"panic.memcpyLenMismatch",
304304 @"panic.memcpyAlias",
305 @"panic.memmoveLenMismatch",
305306 @"panic.noreturnReturned",
306307
307308 VaList,
......@@ -379,6 +380,7 @@ pub const BuiltinDecl = enum {
379380 .@"panic.forLenMismatch",
380381 .@"panic.memcpyLenMismatch",
381382 .@"panic.memcpyAlias",
383 .@"panic.memmoveLenMismatch",
382384 .@"panic.noreturnReturned",
383385 => .func,
384386 };
......@@ -446,6 +448,7 @@ pub const SimplePanicId = enum {
446448 for_len_mismatch,
447449 memcpy_len_mismatch,
448450 memcpy_alias,
451 memmove_len_mismatch,
449452 noreturn_returned,
450453
451454 pub fn toBuiltin(id: SimplePanicId) BuiltinDecl {
......@@ -470,6 +473,7 @@ pub const SimplePanicId = enum {
470473 .for_len_mismatch => .@"panic.forLenMismatch",
471474 .memcpy_len_mismatch => .@"panic.memcpyLenMismatch",
472475 .memcpy_alias => .@"panic.memcpyAlias",
476 .memmove_len_mismatch => .@"panic.memmoveLenMismatch",
473477 .noreturn_returned => .@"panic.noreturnReturned",
474478 // zig fmt: on
475479 };
src/arch/aarch64/CodeGen.zig+6
......@@ -760,6 +760,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
760760 .atomic_rmw => try self.airAtomicRmw(inst),
761761 .atomic_load => try self.airAtomicLoad(inst),
762762 .memcpy => try self.airMemcpy(inst),
763 .memmove => try self.airMemmove(inst),
763764 .memset => try self.airMemset(inst, false),
764765 .memset_safe => try self.airMemset(inst, true),
765766 .set_union_tag => try self.airSetUnionTag(inst),
......@@ -5993,6 +5994,11 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) InnerError!void {
59935994 return self.fail("TODO implement airMemcpy for {}", .{self.target.cpu.arch});
59945995}
59955996
5997fn airMemmove(self: *Self, inst: Air.Inst.Index) InnerError!void {
5998 _ = inst;
5999 return self.fail("TODO implement airMemmove for {}", .{self.target.cpu.arch});
6000}
6001
59966002fn airTagName(self: *Self, inst: Air.Inst.Index) InnerError!void {
59976003 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
59986004 const operand = try self.resolveInst(un_op);
src/arch/arm/CodeGen.zig+6
......@@ -749,6 +749,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
749749 .atomic_rmw => try self.airAtomicRmw(inst),
750750 .atomic_load => try self.airAtomicLoad(inst),
751751 .memcpy => try self.airMemcpy(inst),
752 .memmove => try self.airMemmove(inst),
752753 .memset => try self.airMemset(inst, false),
753754 .memset_safe => try self.airMemset(inst, true),
754755 .set_union_tag => try self.airSetUnionTag(inst),
......@@ -5963,6 +5964,11 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
59635964 return self.fail("TODO implement airMemcpy for {}", .{self.target.cpu.arch});
59645965}
59655966
5967fn airMemmove(self: *Self, inst: Air.Inst.Index) !void {
5968 _ = inst;
5969 return self.fail("TODO implement airMemmove for {}", .{self.target.cpu.arch});
5970}
5971
59665972fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
59675973 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
59685974 const operand = try self.resolveInst(un_op);
src/arch/riscv64/CodeGen.zig+6
......@@ -1581,6 +1581,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
15811581 .atomic_rmw => try func.airAtomicRmw(inst),
15821582 .atomic_load => try func.airAtomicLoad(inst),
15831583 .memcpy => try func.airMemcpy(inst),
1584 .memmove => try func.airMemmove(inst),
15841585 .memset => try func.airMemset(inst, false),
15851586 .memset_safe => try func.airMemset(inst, true),
15861587 .set_union_tag => try func.airSetUnionTag(inst),
......@@ -7919,6 +7920,11 @@ fn airMemcpy(func: *Func, inst: Air.Inst.Index) !void {
79197920 return func.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
79207921}
79217922
7923fn airMemmove(func: *Func, inst: Air.Inst.Index) !void {
7924 _ = inst;
7925 return func.fail("TODO implement airMemmove for riscv64", .{});
7926}
7927
79227928fn airTagName(func: *Func, inst: Air.Inst.Index) !void {
79237929 const pt = func.pt;
79247930
src/arch/sparc64/CodeGen.zig+1
......@@ -604,6 +604,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
604604 .atomic_rmw => try self.airAtomicRmw(inst),
605605 .atomic_load => try self.airAtomicLoad(inst),
606606 .memcpy => @panic("TODO try self.airMemcpy(inst)"),
607 .memmove => @panic("TODO try self.airMemmove(inst)"),
607608 .memset => try self.airMemset(inst, false),
608609 .memset_safe => try self.airMemset(inst, true),
609610 .set_union_tag => try self.airSetUnionTag(inst),
src/arch/wasm/CodeGen.zig+1
......@@ -2061,6 +2061,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
20612061 .c_va_copy,
20622062 .c_va_end,
20632063 .c_va_start,
2064 .memmove,
20642065 => |tag| return cg.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
20652066
20662067 .atomic_load => cg.airAtomicLoad(inst),
src/arch/x86_64/CodeGen.zig+6
......@@ -89453,6 +89453,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
8945389453 .memset => try cg.airMemset(inst, false),
8945489454 .memset_safe => try cg.airMemset(inst, true),
8945589455 .memcpy => try cg.airMemcpy(inst),
89456 .memmove => try cg.airMemmove(inst),
8945689457 .cmpxchg_weak, .cmpxchg_strong => try cg.airCmpxchg(inst),
8945789458 .atomic_load => try cg.airAtomicLoad(inst),
8945889459 .atomic_store_unordered => try cg.airAtomicStore(inst, .unordered),
......@@ -106472,6 +106473,11 @@ fn airMemcpy(self: *CodeGen, inst: Air.Inst.Index) !void {
106472106473 return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
106473106474}
106474106475
106476fn airMemmove(self: *CodeGen, inst: Air.Inst.Index) !void {
106477 _ = inst;
106478 return self.fail("TODO implement airMemmove for {}", .{self.target.cpu.arch});
106479}
106480
106475106481fn airTagName(self: *CodeGen, inst: Air.Inst.Index, only_safety: bool) !void {
106476106482 const pt = self.pt;
106477106483 const zcu = pt.zcu;
src/codegen/c.zig+14-1
......@@ -3349,6 +3349,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
33493349 .memset => try airMemset(f, inst, false),
33503350 .memset_safe => try airMemset(f, inst, true),
33513351 .memcpy => try airMemcpy(f, inst),
3352 .memmove => try airMemmove(f, inst),
33523353 .set_union_tag => try airSetUnionTag(f, inst),
33533354 .get_union_tag => try airGetUnionTag(f, inst),
33543355 .clz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "clz", .bits),
......@@ -6976,6 +6977,14 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
69766977}
69776978
69786979fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
6980 return copyOp(f, inst, .memcpy);
6981}
6982
6983fn airMemmove(f: *Function, inst: Air.Inst.Index) !CValue {
6984 return copyOp(f, inst, .memmove);
6985}
6986
6987fn copyOp(f: *Function, inst: Air.Inst.Index, op: enum { memcpy, memmove }) !CValue {
69796988 const pt = f.object.dg.pt;
69806989 const zcu = pt.zcu;
69816990 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
......@@ -6990,7 +6999,11 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
69906999 try writeArrayLen(f, writer, dest_ptr, dest_ty);
69917000 try writer.writeAll(" != 0) ");
69927001 }
6993 try writer.writeAll("memcpy(");
7002 const function_paren = switch (op) {
7003 .memcpy => "memcpy(",
7004 .memmove => "memmove(",
7005 };
7006 try writer.writeAll(function_paren);
69947007 try writeSliceOrPtr(f, writer, dest_ptr, dest_ty);
69957008 try writer.writeAll(", ");
69967009 try writeSliceOrPtr(f, writer, src_ptr, src_ty);
src/codegen/llvm.zig+27
......@@ -4941,6 +4941,7 @@ pub const FuncGen = struct {
49414941 .memset => try self.airMemset(inst, false),
49424942 .memset_safe => try self.airMemset(inst, true),
49434943 .memcpy => try self.airMemcpy(inst),
4944 .memmove => try self.airMemmove(inst),
49444945 .set_union_tag => try self.airSetUnionTag(inst),
49454946 .get_union_tag => try self.airGetUnionTag(inst),
49464947 .clz => try self.airClzCtz(inst, .ctlz),
......@@ -9927,6 +9928,32 @@ pub const FuncGen = struct {
99279928 return .none;
99289929 }
99299930
9931 fn airMemmove(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
9932 const o = self.ng.object;
9933 const pt = o.pt;
9934 const zcu = pt.zcu;
9935 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
9936 const dest_slice = try self.resolveInst(bin_op.lhs);
9937 const dest_ptr_ty = self.typeOf(bin_op.lhs);
9938 const src_slice = try self.resolveInst(bin_op.rhs);
9939 const src_ptr_ty = self.typeOf(bin_op.rhs);
9940 const src_ptr = try self.sliceOrArrayPtr(src_slice, src_ptr_ty);
9941 const len = try self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty);
9942 const dest_ptr = try self.sliceOrArrayPtr(dest_slice, dest_ptr_ty);
9943 const access_kind: Builder.MemoryAccessKind = if (src_ptr_ty.isVolatilePtr(zcu) or
9944 dest_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
9945
9946 _ = try self.wip.callMemMove(
9947 dest_ptr,
9948 dest_ptr_ty.ptrAlignment(zcu).toLlvm(),
9949 src_ptr,
9950 src_ptr_ty.ptrAlignment(zcu).toLlvm(),
9951 len,
9952 access_kind,
9953 );
9954 return .none;
9955 }
9956
99309957 fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
99319958 const o = self.ng.object;
99329959 const pt = o.pt;
src/codegen/spirv.zig+6
......@@ -3344,6 +3344,7 @@ const NavGen = struct {
33443344 .slice => try self.airSlice(inst),
33453345 .aggregate_init => try self.airAggregateInit(inst),
33463346 .memcpy => return self.airMemcpy(inst),
3347 .memmove => return self.airMemmove(inst),
33473348
33483349 .slice_ptr => try self.airSliceField(inst, 0),
33493350 .slice_len => try self.airSliceField(inst, 1),
......@@ -4914,6 +4915,11 @@ const NavGen = struct {
49144915 });
49154916 }
49164917
4918 fn airMemmove(self: *NavGen, inst: Air.Inst.Index) !void {
4919 _ = inst;
4920 return self.fail("TODO implement airMemcpy for spirv", .{});
4921 }
4922
49174923 fn airSliceField(self: *NavGen, inst: Air.Inst.Index, field: u32) !?IdRef {
49184924 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
49194925 const field_ty = self.typeOfIndex(inst);
src/print_air.zig+1
......@@ -160,6 +160,7 @@ const Writer = struct {
160160 .cmp_gt_optimized,
161161 .cmp_neq_optimized,
162162 .memcpy,
163 .memmove,
163164 .memset,
164165 .memset_safe,
165166 => try w.writeBinOp(s, inst),
src/print_zir.zig+1
......@@ -413,6 +413,7 @@ const Writer = struct {
413413 .min,
414414 .memcpy,
415415 .memset,
416 .memmove,
416417 .elem_ptr_node,
417418 .elem_val_node,
418419 .elem_ptr,
test/cases/compile_errors/bad_panic_call_signature.zig+1
......@@ -29,6 +29,7 @@ pub const panic = struct {
2929 pub const forLenMismatch = simple_panic.forLenMismatch;
3030 pub const memcpyLenMismatch = simple_panic.memcpyLenMismatch;
3131 pub const memcpyAlias = simple_panic.memcpyAlias;
32 pub const memmoveLenMismatch = simple_panic.memmoveLenMismatch;
3233 pub const noreturnReturned = simple_panic.noreturnReturned;
3334};
3435
test/cases/compile_errors/bad_panic_generic_signature.zig+1
......@@ -25,6 +25,7 @@ pub const panic = struct {
2525 pub const forLenMismatch = simple_panic.forLenMismatch;
2626 pub const memcpyLenMismatch = simple_panic.memcpyLenMismatch;
2727 pub const memcpyAlias = simple_panic.memcpyAlias;
28 pub const memmoveLenMismatch = simple_panic.memmoveLenMismatch;
2829 pub const noreturnReturned = simple_panic.noreturnReturned;
2930};
3031
test/incremental/change_panic_handler_explicit+3
......@@ -39,6 +39,7 @@ pub const panic = struct {
3939 pub const forLenMismatch = no_panic.forLenMismatch;
4040 pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
4141 pub const memcpyAlias = no_panic.memcpyAlias;
42 pub const memmoveLenMismatch = no_panic.memmoveLenMismatch;
4243 pub const noreturnReturned = no_panic.noreturnReturned;
4344};
4445fn myPanic(msg: []const u8, _: ?usize) noreturn {
......@@ -86,6 +87,7 @@ pub const panic = struct {
8687 pub const forLenMismatch = no_panic.forLenMismatch;
8788 pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
8889 pub const memcpyAlias = no_panic.memcpyAlias;
90 pub const memmoveLenMismatch = no_panic.memmoveLenMismatch;
8991 pub const noreturnReturned = no_panic.noreturnReturned;
9092};
9193fn myPanic(msg: []const u8, _: ?usize) noreturn {
......@@ -133,6 +135,7 @@ pub const panic = struct {
133135 pub const forLenMismatch = no_panic.forLenMismatch;
134136 pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
135137 pub const memcpyAlias = no_panic.memcpyAlias;
138 pub const memmoveLenMismatch = no_panic.memmoveLenMismatch;
136139 pub const noreturnReturned = no_panic.noreturnReturned;
137140};
138141fn myPanicNew(msg: []const u8, _: ?usize) noreturn {