| ... | @@ -8634,6 +8634,41 @@ pub const FuncGen = struct { | ... | @@ -8634,6 +8634,41 @@ pub const FuncGen = struct { |
| 8634 | const len = self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty); | 8634 | const len = self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty); |
| 8635 | const dest_ptr = self.sliceOrArrayPtr(dest_slice, dest_ptr_ty); | 8635 | const dest_ptr = self.sliceOrArrayPtr(dest_slice, dest_ptr_ty); |
| 8636 | const is_volatile = src_ptr_ty.isVolatilePtr(mod) or dest_ptr_ty.isVolatilePtr(mod); | 8636 | const is_volatile = src_ptr_ty.isVolatilePtr(mod) or dest_ptr_ty.isVolatilePtr(mod); |
| | 8637 | |
| | 8638 | // When bulk-memory is enabled, this will be lowered to WebAssembly's memory.copy instruction. |
| | 8639 | // This instruction will trap on an invalid address, regardless of the length. |
| | 8640 | // For this reason we must add a safety-check for 0-sized slices as its pointer field can be undefined. |
| | 8641 | // We only have to do this for slices as arrays will have a valid pointer. |
| | 8642 | if (o.target.isWasm() and |
| | 8643 | std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory) and |
| | 8644 | (src_ptr_ty.isSlice(mod) or dest_ptr_ty.isSlice(mod))) |
| | 8645 | { |
| | 8646 | const parent_block = self.context.createBasicBlock("Block"); |
| | 8647 | |
| | 8648 | const llvm_usize_ty = self.context.intType(o.target.ptrBitWidth()); |
| | 8649 | const cond = try self.cmp(len, llvm_usize_ty.constInt(0, .False), Type.usize, .eq); |
| | 8650 | const then_block = self.context.appendBasicBlock(self.llvm_func, "Then"); |
| | 8651 | const else_block = self.context.appendBasicBlock(self.llvm_func, "Else"); |
| | 8652 | _ = self.builder.buildCondBr(cond, then_block, else_block); |
| | 8653 | |
| | 8654 | self.builder.positionBuilderAtEnd(then_block); |
| | 8655 | _ = self.builder.buildBr(parent_block); |
| | 8656 | |
| | 8657 | self.builder.positionBuilderAtEnd(else_block); |
| | 8658 | _ = self.builder.buildMemCpy( |
| | 8659 | dest_ptr, |
| | 8660 | dest_ptr_ty.ptrAlignment(mod), |
| | 8661 | src_ptr, |
| | 8662 | src_ptr_ty.ptrAlignment(mod), |
| | 8663 | len, |
| | 8664 | is_volatile, |
| | 8665 | ); |
| | 8666 | _ = self.builder.buildBr(parent_block); |
| | 8667 | self.llvm_func.appendExistingBasicBlock(parent_block); |
| | 8668 | self.builder.positionBuilderAtEnd(parent_block); |
| | 8669 | return null; |
| | 8670 | } |
| | 8671 | |
| 8637 | _ = self.builder.buildMemCpy( | 8672 | _ = self.builder.buildMemCpy( |
| 8638 | dest_ptr, | 8673 | dest_ptr, |
| 8639 | dest_ptr_ty.ptrAlignment(mod), | 8674 | dest_ptr_ty.ptrAlignment(mod), |