compiler: add @memmove builtin

This commit is contained in:
dweiller 2025-01-23 00:13:23 +11:00
parent b9f440620d
commit 898ca82458
29 changed files with 215 additions and 14 deletions

View File

@ -134,6 +134,10 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type {
@branchHint(.cold);
call("@memcpy arguments alias", @returnAddress());
}
pub fn memmoveLenMismatch() noreturn {
@branchHint(.cold);
call("@memmove arguments have non-equal lengths", @returnAddress());
}
pub fn noreturnReturned() noreturn {
@branchHint(.cold);
call("'noreturn' function returned", @returnAddress());

View File

@ -135,6 +135,11 @@ pub fn memcpyAlias() noreturn {
@trap();
}
pub fn memmoveLenMismatch() noreturn {
@branchHint(.cold);
@trap();
}
pub fn noreturnReturned() noreturn {
@branchHint(.cold);
@trap();

View File

@ -128,6 +128,10 @@ pub fn memcpyAlias() noreturn {
call("@memcpy arguments alias", null);
}
pub fn memmoveLenMismatch() noreturn {
call("@memmove arguments have non-equal lengths", null);
}
pub fn noreturnReturned() noreturn {
call("'noreturn' function returned", null);
}

View File

@ -2919,6 +2919,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
.set_runtime_safety,
.memcpy,
.memset,
.memmove,
.validate_deref,
.validate_destructure,
.save_err_ret_index,
@ -9717,6 +9718,13 @@ fn builtinCall(
});
return rvalue(gz, ri, .void_value, node);
},
.memmove => {
_ = try gz.addPlNode(.memmove, node, Zir.Inst.Bin{
.lhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
.rhs = try expr(gz, scope, .{ .rl = .none }, params[1]),
});
return rvalue(gz, ri, .void_value, node);
},
.shuffle => {
const result = try gz.addPlNode(.shuffle, node, Zir.Inst.Shuffle{
.elem_type = try typeExpr(gz, scope, params[0]),

View File

@ -1055,7 +1055,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
_ = try astrl.expr(args[2], block, ResultInfo.none);
return false;
},
.memcpy => {
.memcpy, .memmove => {
_ = try astrl.expr(args[0], block, ResultInfo.none);
_ = try astrl.expr(args[1], block, ResultInfo.none);
return false;

View File

@ -68,6 +68,7 @@ pub const Tag = enum {
max,
memcpy,
memset,
memmove,
min,
wasm_memory_size,
wasm_memory_grow,
@ -641,6 +642,13 @@ pub const list = list: {
.param_count = 2,
},
},
.{
"@memmove",
.{
.tag = .memmove,
.param_count = 2,
},
},
.{
"@min",
.{

View File

@ -986,6 +986,9 @@ pub const Inst = struct {
/// Implements the `@memset` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
memset,
/// Implements the `@memmove` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
memmove,
/// Implements the `@min` builtin for 2 args.
/// Uses the `pl_node` union field with payload `Bin`
min,
@ -1272,6 +1275,7 @@ pub const Inst = struct {
.max,
.memcpy,
.memset,
.memmove,
.min,
.c_import,
.@"resume",
@ -1355,6 +1359,7 @@ pub const Inst = struct {
.set_runtime_safety,
.memcpy,
.memset,
.memmove,
.check_comptime_control_flow,
.@"defer",
.defer_err_code,
@ -1832,6 +1837,7 @@ pub const Inst = struct {
.max = .pl_node,
.memcpy = .pl_node,
.memset = .pl_node,
.memmove = .pl_node,
.min = .pl_node,
.c_import = .pl_node,
@ -4291,6 +4297,7 @@ fn findTrackableInner(
.mul_add,
.memcpy,
.memset,
.memmove,
.min,
.max,
.alloc,

View File

@ -6125,6 +6125,36 @@ pub const WipFunction = struct {
return value.unwrap().instruction;
}
pub fn callMemMove(
self: *WipFunction,
dst: Value,
dst_align: Alignment,
src: Value,
src_align: Alignment,
len: Value,
kind: MemoryAccessKind,
) Allocator.Error!Instruction.Index {
var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })};
var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = src_align })};
const value = try self.callIntrinsic(
.normal,
try self.builder.fnAttrs(&.{
.none,
.none,
try self.builder.attrs(&dst_attrs),
try self.builder.attrs(&src_attrs),
}),
.memmove,
&.{ dst.typeOfWip(self), src.typeOfWip(self), len.typeOfWip(self) },
&.{ dst, src, len, switch (kind) {
.normal => Value.false,
.@"volatile" => Value.true,
} },
undefined,
);
return value.unwrap().instruction;
}
pub fn callMemSet(
self: *WipFunction,
dst: Value,

View File

@ -481,6 +481,7 @@
zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t);
zig_extern void *memset (void *, int, size_t);
zig_extern void *memmove (void *, void const *, size_t);
/* ================ Bool and 8/16/32/64-bit Integer Support ================= */

View File

@ -730,6 +730,18 @@ pub const Inst = struct {
/// source being a pointer-to-array), then it is guaranteed to be
/// greater than zero.
memcpy,
/// Given dest pointer and source pointer, copy elements from source to dest.
/// Dest pointer is either a slice or a pointer to array.
/// The dest element type may be any type.
/// Source pointer must have same element type as dest element type.
/// Dest slice may have any alignment; source pointer may have any alignment.
/// The two memory regions may overlap.
/// Result type is always void.
/// Uses the `bin_op` field. LHS is the dest slice. RHS is the source pointer.
/// If the length is compile-time known (due to the destination or
/// source being a pointer-to-array), then it is guaranteed to be
/// greater than zero.
memmove,
/// Uses the `ty_pl` field with payload `Cmpxchg`.
cmpxchg_weak,
@ -1533,6 +1545,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
.memset,
.memset_safe,
.memcpy,
.memmove,
.set_union_tag,
.prefetch,
.set_err_return_trace,
@ -1696,6 +1709,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
.memset,
.memset_safe,
.memcpy,
.memmove,
.cmpxchg_weak,
.cmpxchg_strong,
.atomic_store_unordered,

View File

@ -83,6 +83,7 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool {
.memset,
.memset_safe,
.memcpy,
.memmove,
.atomic_store_unordered,
.atomic_store_monotonic,
.atomic_store_release,

View File

@ -300,6 +300,7 @@ pub fn categorizeOperand(
.memset,
.memset_safe,
.memcpy,
.memmove,
=> {
const o = air_datas[@intFromEnum(inst)].bin_op;
if (o.lhs == operand_ref) return matchOperandSmallIndex(l, inst, 0, .write);
@ -936,6 +937,7 @@ fn analyzeInst(
.memset,
.memset_safe,
.memcpy,
.memmove,
=> {
const o = inst_datas[@intFromEnum(inst)].bin_op;
return analyzeOperands(a, pass, data, inst, .{ o.lhs, o.rhs, .none });

View File

@ -267,6 +267,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
.memset,
.memset_safe,
.memcpy,
.memmove,
=> {
const bin_op = data[@intFromEnum(inst)].bin_op;
try self.verifyInstOperands(inst, .{ bin_op.lhs, bin_op.rhs, .none });

View File

@ -1583,6 +1583,11 @@ fn analyzeBodyInner(
i += 1;
continue;
},
.memmove => {
try sema.zirMemmove(block, inst);
i += 1;
continue;
},
.check_comptime_control_flow => {
if (!block.isComptime()) {
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
}
fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
return sema.analyzeCopy(block, inst, .memcpy);
}
fn zirMemmove(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
return sema.analyzeCopy(block, inst, .memmove);
}
fn analyzeCopy(
sema: *Sema,
block: *Block,
inst: Zir.Inst.Index,
op: enum { memcpy, memmove },
) CompileError!void {
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
const src = block.nodeOffset(inst_data.src_node);
@ -25625,12 +25643,12 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
const zcu = pt.zcu;
if (dest_ty.isConstPtr(zcu)) {
return sema.fail(block, dest_src, "cannot memcpy to constant pointer", .{});
return sema.fail(block, dest_src, "cannot {s} to constant pointer", .{@tagName(op)});
}
if (dest_len == .none and src_len == .none) {
const msg = msg: {
const msg = try sema.errMsg(src, "unknown @memcpy length", .{});
const msg = try sema.errMsg(src, "unknown @{s} length", .{@tagName(op)});
errdefer msg.destroy(sema.gpa);
try sema.errNote(dest_src, msg, "destination type '{}' provides no length", .{
dest_ty.fmt(pt),
@ -25676,7 +25694,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
if (try sema.resolveDefinedValue(block, src_src, src_len)) |src_len_val| {
if (!(try sema.valuesEqual(dest_len_val, src_len_val, Type.usize))) {
const msg = msg: {
const msg = try sema.errMsg(src, "non-matching @memcpy lengths", .{});
const msg = try sema.errMsg(src, "non-matching @{s} lengths", .{@tagName(op)});
errdefer msg.destroy(sema.gpa);
try sema.errNote(dest_src, msg, "length {} here", .{
dest_len_val.fmtValueSema(pt, sema),
@ -25696,7 +25714,11 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
if (block.wantSafety()) {
const ok = try block.addBinOp(.cmp_eq, dest_len, src_len);
try sema.addSafetyCheck(block, src, ok, .memcpy_len_mismatch);
const panic_id: Zcu.SimplePanicId = switch (op) {
.memcpy => .memcpy_len_mismatch,
.memmove => .memmove_len_mismatch,
};
try sema.addSafetyCheck(block, src, ok, panic_id);
}
} else if (dest_len != .none) {
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
return;
}
const check_aliasing = switch (op) {
.memcpy => true,
.memmove => false,
};
const runtime_src = rs: {
const dest_ptr_val = try sema.resolveDefinedValue(block, dest_src, dest_ptr) orelse break :rs dest_src;
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
const len_u64 = try len_val.?.toUnsignedIntSema(pt);
if (check_aliasing) {
if (Value.doPointersOverlap(
raw_src_ptr,
raw_dest_ptr,
len_u64,
zcu,
)) return sema.fail(block, src, "'@memcpy' arguments alias", .{});
}
if (!sema.isComptimeMutablePtr(dest_ptr_val)) break :rs dest_src;
@ -25810,7 +25839,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
try sema.validateRuntimeValue(block, src_src, src_ptr);
// Aliasing safety check.
if (block.wantSafety()) {
if (check_aliasing and block.wantSafety()) {
const len = if (len_val) |v|
Air.internedToRef(v.toIntern())
else if (dest_len != .none)
@ -25853,7 +25882,10 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
}
_ = try block.addInst(.{
.tag = .memcpy,
.tag = switch (op) {
.memcpy => .memcpy,
.memmove => .memmove,
},
.data = .{ .bin_op = .{
.lhs = new_dest_ptr,
.rhs = new_src_ptr,
@ -38078,6 +38110,7 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Typ
.@"panic.forLenMismatch",
.@"panic.memcpyLenMismatch",
.@"panic.memcpyAlias",
.@"panic.memmoveLenMismatch",
.@"panic.noreturnReturned",
=> try pt.funcType(.{
.param_types = &.{},

View File

@ -302,6 +302,7 @@ pub const BuiltinDecl = enum {
@"panic.forLenMismatch",
@"panic.memcpyLenMismatch",
@"panic.memcpyAlias",
@"panic.memmoveLenMismatch",
@"panic.noreturnReturned",
VaList,
@ -379,6 +380,7 @@ pub const BuiltinDecl = enum {
.@"panic.forLenMismatch",
.@"panic.memcpyLenMismatch",
.@"panic.memcpyAlias",
.@"panic.memmoveLenMismatch",
.@"panic.noreturnReturned",
=> .func,
};
@ -446,6 +448,7 @@ pub const SimplePanicId = enum {
for_len_mismatch,
memcpy_len_mismatch,
memcpy_alias,
memmove_len_mismatch,
noreturn_returned,
pub fn toBuiltin(id: SimplePanicId) BuiltinDecl {
@ -470,6 +473,7 @@ pub const SimplePanicId = enum {
.for_len_mismatch => .@"panic.forLenMismatch",
.memcpy_len_mismatch => .@"panic.memcpyLenMismatch",
.memcpy_alias => .@"panic.memcpyAlias",
.memmove_len_mismatch => .@"panic.memmoveLenMismatch",
.noreturn_returned => .@"panic.noreturnReturned",
// zig fmt: on
};

View File

@ -760,6 +760,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.atomic_rmw => try self.airAtomicRmw(inst),
.atomic_load => try self.airAtomicLoad(inst),
.memcpy => try self.airMemcpy(inst),
.memmove => try self.airMemmove(inst),
.memset => try self.airMemset(inst, false),
.memset_safe => try self.airMemset(inst, true),
.set_union_tag => try self.airSetUnionTag(inst),
@ -5993,6 +5994,11 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) InnerError!void {
return self.fail("TODO implement airMemcpy for {}", .{self.target.cpu.arch});
}
fn airMemmove(self: *Self, inst: Air.Inst.Index) InnerError!void {
_ = inst;
return self.fail("TODO implement airMemmove for {}", .{self.target.cpu.arch});
}
fn airTagName(self: *Self, inst: Air.Inst.Index) InnerError!void {
const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
const operand = try self.resolveInst(un_op);

View File

@ -749,6 +749,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.atomic_rmw => try self.airAtomicRmw(inst),
.atomic_load => try self.airAtomicLoad(inst),
.memcpy => try self.airMemcpy(inst),
.memmove => try self.airMemmove(inst),
.memset => try self.airMemset(inst, false),
.memset_safe => try self.airMemset(inst, true),
.set_union_tag => try self.airSetUnionTag(inst),
@ -5963,6 +5964,11 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
return self.fail("TODO implement airMemcpy for {}", .{self.target.cpu.arch});
}
fn airMemmove(self: *Self, inst: Air.Inst.Index) !void {
_ = inst;
return self.fail("TODO implement airMemmove for {}", .{self.target.cpu.arch});
}
fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
const operand = try self.resolveInst(un_op);

View File

@ -1581,6 +1581,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
.atomic_rmw => try func.airAtomicRmw(inst),
.atomic_load => try func.airAtomicLoad(inst),
.memcpy => try func.airMemcpy(inst),
.memmove => try func.airMemmove(inst),
.memset => try func.airMemset(inst, false),
.memset_safe => try func.airMemset(inst, true),
.set_union_tag => try func.airSetUnionTag(inst),
@ -7919,6 +7920,11 @@ fn airMemcpy(func: *Func, inst: Air.Inst.Index) !void {
return func.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
}
fn airMemmove(func: *Func, inst: Air.Inst.Index) !void {
_ = inst;
return func.fail("TODO implement airMemmove for riscv64", .{});
}
fn airTagName(func: *Func, inst: Air.Inst.Index) !void {
const pt = func.pt;

View File

@ -604,6 +604,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.atomic_rmw => try self.airAtomicRmw(inst),
.atomic_load => try self.airAtomicLoad(inst),
.memcpy => @panic("TODO try self.airMemcpy(inst)"),
.memmove => @panic("TODO try self.airMemmove(inst)"),
.memset => try self.airMemset(inst, false),
.memset_safe => try self.airMemset(inst, true),
.set_union_tag => try self.airSetUnionTag(inst),

View File

@ -2061,6 +2061,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
.c_va_copy,
.c_va_end,
.c_va_start,
.memmove,
=> |tag| return cg.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
.atomic_load => cg.airAtomicLoad(inst),

View File

@ -89453,6 +89453,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.memset => try cg.airMemset(inst, false),
.memset_safe => try cg.airMemset(inst, true),
.memcpy => try cg.airMemcpy(inst),
.memmove => try cg.airMemmove(inst),
.cmpxchg_weak, .cmpxchg_strong => try cg.airCmpxchg(inst),
.atomic_load => try cg.airAtomicLoad(inst),
.atomic_store_unordered => try cg.airAtomicStore(inst, .unordered),
@ -106472,6 +106473,11 @@ fn airMemcpy(self: *CodeGen, inst: Air.Inst.Index) !void {
return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
}
fn airMemmove(self: *CodeGen, inst: Air.Inst.Index) !void {
_ = inst;
return self.fail("TODO implement airMemmove for {}", .{self.target.cpu.arch});
}
fn airTagName(self: *CodeGen, inst: Air.Inst.Index, only_safety: bool) !void {
const pt = self.pt;
const zcu = pt.zcu;

View File

@ -3349,6 +3349,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
.memset => try airMemset(f, inst, false),
.memset_safe => try airMemset(f, inst, true),
.memcpy => try airMemcpy(f, inst),
.memmove => try airMemmove(f, inst),
.set_union_tag => try airSetUnionTag(f, inst),
.get_union_tag => try airGetUnionTag(f, inst),
.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 {
}
fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
return copyOp(f, inst, .memcpy);
}
fn airMemmove(f: *Function, inst: Air.Inst.Index) !CValue {
return copyOp(f, inst, .memmove);
}
fn copyOp(f: *Function, inst: Air.Inst.Index, op: enum { memcpy, memmove }) !CValue {
const pt = f.object.dg.pt;
const zcu = pt.zcu;
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 {
try writeArrayLen(f, writer, dest_ptr, dest_ty);
try writer.writeAll(" != 0) ");
}
try writer.writeAll("memcpy(");
const function_paren = switch (op) {
.memcpy => "memcpy(",
.memmove => "memmove(",
};
try writer.writeAll(function_paren);
try writeSliceOrPtr(f, writer, dest_ptr, dest_ty);
try writer.writeAll(", ");
try writeSliceOrPtr(f, writer, src_ptr, src_ty);

View File

@ -4941,6 +4941,7 @@ pub const FuncGen = struct {
.memset => try self.airMemset(inst, false),
.memset_safe => try self.airMemset(inst, true),
.memcpy => try self.airMemcpy(inst),
.memmove => try self.airMemmove(inst),
.set_union_tag => try self.airSetUnionTag(inst),
.get_union_tag => try self.airGetUnionTag(inst),
.clz => try self.airClzCtz(inst, .ctlz),
@ -9927,6 +9928,32 @@ pub const FuncGen = struct {
return .none;
}
fn airMemmove(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
const o = self.ng.object;
const pt = o.pt;
const zcu = pt.zcu;
const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
const dest_slice = try self.resolveInst(bin_op.lhs);
const dest_ptr_ty = self.typeOf(bin_op.lhs);
const src_slice = try self.resolveInst(bin_op.rhs);
const src_ptr_ty = self.typeOf(bin_op.rhs);
const src_ptr = try self.sliceOrArrayPtr(src_slice, src_ptr_ty);
const len = try self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty);
const dest_ptr = try self.sliceOrArrayPtr(dest_slice, dest_ptr_ty);
const access_kind: Builder.MemoryAccessKind = if (src_ptr_ty.isVolatilePtr(zcu) or
dest_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
_ = try self.wip.callMemMove(
dest_ptr,
dest_ptr_ty.ptrAlignment(zcu).toLlvm(),
src_ptr,
src_ptr_ty.ptrAlignment(zcu).toLlvm(),
len,
access_kind,
);
return .none;
}
fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
const o = self.ng.object;
const pt = o.pt;

View File

@ -3344,6 +3344,7 @@ const NavGen = struct {
.slice => try self.airSlice(inst),
.aggregate_init => try self.airAggregateInit(inst),
.memcpy => return self.airMemcpy(inst),
.memmove => return self.airMemmove(inst),
.slice_ptr => try self.airSliceField(inst, 0),
.slice_len => try self.airSliceField(inst, 1),
@ -4914,6 +4915,11 @@ const NavGen = struct {
});
}
fn airMemmove(self: *NavGen, inst: Air.Inst.Index) !void {
_ = inst;
return self.fail("TODO implement airMemcpy for spirv", .{});
}
fn airSliceField(self: *NavGen, inst: Air.Inst.Index, field: u32) !?IdRef {
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const field_ty = self.typeOfIndex(inst);

View File

@ -160,6 +160,7 @@ const Writer = struct {
.cmp_gt_optimized,
.cmp_neq_optimized,
.memcpy,
.memmove,
.memset,
.memset_safe,
=> try w.writeBinOp(s, inst),

View File

@ -413,6 +413,7 @@ const Writer = struct {
.min,
.memcpy,
.memset,
.memmove,
.elem_ptr_node,
.elem_val_node,
.elem_ptr,

View File

@ -29,6 +29,7 @@ pub const panic = struct {
pub const forLenMismatch = simple_panic.forLenMismatch;
pub const memcpyLenMismatch = simple_panic.memcpyLenMismatch;
pub const memcpyAlias = simple_panic.memcpyAlias;
pub const memmoveLenMismatch = simple_panic.memmoveLenMismatch;
pub const noreturnReturned = simple_panic.noreturnReturned;
};

View File

@ -25,6 +25,7 @@ pub const panic = struct {
pub const forLenMismatch = simple_panic.forLenMismatch;
pub const memcpyLenMismatch = simple_panic.memcpyLenMismatch;
pub const memcpyAlias = simple_panic.memcpyAlias;
pub const memmoveLenMismatch = simple_panic.memmoveLenMismatch;
pub const noreturnReturned = simple_panic.noreturnReturned;
};

View File

@ -39,6 +39,7 @@ pub const panic = struct {
pub const forLenMismatch = no_panic.forLenMismatch;
pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
pub const memcpyAlias = no_panic.memcpyAlias;
pub const memmoveLenMismatch = no_panic.memmoveLenMismatch;
pub const noreturnReturned = no_panic.noreturnReturned;
};
fn myPanic(msg: []const u8, _: ?usize) noreturn {
@ -86,6 +87,7 @@ pub const panic = struct {
pub const forLenMismatch = no_panic.forLenMismatch;
pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
pub const memcpyAlias = no_panic.memcpyAlias;
pub const memmoveLenMismatch = no_panic.memmoveLenMismatch;
pub const noreturnReturned = no_panic.noreturnReturned;
};
fn myPanic(msg: []const u8, _: ?usize) noreturn {
@ -133,6 +135,7 @@ pub const panic = struct {
pub const forLenMismatch = no_panic.forLenMismatch;
pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
pub const memcpyAlias = no_panic.memcpyAlias;
pub const memmoveLenMismatch = no_panic.memmoveLenMismatch;
pub const noreturnReturned = no_panic.noreturnReturned;
};
fn myPanicNew(msg: []const u8, _: ?usize) noreturn {