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