| ... | @@ -8514,8 +8514,8 @@ pub const FuncGen = struct { | ... | @@ -8514,8 +8514,8 @@ pub const FuncGen = struct { |
| 8514 | // Any WebAssembly runtime will trap when the destination pointer is out-of-bounds, regardless | 8514 | // Any WebAssembly runtime will trap when the destination pointer is out-of-bounds, regardless |
| 8515 | // of the length. This means we need to emit a check where we skip the memset when the length | 8515 | // of the length. This means we need to emit a check where we skip the memset when the length |
| 8516 | // is 0 as we allow for undefined pointers in 0-sized slices. | 8516 | // is 0 as we allow for undefined pointers in 0-sized slices. |
| 8517 | const needs_wasm_safety_check = safety and | 8517 | // This logic can be removed once https://github.com/ziglang/zig/issues/16360 is done. |
| 8518 | o.target.isWasm() and | 8518 | const intrinsic_len0_traps = o.target.isWasm() and |
| 8519 | ptr_ty.isSlice(mod) and | 8519 | ptr_ty.isSlice(mod) and |
| 8520 | std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory); | 8520 | std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory); |
| 8521 | | 8521 | |
| ... | @@ -8529,7 +8529,7 @@ pub const FuncGen = struct { | ... | @@ -8529,7 +8529,7 @@ pub const FuncGen = struct { |
| 8529 | else | 8529 | else |
| 8530 | u8_llvm_ty.getUndef(); | 8530 | u8_llvm_ty.getUndef(); |
| 8531 | const len = self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); | 8531 | const len = self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); |
| 8532 | if (needs_wasm_safety_check) { | 8532 | if (intrinsic_len0_traps) { |
| 8533 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); | 8533 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| 8534 | } else { | 8534 | } else { |
| 8535 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); | 8535 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| ... | @@ -8552,7 +8552,7 @@ pub const FuncGen = struct { | ... | @@ -8552,7 +8552,7 @@ pub const FuncGen = struct { |
| 8552 | }); | 8552 | }); |
| 8553 | const len = self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); | 8553 | const len = self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); |
| 8554 | | 8554 | |
| 8555 | if (needs_wasm_safety_check) { | 8555 | if (intrinsic_len0_traps) { |
| 8556 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); | 8556 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| 8557 | } else { | 8557 | } else { |
| 8558 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); | 8558 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| ... | @@ -8569,7 +8569,7 @@ pub const FuncGen = struct { | ... | @@ -8569,7 +8569,7 @@ pub const FuncGen = struct { |
| 8569 | const fill_byte = try self.bitCast(value, elem_ty, Type.u8); | 8569 | const fill_byte = try self.bitCast(value, elem_ty, Type.u8); |
| 8570 | const len = self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); | 8570 | const len = self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); |
| 8571 | | 8571 | |
| 8572 | if (needs_wasm_safety_check) { | 8572 | if (intrinsic_len0_traps) { |
| 8573 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); | 8573 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| 8574 | } else { | 8574 | } else { |
| 8575 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); | 8575 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| ... | @@ -8652,19 +8652,15 @@ pub const FuncGen = struct { | ... | @@ -8652,19 +8652,15 @@ pub const FuncGen = struct { |
| 8652 | dest_ptr_align: u32, | 8652 | dest_ptr_align: u32, |
| 8653 | is_volatile: bool, | 8653 | is_volatile: bool, |
| 8654 | ) !void { | 8654 | ) !void { |
| 8655 | const parent_block = self.context.createBasicBlock("Block"); | | |
| 8656 | const llvm_usize_ty = self.context.intType(self.dg.object.target.ptrBitWidth()); | 8655 | const llvm_usize_ty = self.context.intType(self.dg.object.target.ptrBitWidth()); |
| 8657 | const cond = try self.cmp(len, llvm_usize_ty.constInt(0, .False), Type.usize, .eq); | 8656 | const cond = try self.cmp(len, llvm_usize_ty.constInt(0, .False), Type.usize, .neq); |
| 8658 | const then_block = self.context.appendBasicBlock(self.llvm_func, "Then"); | 8657 | const memset_block = self.context.appendBasicBlock(self.llvm_func, "MemsetTrapSkip"); |
| 8659 | const else_block = self.context.appendBasicBlock(self.llvm_func, "Else"); | 8658 | const end_block = self.context.appendBasicBlock(self.llvm_func, "MemsetTrapEnd"); |
| 8660 | _ = self.builder.buildCondBr(cond, then_block, else_block); | 8659 | _ = self.builder.buildCondBr(cond, memset_block, end_block); |
| 8661 | self.builder.positionBuilderAtEnd(then_block); | 8660 | self.builder.positionBuilderAtEnd(memset_block); |
| 8662 | _ = self.builder.buildBr(parent_block); | | |
| 8663 | self.builder.positionBuilderAtEnd(else_block); | | |
| 8664 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); | 8661 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| 8665 | _ = self.builder.buildBr(parent_block); | 8662 | _ = self.builder.buildBr(end_block); |
| 8666 | self.llvm_func.appendExistingBasicBlock(parent_block); | 8663 | self.builder.positionBuilderAtEnd(end_block); |
| 8667 | self.builder.positionBuilderAtEnd(parent_block); | | |
| 8668 | } | 8664 | } |
| 8669 | | 8665 | |
| 8670 | fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 8666 | fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| ... | @@ -8682,24 +8678,19 @@ pub const FuncGen = struct { | ... | @@ -8682,24 +8678,19 @@ pub const FuncGen = struct { |
| 8682 | | 8678 | |
| 8683 | // When bulk-memory is enabled, this will be lowered to WebAssembly's memory.copy instruction. | 8679 | // When bulk-memory is enabled, this will be lowered to WebAssembly's memory.copy instruction. |
| 8684 | // This instruction will trap on an invalid address, regardless of the length. | 8680 | // This instruction will trap on an invalid address, regardless of the length. |
| 8685 | // For this reason we must add a safety-check for 0-sized slices as its pointer field can be undefined. | 8681 | // For this reason we must add a check for 0-sized slices as its pointer field can be undefined. |
| 8686 | // We only have to do this for slices as arrays will have a valid pointer. | 8682 | // We only have to do this for slices as arrays will have a valid pointer. |
| | 8683 | // This logic can be removed once https://github.com/ziglang/zig/issues/16360 is done. |
| 8687 | if (o.target.isWasm() and | 8684 | if (o.target.isWasm() and |
| 8688 | std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory) and | 8685 | std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory) and |
| 8689 | (src_ptr_ty.isSlice(mod) or dest_ptr_ty.isSlice(mod))) | 8686 | dest_ptr_ty.isSlice(mod)) |
| 8690 | { | 8687 | { |
| 8691 | const parent_block = self.context.createBasicBlock("Block"); | 8688 | const llvm_usize_ty = self.context.intType(self.dg.object.target.ptrBitWidth()); |
| 8692 | | 8689 | const cond = try self.cmp(len, llvm_usize_ty.constInt(0, .False), Type.usize, .neq); |
| 8693 | const llvm_usize_ty = self.context.intType(o.target.ptrBitWidth()); | 8690 | const memcpy_block = self.context.appendBasicBlock(self.llvm_func, "MemcpyTrapSkip"); |
| 8694 | const cond = try self.cmp(len, llvm_usize_ty.constInt(0, .False), Type.usize, .eq); | 8691 | const end_block = self.context.appendBasicBlock(self.llvm_func, "MemcpyTrapEnd"); |
| 8695 | const then_block = self.context.appendBasicBlock(self.llvm_func, "Then"); | 8692 | _ = self.builder.buildCondBr(cond, memcpy_block, end_block); |
| 8696 | const else_block = self.context.appendBasicBlock(self.llvm_func, "Else"); | 8693 | self.builder.positionBuilderAtEnd(memcpy_block); |
| 8697 | _ = self.builder.buildCondBr(cond, then_block, else_block); | | |
| 8698 | | | |
| 8699 | self.builder.positionBuilderAtEnd(then_block); | | |
| 8700 | _ = self.builder.buildBr(parent_block); | | |
| 8701 | | | |
| 8702 | self.builder.positionBuilderAtEnd(else_block); | | |
| 8703 | _ = self.builder.buildMemCpy( | 8694 | _ = self.builder.buildMemCpy( |
| 8704 | dest_ptr, | 8695 | dest_ptr, |
| 8705 | dest_ptr_ty.ptrAlignment(mod), | 8696 | dest_ptr_ty.ptrAlignment(mod), |
| ... | @@ -8708,9 +8699,8 @@ pub const FuncGen = struct { | ... | @@ -8708,9 +8699,8 @@ pub const FuncGen = struct { |
| 8708 | len, | 8699 | len, |
| 8709 | is_volatile, | 8700 | is_volatile, |
| 8710 | ); | 8701 | ); |
| 8711 | _ = self.builder.buildBr(parent_block); | 8702 | _ = self.builder.buildBr(end_block); |
| 8712 | self.llvm_func.appendExistingBasicBlock(parent_block); | 8703 | self.builder.positionBuilderAtEnd(end_block); |
| 8713 | self.builder.positionBuilderAtEnd(parent_block); | | |
| 8714 | return null; | 8704 | return null; |
| 8715 | } | 8705 | } |
| 8716 | | 8706 | |