| ... | ... | @@ -1591,10 +1591,28 @@ fn memcpy(cg: *CodeGen, dst: WValue, src: WValue, len: WValue) !void { |
| 1591 | 1591 | // When bulk_memory is enabled, we lower it to wasm's memcpy instruction. |
| 1592 | 1592 | // If not, we lower it ourselves manually |
| 1593 | 1593 | if (std.Target.wasm.featureSetHas(cg.target.cpu.features, .bulk_memory)) { |
| 1594 | try cg.startBlock(.block, .empty); |
| 1595 | |
| 1596 | // Even if `len` is zero, the spec requires an implementation to trap if `src + len` or |
| 1597 | // `dst + len` are out of memory bounds. This can easily happen in Zig in a case such as: |
| 1598 | // |
| 1599 | // const dst: [*]u8 = undefined; |
| 1600 | // const src: [*]u8 = undefined; |
| 1601 | // var len: usize = runtime_zero(); |
| 1602 | // @memcpy(dst[0..len], src[0..len]); |
| 1603 | // |
| 1604 | // So explicitly avoid using `memory.copy` in the `len == 0` case. Lovely design. |
| 1605 | try cg.emitWValue(len); |
| 1606 | try cg.addTag(.i32_eqz); |
| 1607 | try cg.addLabel(.br_if, 0); |
| 1608 | |
| 1594 | 1609 | try cg.lowerToStack(dst); |
| 1595 | 1610 | try cg.lowerToStack(src); |
| 1596 | 1611 | try cg.emitWValue(len); |
| 1597 | 1612 | try cg.addExtended(.memory_copy); |
| 1613 | |
| 1614 | try cg.endBlock(); |
| 1615 | |
| 1598 | 1616 | return; |
| 1599 | 1617 | } |
| 1600 | 1618 | |
| ... | ... | @@ -4782,10 +4800,27 @@ fn memset(cg: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue) |
| 4782 | 4800 | // When bulk_memory is enabled, we lower it to wasm's memset instruction. |
| 4783 | 4801 | // If not, we lower it ourselves. |
| 4784 | 4802 | if (std.Target.wasm.featureSetHas(cg.target.cpu.features, .bulk_memory) and abi_size == 1) { |
| 4803 | try cg.startBlock(.block, .empty); |
| 4804 | |
| 4805 | // Even if `len` is zero, the spec requires an implementation to trap if `ptr + len` is |
| 4806 | // out of memory bounds. This can easily happen in Zig in a case such as: |
| 4807 | // |
| 4808 | // const ptr: [*]u8 = undefined; |
| 4809 | // var len: usize = runtime_zero(); |
| 4810 | // @memset(ptr[0..len], 42); |
| 4811 | // |
| 4812 | // So explicitly avoid using `memory.fill` in the `len == 0` case. Lovely design. |
| 4813 | try cg.emitWValue(len); |
| 4814 | try cg.addTag(.i32_eqz); |
| 4815 | try cg.addLabel(.br_if, 0); |
| 4816 | |
| 4785 | 4817 | try cg.lowerToStack(ptr); |
| 4786 | 4818 | try cg.emitWValue(value); |
| 4787 | 4819 | try cg.emitWValue(len); |
| 4788 | 4820 | try cg.addExtended(.memory_fill); |
| 4821 | |
| 4822 | try cg.endBlock(); |
| 4823 | |
| 4789 | 4824 | return; |
| 4790 | 4825 | } |
| 4791 | 4826 | |