mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Merge pull request #22098 from alexrp/wasm-generic-baseline
`std.Target`: Use `lime1` as wasm baseline model and `mvp` as generic model
This commit is contained in:
commit
d916954bee
15
build.zig
15
build.zig
@ -594,15 +594,14 @@ pub fn build(b: *std.Build) !void {
|
|||||||
fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
|
fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
|
||||||
const semver = try std.SemanticVersion.parse(version);
|
const semver = try std.SemanticVersion.parse(version);
|
||||||
|
|
||||||
var target_query: std.Target.Query = .{
|
|
||||||
.cpu_arch = .wasm32,
|
|
||||||
.os_tag = .wasi,
|
|
||||||
};
|
|
||||||
target_query.cpu_features_add.addFeature(@intFromEnum(std.Target.wasm.Feature.bulk_memory));
|
|
||||||
|
|
||||||
const exe = addCompilerStep(b, .{
|
const exe = addCompilerStep(b, .{
|
||||||
.optimize = .ReleaseSmall,
|
.optimize = .ReleaseSmall,
|
||||||
.target = b.resolveTargetQuery(target_query),
|
.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_bulk_memory_len0` is supported by `wasm2c`.
|
||||||
|
.cpu_features = "baseline-extended_const+nontrapping_bulk_memory_len0",
|
||||||
|
}) catch unreachable),
|
||||||
});
|
});
|
||||||
|
|
||||||
const exe_options = b.addOptions();
|
const exe_options = b.addOptions();
|
||||||
@ -644,6 +643,8 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
|
|||||||
"wasm-opt",
|
"wasm-opt",
|
||||||
"-Oz",
|
"-Oz",
|
||||||
"--enable-bulk-memory",
|
"--enable-bulk-memory",
|
||||||
|
"--enable-mutable-globals",
|
||||||
|
"--enable-nontrapping-float-to-int",
|
||||||
"--enable-sign-ext",
|
"--enable-sign-ext",
|
||||||
});
|
});
|
||||||
run_opt.addArtifactArg(exe);
|
run_opt.addArtifactArg(exe);
|
||||||
|
|||||||
@ -1958,7 +1958,7 @@ pub const Cpu = struct {
|
|||||||
.x86_64 => &x86.cpu.x86_64,
|
.x86_64 => &x86.cpu.x86_64,
|
||||||
.nvptx, .nvptx64 => &nvptx.cpu.sm_20,
|
.nvptx, .nvptx64 => &nvptx.cpu.sm_20,
|
||||||
.ve => &ve.cpu.generic,
|
.ve => &ve.cpu.generic,
|
||||||
.wasm32, .wasm64 => &wasm.cpu.generic,
|
.wasm32, .wasm64 => &wasm.cpu.mvp,
|
||||||
.xcore => &xcore.cpu.generic,
|
.xcore => &xcore.cpu.generic,
|
||||||
.xtensa => &xtensa.cpu.generic,
|
.xtensa => &xtensa.cpu.generic,
|
||||||
|
|
||||||
@ -2012,6 +2012,7 @@ pub const Cpu = struct {
|
|||||||
else => generic(arch),
|
else => generic(arch),
|
||||||
},
|
},
|
||||||
.xcore => &xcore.cpu.xs1b_generic,
|
.xcore => &xcore.cpu.xs1b_generic,
|
||||||
|
.wasm32, .wasm64 => &wasm.cpu.lime1,
|
||||||
|
|
||||||
else => generic(arch),
|
else => generic(arch),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@ pub const Feature = enum {
|
|||||||
multimemory,
|
multimemory,
|
||||||
multivalue,
|
multivalue,
|
||||||
mutable_globals,
|
mutable_globals,
|
||||||
|
nontrapping_bulk_memory_len0,
|
||||||
nontrapping_fptoint,
|
nontrapping_fptoint,
|
||||||
reference_types,
|
reference_types,
|
||||||
relaxed_simd,
|
relaxed_simd,
|
||||||
@ -70,6 +71,13 @@ pub const all_features = blk: {
|
|||||||
.description = "Enable mutable globals",
|
.description = "Enable mutable globals",
|
||||||
.dependencies = featureSet(&[_]Feature{}),
|
.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)] = .{
|
result[@intFromEnum(Feature.nontrapping_fptoint)] = .{
|
||||||
.llvm_name = "nontrapping-fptoint",
|
.llvm_name = "nontrapping-fptoint",
|
||||||
.description = "Enable non-trapping float-to-int conversion operators",
|
.description = "Enable non-trapping float-to-int conversion operators",
|
||||||
@ -139,6 +147,18 @@ pub const cpu = struct {
|
|||||||
.sign_ext,
|
.sign_ext,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
pub const lime1: CpuModel = .{
|
||||||
|
.name = "lime1",
|
||||||
|
.llvm_name = null,
|
||||||
|
.features = featureSet(&[_]Feature{
|
||||||
|
.bulk_memory,
|
||||||
|
.extended_const,
|
||||||
|
.multivalue,
|
||||||
|
.mutable_globals,
|
||||||
|
.nontrapping_fptoint,
|
||||||
|
.sign_ext,
|
||||||
|
}),
|
||||||
|
};
|
||||||
pub const mvp: CpuModel = .{
|
pub const mvp: CpuModel = .{
|
||||||
.name = "mvp",
|
.name = "mvp",
|
||||||
.llvm_name = "mvp",
|
.llvm_name = "mvp",
|
||||||
|
|||||||
@ -4150,14 +4150,9 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
|
|||||||
.os_tag = .freestanding,
|
.os_tag = .freestanding,
|
||||||
.cpu_features_add = std.Target.wasm.featureSet(&.{
|
.cpu_features_add = std.Target.wasm.featureSet(&.{
|
||||||
.atomics,
|
.atomics,
|
||||||
.bulk_memory,
|
|
||||||
// .extended_const, not supported by Safari
|
// .extended_const, not supported by Safari
|
||||||
.multivalue,
|
|
||||||
.mutable_globals,
|
|
||||||
.nontrapping_fptoint,
|
|
||||||
.reference_types,
|
.reference_types,
|
||||||
//.relaxed_simd, not supported by Firefox or Safari
|
//.relaxed_simd, not supported by Firefox or Safari
|
||||||
.sign_ext,
|
|
||||||
// observed to cause Error occured during wast conversion :
|
// observed to cause Error occured during wast conversion :
|
||||||
// Unknown operator: 0xfd058 in Firefox 117
|
// Unknown operator: 0xfd058 in Firefox 117
|
||||||
//.simd128,
|
//.simd128,
|
||||||
|
|||||||
@ -1591,10 +1591,35 @@ fn memcpy(cg: *CodeGen, dst: WValue, src: WValue, len: WValue) !void {
|
|||||||
// When bulk_memory is enabled, we lower it to wasm's memcpy instruction.
|
// When bulk_memory is enabled, we lower it to wasm's memcpy instruction.
|
||||||
// If not, we lower it ourselves manually
|
// If not, we lower it ourselves manually
|
||||||
if (std.Target.wasm.featureSetHas(cg.target.cpu.features, .bulk_memory)) {
|
if (std.Target.wasm.featureSetHas(cg.target.cpu.features, .bulk_memory)) {
|
||||||
|
const len0_ok = std.Target.wasm.featureSetHas(cg.target.cpu.features, .nontrapping_bulk_memory_len0);
|
||||||
|
|
||||||
|
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(dst);
|
||||||
try cg.lowerToStack(src);
|
try cg.lowerToStack(src);
|
||||||
try cg.emitWValue(len);
|
try cg.emitWValue(len);
|
||||||
try cg.addExtended(.memory_copy);
|
try cg.addExtended(.memory_copy);
|
||||||
|
|
||||||
|
if (!len0_ok) {
|
||||||
|
try cg.endBlock();
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4782,10 +4807,33 @@ 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.
|
// When bulk_memory is enabled, we lower it to wasm's memset instruction.
|
||||||
// If not, we lower it ourselves.
|
// If not, we lower it ourselves.
|
||||||
if (std.Target.wasm.featureSetHas(cg.target.cpu.features, .bulk_memory) and abi_size == 1) {
|
if (std.Target.wasm.featureSetHas(cg.target.cpu.features, .bulk_memory) and abi_size == 1) {
|
||||||
|
const len0_ok = std.Target.wasm.featureSetHas(cg.target.cpu.features, .nontrapping_bulk_memory_len0);
|
||||||
|
|
||||||
|
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.lowerToStack(ptr);
|
||||||
try cg.emitWValue(value);
|
try cg.emitWValue(value);
|
||||||
try cg.emitWValue(len);
|
try cg.emitWValue(len);
|
||||||
try cg.addExtended(.memory_fill);
|
try cg.addExtended(.memory_fill);
|
||||||
|
|
||||||
|
if (!len0_ok) {
|
||||||
|
try cg.endBlock();
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2826,6 +2826,7 @@ pub const Feature = packed struct(u8) {
|
|||||||
multimemory,
|
multimemory,
|
||||||
multivalue,
|
multivalue,
|
||||||
@"mutable-globals",
|
@"mutable-globals",
|
||||||
|
@"nontrapping-bulk-memory-len0",
|
||||||
@"nontrapping-fptoint",
|
@"nontrapping-fptoint",
|
||||||
@"reference-types",
|
@"reference-types",
|
||||||
@"relaxed-simd",
|
@"relaxed-simd",
|
||||||
@ -2835,14 +2836,44 @@ pub const Feature = packed struct(u8) {
|
|||||||
@"shared-mem",
|
@"shared-mem",
|
||||||
|
|
||||||
pub fn fromCpuFeature(feature: std.Target.wasm.Feature) Tag {
|
pub fn fromCpuFeature(feature: std.Target.wasm.Feature) Tag {
|
||||||
return @enumFromInt(@intFromEnum(feature));
|
return switch (feature) {
|
||||||
|
.atomics => .atomics,
|
||||||
|
.bulk_memory => .@"bulk-memory",
|
||||||
|
.exception_handling => .@"exception-handling",
|
||||||
|
.extended_const => .@"extended-const",
|
||||||
|
.half_precision => .@"half-precision",
|
||||||
|
.multimemory => .multimemory,
|
||||||
|
.multivalue => .multivalue,
|
||||||
|
.mutable_globals => .@"mutable-globals",
|
||||||
|
.nontrapping_bulk_memory_len0 => .@"nontrapping-bulk-memory-len0", // Zig extension.
|
||||||
|
.nontrapping_fptoint => .@"nontrapping-fptoint",
|
||||||
|
.reference_types => .@"reference-types",
|
||||||
|
.relaxed_simd => .@"relaxed-simd",
|
||||||
|
.sign_ext => .@"sign-ext",
|
||||||
|
.simd128 => .simd128,
|
||||||
|
.tail_call => .@"tail-call",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toCpuFeature(tag: Tag) ?std.Target.wasm.Feature {
|
pub fn toCpuFeature(tag: Tag) ?std.Target.wasm.Feature {
|
||||||
return if (@intFromEnum(tag) < @typeInfo(std.Target.wasm.Feature).@"enum".fields.len)
|
return switch (tag) {
|
||||||
@enumFromInt(@intFromEnum(tag))
|
.atomics => .atomics,
|
||||||
else
|
.@"bulk-memory" => .bulk_memory,
|
||||||
null;
|
.@"exception-handling" => .exception_handling,
|
||||||
|
.@"extended-const" => .extended_const,
|
||||||
|
.@"half-precision" => .half_precision,
|
||||||
|
.multimemory => .multimemory,
|
||||||
|
.multivalue => .multivalue,
|
||||||
|
.@"mutable-globals" => .mutable_globals,
|
||||||
|
.@"nontrapping-bulk-memory-len0" => .nontrapping_bulk_memory_len0, // Zig extension.
|
||||||
|
.@"nontrapping-fptoint" => .nontrapping_fptoint,
|
||||||
|
.@"reference-types" => .reference_types,
|
||||||
|
.@"relaxed-simd" => .relaxed_simd,
|
||||||
|
.@"sign-ext" => .sign_ext,
|
||||||
|
.simd128 => .simd128,
|
||||||
|
.@"tail-call" => .tail_call,
|
||||||
|
.@"shared-mem" => null, // Linker-only feature.
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const format = @compileError("use @tagName instead");
|
pub const format = @compileError("use @tagName instead");
|
||||||
|
|||||||
@ -109,7 +109,8 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
FILE *out = fopen(argv[2], "wb");
|
FILE *out = fopen(argv[2], "wb");
|
||||||
if (out == NULL) panic("unable to open output file");
|
if (out == NULL) panic("unable to open output file");
|
||||||
fputs("#include <math.h>\n"
|
fputs("#include <float.h>\n"
|
||||||
|
"#include <math.h>\n"
|
||||||
"#include <stdint.h>\n"
|
"#include <stdint.h>\n"
|
||||||
"#include <stdlib.h>\n"
|
"#include <stdlib.h>\n"
|
||||||
"#include <string.h>\n"
|
"#include <string.h>\n"
|
||||||
@ -273,6 +274,47 @@ int main(int argc, char **argv) {
|
|||||||
" return dst;\n"
|
" return dst;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"static uint32_t i32_trunc_sat_f32(const float src) {\n"
|
||||||
|
" if (isnan(src)) return 0;\n"
|
||||||
|
" if (isinf(src)) return (uint32_t)(signbit(src) == 0 ? INT32_MAX : INT32_MIN);\n"
|
||||||
|
" return (uint32_t)(int32_t)src;\n"
|
||||||
|
"}\n"
|
||||||
|
"static uint32_t u32_trunc_sat_f32(const float src) {\n"
|
||||||
|
" if (isnan(src)) return 0;\n"
|
||||||
|
" if (isinf(src)) return signbit(src) == 0 ? UINT32_MAX : 0;\n"
|
||||||
|
" return (uint32_t)src;\n"
|
||||||
|
"}\n"
|
||||||
|
"static uint32_t i32_trunc_sat_f64(const double src) {\n"
|
||||||
|
" if (isnan(src)) return 0;\n"
|
||||||
|
" if (isinf(src)) return (uint32_t)(signbit(src) == 0 ? INT32_MAX : INT32_MIN);\n"
|
||||||
|
" return (uint32_t)(int32_t)src;\n"
|
||||||
|
"}\n"
|
||||||
|
"static uint32_t u32_trunc_sat_f64(const double src) {\n"
|
||||||
|
" if (isnan(src)) return 0;\n"
|
||||||
|
" if (isinf(src)) return signbit(src) == 0 ? UINT32_MAX : 0;\n"
|
||||||
|
" return (uint32_t)src;\n"
|
||||||
|
"}\n"
|
||||||
|
"static uint64_t i64_trunc_sat_f32(const float src) {\n"
|
||||||
|
" if (isnan(src)) return 0;\n"
|
||||||
|
" if (isinf(src)) return (uint64_t)(signbit(src) == 0 ? INT64_MAX : INT64_MIN);\n"
|
||||||
|
" return (uint64_t)(int64_t)src;\n"
|
||||||
|
"}\n"
|
||||||
|
"static uint64_t u64_trunc_sat_f32(const float src) {\n"
|
||||||
|
" if (isnan(src)) return 0;\n"
|
||||||
|
" if (isinf(src)) return signbit(src) == 0 ? UINT64_MAX : 0;\n"
|
||||||
|
" return (uint64_t)src;\n"
|
||||||
|
"}\n"
|
||||||
|
"static uint64_t i64_trunc_sat_f64(const double src) {\n"
|
||||||
|
" if (isnan(src)) return 0;\n"
|
||||||
|
" if (isinf(src)) return (uint64_t)(signbit(src) == 0 ? INT64_MAX : INT64_MIN);\n"
|
||||||
|
" return (uint64_t)(int64_t)src;\n"
|
||||||
|
"}\n"
|
||||||
|
"static uint64_t u64_trunc_sat_f64(const double src) {\n"
|
||||||
|
" if (isnan(src)) return 0;\n"
|
||||||
|
" if (isinf(src)) return signbit(src) == 0 ? UINT64_MAX : 0;\n"
|
||||||
|
" return (uint64_t)src;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
"static uint32_t memory_grow(uint8_t **m, uint32_t *p, uint32_t *c, uint32_t n) {\n"
|
"static uint32_t memory_grow(uint8_t **m, uint32_t *p, uint32_t *c, uint32_t n) {\n"
|
||||||
" uint8_t *new_m = *m;\n"
|
" uint8_t *new_m = *m;\n"
|
||||||
" uint32_t r = *p;\n"
|
" uint32_t r = *p;\n"
|
||||||
@ -2074,14 +2116,61 @@ int main(int argc, char **argv) {
|
|||||||
case WasmOpcode_prefixed:
|
case WasmOpcode_prefixed:
|
||||||
switch (InputStream_readLeb128_u32(&in)) {
|
switch (InputStream_readLeb128_u32(&in)) {
|
||||||
case WasmPrefixedOpcode_i32_trunc_sat_f32_s:
|
case WasmPrefixedOpcode_i32_trunc_sat_f32_s:
|
||||||
|
if (unreachable_depth == 0) {
|
||||||
|
uint32_t lhs = FuncGen_stackPop(&fg);
|
||||||
|
FuncGen_stackPush(&fg, out, WasmValType_i32);
|
||||||
|
fprintf(out, "i32_trunc_sat_f32(l%" PRIu32 ");\n", lhs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WasmPrefixedOpcode_i32_trunc_sat_f32_u:
|
case WasmPrefixedOpcode_i32_trunc_sat_f32_u:
|
||||||
|
if (unreachable_depth == 0) {
|
||||||
|
uint32_t lhs = FuncGen_stackPop(&fg);
|
||||||
|
FuncGen_stackPush(&fg, out, WasmValType_i32);
|
||||||
|
fprintf(out, "u32_trunc_sat_f32(l%" PRIu32 ");\n", lhs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WasmPrefixedOpcode_i32_trunc_sat_f64_s:
|
case WasmPrefixedOpcode_i32_trunc_sat_f64_s:
|
||||||
|
if (unreachable_depth == 0) {
|
||||||
|
uint32_t lhs = FuncGen_stackPop(&fg);
|
||||||
|
FuncGen_stackPush(&fg, out, WasmValType_i32);
|
||||||
|
fprintf(out, "i32_trunc_sat_f64(l%" PRIu32 ");\n", lhs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WasmPrefixedOpcode_i32_trunc_sat_f64_u:
|
case WasmPrefixedOpcode_i32_trunc_sat_f64_u:
|
||||||
|
if (unreachable_depth == 0) {
|
||||||
|
uint32_t lhs = FuncGen_stackPop(&fg);
|
||||||
|
FuncGen_stackPush(&fg, out, WasmValType_i32);
|
||||||
|
fprintf(out, "u32_trunc_sat_f64(l%" PRIu32 ");\n", lhs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WasmPrefixedOpcode_i64_trunc_sat_f32_s:
|
case WasmPrefixedOpcode_i64_trunc_sat_f32_s:
|
||||||
|
if (unreachable_depth == 0) {
|
||||||
|
uint32_t lhs = FuncGen_stackPop(&fg);
|
||||||
|
FuncGen_stackPush(&fg, out, WasmValType_i32);
|
||||||
|
fprintf(out, "i64_trunc_sat_f32(l%" PRIu32 ");\n", lhs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WasmPrefixedOpcode_i64_trunc_sat_f32_u:
|
case WasmPrefixedOpcode_i64_trunc_sat_f32_u:
|
||||||
|
if (unreachable_depth == 0) {
|
||||||
|
uint32_t lhs = FuncGen_stackPop(&fg);
|
||||||
|
FuncGen_stackPush(&fg, out, WasmValType_i32);
|
||||||
|
fprintf(out, "u64_trunc_sat_f32(l%" PRIu32 ");\n", lhs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WasmPrefixedOpcode_i64_trunc_sat_f64_s:
|
case WasmPrefixedOpcode_i64_trunc_sat_f64_s:
|
||||||
|
if (unreachable_depth == 0) {
|
||||||
|
uint32_t lhs = FuncGen_stackPop(&fg);
|
||||||
|
FuncGen_stackPush(&fg, out, WasmValType_i32);
|
||||||
|
fprintf(out, "i64_trunc_sat_f64(l%" PRIu32 ");\n", lhs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WasmPrefixedOpcode_i64_trunc_sat_f64_u:
|
case WasmPrefixedOpcode_i64_trunc_sat_f64_u:
|
||||||
if (unreachable_depth == 0) panic("unimplemented opcode");
|
if (unreachable_depth == 0) {
|
||||||
|
uint32_t lhs = FuncGen_stackPop(&fg);
|
||||||
|
FuncGen_stackPush(&fg, out, WasmValType_i32);
|
||||||
|
fprintf(out, "u64_trunc_sat_f64(l%" PRIu32 ");\n", lhs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case WasmPrefixedOpcode_memory_init:
|
case WasmPrefixedOpcode_memory_init:
|
||||||
(void)InputStream_readLeb128_u32(&in);
|
(void)InputStream_readLeb128_u32(&in);
|
||||||
|
|||||||
@ -1033,6 +1033,27 @@ const llvm_targets = [_]LlvmTarget{
|
|||||||
.zig_name = "wasm",
|
.zig_name = "wasm",
|
||||||
.llvm_name = "WebAssembly",
|
.llvm_name = "WebAssembly",
|
||||||
.td_name = "WebAssembly.td",
|
.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,
|
||||||
|
.zig_name = "lime1",
|
||||||
|
.features = &.{
|
||||||
|
"bulk_memory",
|
||||||
|
"extended_const",
|
||||||
|
"multivalue",
|
||||||
|
"mutable_globals",
|
||||||
|
"nontrapping_fptoint",
|
||||||
|
"sign_ext",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
.{
|
.{
|
||||||
.zig_name = "x86",
|
.zig_name = "x86",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user