mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 06:45:24 +00:00
wasm: Add a nontrapping_bulk_memory_len0 feature.
This will mainly be used when targeting our wasm2c implementation which has no problem with zero-length bulk memory operations, as a non-standard extension.
This commit is contained in:
parent
280ced66eb
commit
ea1502974d
@ -598,9 +598,10 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
|
||||
.optimize = .ReleaseSmall,
|
||||
.target = b.resolveTargetQuery(std.Target.Query.parse(.{
|
||||
.arch_os_abi = "wasm32-wasi",
|
||||
// `extended_const` is not supported by the `wasm-opt` version in CI.
|
||||
// `nontrapping_fptoint` is not supported by `wasm2c`.
|
||||
.cpu_features = "baseline-extended_const-nontrapping_fptoint",
|
||||
// * `extended_const` is not supported by the `wasm-opt` version in CI.
|
||||
// * `nontrapping_fptoint` is not supported by `wasm2c`.
|
||||
// * `nontrapping_bulk_memory_len0` is supported by `wasm2c`.
|
||||
.cpu_features = "baseline-extended_const-nontrapping_fptoint+nontrapping_bulk_memory_len0",
|
||||
}) catch unreachable),
|
||||
});
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ pub const Feature = enum {
|
||||
multimemory,
|
||||
multivalue,
|
||||
mutable_globals,
|
||||
nontrapping_bulk_memory_len0,
|
||||
nontrapping_fptoint,
|
||||
reference_types,
|
||||
relaxed_simd,
|
||||
@ -70,6 +71,13 @@ pub const all_features = blk: {
|
||||
.description = "Enable mutable globals",
|
||||
.dependencies = featureSet(&[_]Feature{}),
|
||||
};
|
||||
result[@intFromEnum(Feature.nontrapping_bulk_memory_len0)] = .{
|
||||
.llvm_name = null,
|
||||
.description = "Bulk memory operations with a zero length do not trap",
|
||||
.dependencies = featureSet(&[_]Feature{
|
||||
.bulk_memory,
|
||||
}),
|
||||
};
|
||||
result[@intFromEnum(Feature.nontrapping_fptoint)] = .{
|
||||
.llvm_name = "nontrapping-fptoint",
|
||||
.description = "Enable non-trapping float-to-int conversion operators",
|
||||
|
||||
@ -1591,27 +1591,34 @@ fn memcpy(cg: *CodeGen, dst: WValue, src: WValue, len: WValue) !void {
|
||||
// When bulk_memory is enabled, we lower it to wasm's memcpy instruction.
|
||||
// If not, we lower it ourselves manually
|
||||
if (std.Target.wasm.featureSetHas(cg.target.cpu.features, .bulk_memory)) {
|
||||
try cg.startBlock(.block, .empty);
|
||||
const len0_ok = std.Target.wasm.featureSetHas(cg.target.cpu.features, .nontrapping_bulk_memory_len0);
|
||||
|
||||
// Even if `len` is zero, the spec requires an implementation to trap if `src + len` or
|
||||
// `dst + len` are out of memory bounds. This can easily happen in Zig in a case such as:
|
||||
//
|
||||
// const dst: [*]u8 = undefined;
|
||||
// const src: [*]u8 = undefined;
|
||||
// var len: usize = runtime_zero();
|
||||
// @memcpy(dst[0..len], src[0..len]);
|
||||
//
|
||||
// So explicitly avoid using `memory.copy` in the `len == 0` case. Lovely design.
|
||||
try cg.emitWValue(len);
|
||||
try cg.addTag(.i32_eqz);
|
||||
try cg.addLabel(.br_if, 0);
|
||||
if (!len0_ok) {
|
||||
try cg.startBlock(.block, .empty);
|
||||
|
||||
// Even if `len` is zero, the spec requires an implementation to trap if `src + len` or
|
||||
// `dst + len` are out of memory bounds. This can easily happen in Zig in a case such
|
||||
// as:
|
||||
//
|
||||
// const dst: [*]u8 = undefined;
|
||||
// const src: [*]u8 = undefined;
|
||||
// var len: usize = runtime_zero();
|
||||
// @memcpy(dst[0..len], src[0..len]);
|
||||
//
|
||||
// So explicitly avoid using `memory.copy` in the `len == 0` case. Lovely design.
|
||||
try cg.emitWValue(len);
|
||||
try cg.addTag(.i32_eqz);
|
||||
try cg.addLabel(.br_if, 0);
|
||||
}
|
||||
|
||||
try cg.lowerToStack(dst);
|
||||
try cg.lowerToStack(src);
|
||||
try cg.emitWValue(len);
|
||||
try cg.addExtended(.memory_copy);
|
||||
|
||||
try cg.endBlock();
|
||||
if (!len0_ok) {
|
||||
try cg.endBlock();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -4800,26 +4807,32 @@ fn memset(cg: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue)
|
||||
// When bulk_memory is enabled, we lower it to wasm's memset instruction.
|
||||
// If not, we lower it ourselves.
|
||||
if (std.Target.wasm.featureSetHas(cg.target.cpu.features, .bulk_memory) and abi_size == 1) {
|
||||
try cg.startBlock(.block, .empty);
|
||||
const len0_ok = std.Target.wasm.featureSetHas(cg.target.cpu.features, .nontrapping_bulk_memory_len0);
|
||||
|
||||
// Even if `len` is zero, the spec requires an implementation to trap if `ptr + len` is
|
||||
// out of memory bounds. This can easily happen in Zig in a case such as:
|
||||
//
|
||||
// const ptr: [*]u8 = undefined;
|
||||
// var len: usize = runtime_zero();
|
||||
// @memset(ptr[0..len], 42);
|
||||
//
|
||||
// So explicitly avoid using `memory.fill` in the `len == 0` case. Lovely design.
|
||||
try cg.emitWValue(len);
|
||||
try cg.addTag(.i32_eqz);
|
||||
try cg.addLabel(.br_if, 0);
|
||||
if (!len0_ok) {
|
||||
try cg.startBlock(.block, .empty);
|
||||
|
||||
// Even if `len` is zero, the spec requires an implementation to trap if `ptr + len` is
|
||||
// out of memory bounds. This can easily happen in Zig in a case such as:
|
||||
//
|
||||
// const ptr: [*]u8 = undefined;
|
||||
// var len: usize = runtime_zero();
|
||||
// @memset(ptr[0..len], 42);
|
||||
//
|
||||
// So explicitly avoid using `memory.fill` in the `len == 0` case. Lovely design.
|
||||
try cg.emitWValue(len);
|
||||
try cg.addTag(.i32_eqz);
|
||||
try cg.addLabel(.br_if, 0);
|
||||
}
|
||||
|
||||
try cg.lowerToStack(ptr);
|
||||
try cg.emitWValue(value);
|
||||
try cg.emitWValue(len);
|
||||
try cg.addExtended(.memory_fill);
|
||||
|
||||
try cg.endBlock();
|
||||
if (!len0_ok) {
|
||||
try cg.endBlock();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2826,6 +2826,7 @@ pub const Feature = packed struct(u8) {
|
||||
multimemory,
|
||||
multivalue,
|
||||
@"mutable-globals",
|
||||
@"nontrapping-bulk-memory-len0",
|
||||
@"nontrapping-fptoint",
|
||||
@"reference-types",
|
||||
@"relaxed-simd",
|
||||
|
||||
@ -1033,6 +1033,13 @@ const llvm_targets = [_]LlvmTarget{
|
||||
.zig_name = "wasm",
|
||||
.llvm_name = "WebAssembly",
|
||||
.td_name = "WebAssembly.td",
|
||||
.extra_features = &.{
|
||||
.{
|
||||
.zig_name = "nontrapping_bulk_memory_len0",
|
||||
.desc = "Bulk memory operations with a zero length do not trap",
|
||||
.deps = &.{"bulk_memory"},
|
||||
},
|
||||
},
|
||||
.extra_cpus = &.{
|
||||
.{
|
||||
.llvm_name = null,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user