| author | |
| committer | |
| log | d916954bee0f477bcada0693d4aa952197cf1eef |
| tree | a28e9b0f02df80b4c484119dffc48c8e5c16d7d2 |
| parent | f3c29dcb247be5e50d2d05f9fb2e814ebf115a86 |
| parent | 68c6a88770420b897467073ec328ddc2bb3317d6 |
| signature |
`std.Target`: Use `lime1` as wasm baseline model and `mvp` as generic model8 files changed, 226 insertions(+), 20 deletions(-)
build.zig+8-7| ... | @@ -594,15 +594,14 @@ pub fn build(b: *std.Build) !void { | ... | @@ -594,15 +594,14 @@ pub fn build(b: *std.Build) !void { |
| 594 | fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { | 594 | fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { |
| 595 | const semver = try std.SemanticVersion.parse(version); | 595 | const semver = try std.SemanticVersion.parse(version); |
| 596 | 596 | ||
| 597 | var target_query: std.Target.Query = .{ | ||
| 598 | .cpu_arch = .wasm32, | ||
| 599 | .os_tag = .wasi, | ||
| 600 | }; | ||
| 601 | target_query.cpu_features_add.addFeature(@intFromEnum(std.Target.wasm.Feature.bulk_memory)); | ||
| 602 | |||
| 603 | const exe = addCompilerStep(b, .{ | 597 | const exe = addCompilerStep(b, .{ |
| 604 | .optimize = .ReleaseSmall, | 598 | .optimize = .ReleaseSmall, |
| 605 | .target = b.resolveTargetQuery(target_query), | 599 | .target = b.resolveTargetQuery(std.Target.Query.parse(.{ |
| 600 | .arch_os_abi = "wasm32-wasi", | ||
| 601 | // * `extended_const` is not supported by the `wasm-opt` version in CI. | ||
| 602 | // * `nontrapping_bulk_memory_len0` is supported by `wasm2c`. | ||
| 603 | .cpu_features = "baseline-extended_const+nontrapping_bulk_memory_len0", | ||
| 604 | }) catch unreachable), | ||
| 606 | }); | 605 | }); |
| 607 | 606 | ||
| 608 | const exe_options = b.addOptions(); | 607 | const exe_options = b.addOptions(); |
| ... | @@ -644,6 +643,8 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { | ... | @@ -644,6 +643,8 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { |
| 644 | "wasm-opt", | 643 | "wasm-opt", |
| 645 | "-Oz", | 644 | "-Oz", |
| 646 | "--enable-bulk-memory", | 645 | "--enable-bulk-memory", |
| 646 | "--enable-mutable-globals", | ||
| 647 | "--enable-nontrapping-float-to-int", | ||
| 647 | "--enable-sign-ext", | 648 | "--enable-sign-ext", |
| 648 | }); | 649 | }); |
| 649 | run_opt.addArtifactArg(exe); | 650 | run_opt.addArtifactArg(exe); |
lib/std/Target.zig+2-1| ... | @@ -1958,7 +1958,7 @@ pub const Cpu = struct { | ... | @@ -1958,7 +1958,7 @@ pub const Cpu = struct { |
| 1958 | .x86_64 => &x86.cpu.x86_64, | 1958 | .x86_64 => &x86.cpu.x86_64, |
| 1959 | .nvptx, .nvptx64 => &nvptx.cpu.sm_20, | 1959 | .nvptx, .nvptx64 => &nvptx.cpu.sm_20, |
| 1960 | .ve => &ve.cpu.generic, | 1960 | .ve => &ve.cpu.generic, |
| 1961 | .wasm32, .wasm64 => &wasm.cpu.generic, | 1961 | .wasm32, .wasm64 => &wasm.cpu.mvp, |
| 1962 | .xcore => &xcore.cpu.generic, | 1962 | .xcore => &xcore.cpu.generic, |
| 1963 | .xtensa => &xtensa.cpu.generic, | 1963 | .xtensa => &xtensa.cpu.generic, |
| 1964 | 1964 | ||
| ... | @@ -2012,6 +2012,7 @@ pub const Cpu = struct { | ... | @@ -2012,6 +2012,7 @@ pub const Cpu = struct { |
| 2012 | else => generic(arch), | 2012 | else => generic(arch), |
| 2013 | }, | 2013 | }, |
| 2014 | .xcore => &xcore.cpu.xs1b_generic, | 2014 | .xcore => &xcore.cpu.xs1b_generic, |
| 2015 | .wasm32, .wasm64 => &wasm.cpu.lime1, | ||
| 2015 | 2016 | ||
| 2016 | else => generic(arch), | 2017 | else => generic(arch), |
| 2017 | }; | 2018 | }; |
lib/std/Target/wasm.zig+20| ... | @@ -13,6 +13,7 @@ pub const Feature = enum { | ... | @@ -13,6 +13,7 @@ pub const Feature = enum { |
| 13 | multimemory, | 13 | multimemory, |
| 14 | multivalue, | 14 | multivalue, |
| 15 | mutable_globals, | 15 | mutable_globals, |
| 16 | nontrapping_bulk_memory_len0, | ||
| 16 | nontrapping_fptoint, | 17 | nontrapping_fptoint, |
| 17 | reference_types, | 18 | reference_types, |
| 18 | relaxed_simd, | 19 | relaxed_simd, |
| ... | @@ -70,6 +71,13 @@ pub const all_features = blk: { | ... | @@ -70,6 +71,13 @@ pub const all_features = blk: { |
| 70 | .description = "Enable mutable globals", | 71 | .description = "Enable mutable globals", |
| 71 | .dependencies = featureSet(&[_]Feature{}), | 72 | .dependencies = featureSet(&[_]Feature{}), |
| 72 | }; | 73 | }; |
| 74 | result[@intFromEnum(Feature.nontrapping_bulk_memory_len0)] = .{ | ||
| 75 | .llvm_name = null, | ||
| 76 | .description = "Bulk memory operations with a zero length do not trap", | ||
| 77 | .dependencies = featureSet(&[_]Feature{ | ||
| 78 | .bulk_memory, | ||
| 79 | }), | ||
| 80 | }; | ||
| 73 | result[@intFromEnum(Feature.nontrapping_fptoint)] = .{ | 81 | result[@intFromEnum(Feature.nontrapping_fptoint)] = .{ |
| 74 | .llvm_name = "nontrapping-fptoint", | 82 | .llvm_name = "nontrapping-fptoint", |
| 75 | .description = "Enable non-trapping float-to-int conversion operators", | 83 | .description = "Enable non-trapping float-to-int conversion operators", |
| ... | @@ -139,6 +147,18 @@ pub const cpu = struct { | ... | @@ -139,6 +147,18 @@ pub const cpu = struct { |
| 139 | .sign_ext, | 147 | .sign_ext, |
| 140 | }), | 148 | }), |
| 141 | }; | 149 | }; |
| 150 | pub const lime1: CpuModel = .{ | ||
| 151 | .name = "lime1", | ||
| 152 | .llvm_name = null, | ||
| 153 | .features = featureSet(&[_]Feature{ | ||
| 154 | .bulk_memory, | ||
| 155 | .extended_const, | ||
| 156 | .multivalue, | ||
| 157 | .mutable_globals, | ||
| 158 | .nontrapping_fptoint, | ||
| 159 | .sign_ext, | ||
| 160 | }), | ||
| 161 | }; | ||
| 142 | pub const mvp: CpuModel = .{ | 162 | pub const mvp: CpuModel = .{ |
| 143 | .name = "mvp", | 163 | .name = "mvp", |
| 144 | .llvm_name = "mvp", | 164 | .llvm_name = "mvp", |
src/Compilation.zig-5| ... | @@ -4150,14 +4150,9 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye | ... | @@ -4150,14 +4150,9 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 4150 | .os_tag = .freestanding, | 4150 | .os_tag = .freestanding, |
| 4151 | .cpu_features_add = std.Target.wasm.featureSet(&.{ | 4151 | .cpu_features_add = std.Target.wasm.featureSet(&.{ |
| 4152 | .atomics, | 4152 | .atomics, |
| 4153 | .bulk_memory, | ||
| 4154 | // .extended_const, not supported by Safari | 4153 | // .extended_const, not supported by Safari |
| 4155 | .multivalue, | ||
| 4156 | .mutable_globals, | ||
| 4157 | .nontrapping_fptoint, | ||
| 4158 | .reference_types, | 4154 | .reference_types, |
| 4159 | //.relaxed_simd, not supported by Firefox or Safari | 4155 | //.relaxed_simd, not supported by Firefox or Safari |
| 4160 | .sign_ext, | ||
| 4161 | // observed to cause Error occured during wast conversion : | 4156 | // observed to cause Error occured during wast conversion : |
| 4162 | // Unknown operator: 0xfd058 in Firefox 117 | 4157 | // Unknown operator: 0xfd058 in Firefox 117 |
| 4163 | //.simd128, | 4158 | //.simd128, |
src/arch/wasm/CodeGen.zig+48| ... | @@ -1591,10 +1591,35 @@ fn memcpy(cg: *CodeGen, dst: WValue, src: WValue, len: WValue) !void { | ... | @@ -1591,10 +1591,35 @@ fn memcpy(cg: *CodeGen, dst: WValue, src: WValue, len: WValue) !void { |
| 1591 | // When bulk_memory is enabled, we lower it to wasm's memcpy instruction. | 1591 | // When bulk_memory is enabled, we lower it to wasm's memcpy instruction. |
| 1592 | // If not, we lower it ourselves manually | 1592 | // If not, we lower it ourselves manually |
| 1593 | if (std.Target.wasm.featureSetHas(cg.target.cpu.features, .bulk_memory)) { | 1593 | if (std.Target.wasm.featureSetHas(cg.target.cpu.features, .bulk_memory)) { |
| 1594 | const len0_ok = std.Target.wasm.featureSetHas(cg.target.cpu.features, .nontrapping_bulk_memory_len0); | ||
| 1595 | |||
| 1596 | if (!len0_ok) { | ||
| 1597 | try cg.startBlock(.block, .empty); | ||
| 1598 | |||
| 1599 | // Even if `len` is zero, the spec requires an implementation to trap if `src + len` or | ||
| 1600 | // `dst + len` are out of memory bounds. This can easily happen in Zig in a case such | ||
| 1601 | // as: | ||
| 1602 | // | ||
| 1603 | // const dst: [*]u8 = undefined; | ||
| 1604 | // const src: [*]u8 = undefined; | ||
| 1605 | // var len: usize = runtime_zero(); | ||
| 1606 | // @memcpy(dst[0..len], src[0..len]); | ||
| 1607 | // | ||
| 1608 | // So explicitly avoid using `memory.copy` in the `len == 0` case. Lovely design. | ||
| 1609 | try cg.emitWValue(len); | ||
| 1610 | try cg.addTag(.i32_eqz); | ||
| 1611 | try cg.addLabel(.br_if, 0); | ||
| 1612 | } | ||
| 1613 | |||
| 1594 | try cg.lowerToStack(dst); | 1614 | try cg.lowerToStack(dst); |
| 1595 | try cg.lowerToStack(src); | 1615 | try cg.lowerToStack(src); |
| 1596 | try cg.emitWValue(len); | 1616 | try cg.emitWValue(len); |
| 1597 | try cg.addExtended(.memory_copy); | 1617 | try cg.addExtended(.memory_copy); |
| 1618 | |||
| 1619 | if (!len0_ok) { | ||
| 1620 | try cg.endBlock(); | ||
| 1621 | } | ||
| 1622 | |||
| 1598 | return; | 1623 | return; |
| 1599 | } | 1624 | } |
| 1600 | 1625 | ||
| ... | @@ -4782,10 +4807,33 @@ fn memset(cg: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue) | ... | @@ -4782,10 +4807,33 @@ fn memset(cg: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue) |
| 4782 | // When bulk_memory is enabled, we lower it to wasm's memset instruction. | 4807 | // When bulk_memory is enabled, we lower it to wasm's memset instruction. |
| 4783 | // If not, we lower it ourselves. | 4808 | // If not, we lower it ourselves. |
| 4784 | if (std.Target.wasm.featureSetHas(cg.target.cpu.features, .bulk_memory) and abi_size == 1) { | 4809 | if (std.Target.wasm.featureSetHas(cg.target.cpu.features, .bulk_memory) and abi_size == 1) { |
| 4810 | const len0_ok = std.Target.wasm.featureSetHas(cg.target.cpu.features, .nontrapping_bulk_memory_len0); | ||
| 4811 | |||
| 4812 | if (!len0_ok) { | ||
| 4813 | try cg.startBlock(.block, .empty); | ||
| 4814 | |||
| 4815 | // Even if `len` is zero, the spec requires an implementation to trap if `ptr + len` is | ||
| 4816 | // out of memory bounds. This can easily happen in Zig in a case such as: | ||
| 4817 | // | ||
| 4818 | // const ptr: [*]u8 = undefined; | ||
| 4819 | // var len: usize = runtime_zero(); | ||
| 4820 | // @memset(ptr[0..len], 42); | ||
| 4821 | // | ||
| 4822 | // So explicitly avoid using `memory.fill` in the `len == 0` case. Lovely design. | ||
| 4823 | try cg.emitWValue(len); | ||
| 4824 | try cg.addTag(.i32_eqz); | ||
| 4825 | try cg.addLabel(.br_if, 0); | ||
| 4826 | } | ||
| 4827 | |||
| 4785 | try cg.lowerToStack(ptr); | 4828 | try cg.lowerToStack(ptr); |
| 4786 | try cg.emitWValue(value); | 4829 | try cg.emitWValue(value); |
| 4787 | try cg.emitWValue(len); | 4830 | try cg.emitWValue(len); |
| 4788 | try cg.addExtended(.memory_fill); | 4831 | try cg.addExtended(.memory_fill); |
| 4832 | |||
| 4833 | if (!len0_ok) { | ||
| 4834 | try cg.endBlock(); | ||
| 4835 | } | ||
| 4836 | |||
| 4789 | return; | 4837 | return; |
| 4790 | } | 4838 | } |
| 4791 | 4839 |
src/link/Wasm.zig+36-5| ... | @@ -2826,6 +2826,7 @@ pub const Feature = packed struct(u8) { | ... | @@ -2826,6 +2826,7 @@ pub const Feature = packed struct(u8) { |
| 2826 | multimemory, | 2826 | multimemory, |
| 2827 | multivalue, | 2827 | multivalue, |
| 2828 | @"mutable-globals", | 2828 | @"mutable-globals", |
| 2829 | @"nontrapping-bulk-memory-len0", | ||
| 2829 | @"nontrapping-fptoint", | 2830 | @"nontrapping-fptoint", |
| 2830 | @"reference-types", | 2831 | @"reference-types", |
| 2831 | @"relaxed-simd", | 2832 | @"relaxed-simd", |
| ... | @@ -2835,14 +2836,44 @@ pub const Feature = packed struct(u8) { | ... | @@ -2835,14 +2836,44 @@ pub const Feature = packed struct(u8) { |
| 2835 | @"shared-mem", | 2836 | @"shared-mem", |
| 2836 | 2837 | ||
| 2837 | pub fn fromCpuFeature(feature: std.Target.wasm.Feature) Tag { | 2838 | pub fn fromCpuFeature(feature: std.Target.wasm.Feature) Tag { |
| 2838 | return @enumFromInt(@intFromEnum(feature)); | 2839 | return switch (feature) { |
| 2840 | .atomics => .atomics, | ||
| 2841 | .bulk_memory => .@"bulk-memory", | ||
| 2842 | .exception_handling => .@"exception-handling", | ||
| 2843 | .extended_const => .@"extended-const", | ||
| 2844 | .half_precision => .@"half-precision", | ||
| 2845 | .multimemory => .multimemory, | ||
| 2846 | .multivalue => .multivalue, | ||
| 2847 | .mutable_globals => .@"mutable-globals", | ||
| 2848 | .nontrapping_bulk_memory_len0 => .@"nontrapping-bulk-memory-len0", // Zig extension. | ||
| 2849 | .nontrapping_fptoint => .@"nontrapping-fptoint", | ||
| 2850 | .reference_types => .@"reference-types", | ||
| 2851 | .relaxed_simd => .@"relaxed-simd", | ||
| 2852 | .sign_ext => .@"sign-ext", | ||
| 2853 | .simd128 => .simd128, | ||
| 2854 | .tail_call => .@"tail-call", | ||
| 2855 | }; | ||
| 2839 | } | 2856 | } |
| 2840 | 2857 | ||
| 2841 | pub fn toCpuFeature(tag: Tag) ?std.Target.wasm.Feature { | 2858 | pub fn toCpuFeature(tag: Tag) ?std.Target.wasm.Feature { |
| 2842 | return if (@intFromEnum(tag) < @typeInfo(std.Target.wasm.Feature).@"enum".fields.len) | 2859 | return switch (tag) { |
| 2843 | @enumFromInt(@intFromEnum(tag)) | 2860 | .atomics => .atomics, |
| 2844 | else | 2861 | .@"bulk-memory" => .bulk_memory, |
| 2845 | null; | 2862 | .@"exception-handling" => .exception_handling, |
| 2863 | .@"extended-const" => .extended_const, | ||
| 2864 | .@"half-precision" => .half_precision, | ||
| 2865 | .multimemory => .multimemory, | ||
| 2866 | .multivalue => .multivalue, | ||
| 2867 | .@"mutable-globals" => .mutable_globals, | ||
| 2868 | .@"nontrapping-bulk-memory-len0" => .nontrapping_bulk_memory_len0, // Zig extension. | ||
| 2869 | .@"nontrapping-fptoint" => .nontrapping_fptoint, | ||
| 2870 | .@"reference-types" => .reference_types, | ||
| 2871 | .@"relaxed-simd" => .relaxed_simd, | ||
| 2872 | .@"sign-ext" => .sign_ext, | ||
| 2873 | .simd128 => .simd128, | ||
| 2874 | .@"tail-call" => .tail_call, | ||
| 2875 | .@"shared-mem" => null, // Linker-only feature. | ||
| 2876 | }; | ||
| 2846 | } | 2877 | } |
| 2847 | 2878 | ||
| 2848 | pub const format = @compileError("use @tagName instead"); | 2879 | pub const format = @compileError("use @tagName instead"); |
stage1/wasm2c.c+91-2| ... | @@ -109,7 +109,8 @@ int main(int argc, char **argv) { | ... | @@ -109,7 +109,8 @@ int main(int argc, char **argv) { |
| 109 | 109 | ||
| 110 | FILE *out = fopen(argv[2], "wb"); | 110 | FILE *out = fopen(argv[2], "wb"); |
| 111 | if (out == NULL) panic("unable to open output file"); | 111 | if (out == NULL) panic("unable to open output file"); |
| 112 | fputs("#include <math.h>\n" | 112 | fputs("#include <float.h>\n" |
| 113 | "#include <math.h>\n" | ||
| 113 | "#include <stdint.h>\n" | 114 | "#include <stdint.h>\n" |
| 114 | "#include <stdlib.h>\n" | 115 | "#include <stdlib.h>\n" |
| 115 | "#include <string.h>\n" | 116 | "#include <string.h>\n" |
| ... | @@ -273,6 +274,47 @@ int main(int argc, char **argv) { | ... | @@ -273,6 +274,47 @@ int main(int argc, char **argv) { |
| 273 | " return dst;\n" | 274 | " return dst;\n" |
| 274 | "}\n" | 275 | "}\n" |
| 275 | "\n" | 276 | "\n" |
| 277 | "static uint32_t i32_trunc_sat_f32(const float src) {\n" | ||
| 278 | " if (isnan(src)) return 0;\n" | ||
| 279 | " if (isinf(src)) return (uint32_t)(signbit(src) == 0 ? INT32_MAX : INT32_MIN);\n" | ||
| 280 | " return (uint32_t)(int32_t)src;\n" | ||
| 281 | "}\n" | ||
| 282 | "static uint32_t u32_trunc_sat_f32(const float src) {\n" | ||
| 283 | " if (isnan(src)) return 0;\n" | ||
| 284 | " if (isinf(src)) return signbit(src) == 0 ? UINT32_MAX : 0;\n" | ||
| 285 | " return (uint32_t)src;\n" | ||
| 286 | "}\n" | ||
| 287 | "static uint32_t i32_trunc_sat_f64(const double src) {\n" | ||
| 288 | " if (isnan(src)) return 0;\n" | ||
| 289 | " if (isinf(src)) return (uint32_t)(signbit(src) == 0 ? INT32_MAX : INT32_MIN);\n" | ||
| 290 | " return (uint32_t)(int32_t)src;\n" | ||
| 291 | "}\n" | ||
| 292 | "static uint32_t u32_trunc_sat_f64(const double src) {\n" | ||
| 293 | " if (isnan(src)) return 0;\n" | ||
| 294 | " if (isinf(src)) return signbit(src) == 0 ? UINT32_MAX : 0;\n" | ||
| 295 | " return (uint32_t)src;\n" | ||
| 296 | "}\n" | ||
| 297 | "static uint64_t i64_trunc_sat_f32(const float src) {\n" | ||
| 298 | " if (isnan(src)) return 0;\n" | ||
| 299 | " if (isinf(src)) return (uint64_t)(signbit(src) == 0 ? INT64_MAX : INT64_MIN);\n" | ||
| 300 | " return (uint64_t)(int64_t)src;\n" | ||
| 301 | "}\n" | ||
| 302 | "static uint64_t u64_trunc_sat_f32(const float src) {\n" | ||
| 303 | " if (isnan(src)) return 0;\n" | ||
| 304 | " if (isinf(src)) return signbit(src) == 0 ? UINT64_MAX : 0;\n" | ||
| 305 | " return (uint64_t)src;\n" | ||
| 306 | "}\n" | ||
| 307 | "static uint64_t i64_trunc_sat_f64(const double src) {\n" | ||
| 308 | " if (isnan(src)) return 0;\n" | ||
| 309 | " if (isinf(src)) return (uint64_t)(signbit(src) == 0 ? INT64_MAX : INT64_MIN);\n" | ||
| 310 | " return (uint64_t)(int64_t)src;\n" | ||
| 311 | "}\n" | ||
| 312 | "static uint64_t u64_trunc_sat_f64(const double src) {\n" | ||
| 313 | " if (isnan(src)) return 0;\n" | ||
| 314 | " if (isinf(src)) return signbit(src) == 0 ? UINT64_MAX : 0;\n" | ||
| 315 | " return (uint64_t)src;\n" | ||
| 316 | "}\n" | ||
| 317 | "\n" | ||
| 276 | "static uint32_t memory_grow(uint8_t **m, uint32_t *p, uint32_t *c, uint32_t n) {\n" | 318 | "static uint32_t memory_grow(uint8_t **m, uint32_t *p, uint32_t *c, uint32_t n) {\n" |
| 277 | " uint8_t *new_m = *m;\n" | 319 | " uint8_t *new_m = *m;\n" |
| 278 | " uint32_t r = *p;\n" | 320 | " uint32_t r = *p;\n" |
| ... | @@ -2074,14 +2116,61 @@ int main(int argc, char **argv) { | ... | @@ -2074,14 +2116,61 @@ int main(int argc, char **argv) { |
| 2074 | case WasmOpcode_prefixed: | 2116 | case WasmOpcode_prefixed: |
| 2075 | switch (InputStream_readLeb128_u32(&in)) { | 2117 | switch (InputStream_readLeb128_u32(&in)) { |
| 2076 | case WasmPrefixedOpcode_i32_trunc_sat_f32_s: | 2118 | case WasmPrefixedOpcode_i32_trunc_sat_f32_s: |
| 2119 | if (unreachable_depth == 0) { | ||
| 2120 | uint32_t lhs = FuncGen_stackPop(&fg); | ||
| 2121 | FuncGen_stackPush(&fg, out, WasmValType_i32); | ||
| 2122 | fprintf(out, "i32_trunc_sat_f32(l%" PRIu32 ");\n", lhs); | ||
| 2123 | } | ||
| 2124 | break; | ||
| 2077 | case WasmPrefixedOpcode_i32_trunc_sat_f32_u: | 2125 | case WasmPrefixedOpcode_i32_trunc_sat_f32_u: |
| 2126 | if (unreachable_depth == 0) { | ||
| 2127 | uint32_t lhs = FuncGen_stackPop(&fg); | ||
| 2128 | FuncGen_stackPush(&fg, out, WasmValType_i32); | ||
| 2129 | fprintf(out, "u32_trunc_sat_f32(l%" PRIu32 ");\n", lhs); | ||
| 2130 | } | ||
| 2131 | break; | ||
| 2078 | case WasmPrefixedOpcode_i32_trunc_sat_f64_s: | 2132 | case WasmPrefixedOpcode_i32_trunc_sat_f64_s: |
| 2133 | if (unreachable_depth == 0) { | ||
| 2134 | uint32_t lhs = FuncGen_stackPop(&fg); | ||
| 2135 | FuncGen_stackPush(&fg, out, WasmValType_i32); | ||
| 2136 | fprintf(out, "i32_trunc_sat_f64(l%" PRIu32 ");\n", lhs); | ||
| 2137 | } | ||
| 2138 | break; | ||
| 2079 | case WasmPrefixedOpcode_i32_trunc_sat_f64_u: | 2139 | case WasmPrefixedOpcode_i32_trunc_sat_f64_u: |
| 2140 | if (unreachable_depth == 0) { | ||
| 2141 | uint32_t lhs = FuncGen_stackPop(&fg); | ||
| 2142 | FuncGen_stackPush(&fg, out, WasmValType_i32); | ||
| 2143 | fprintf(out, "u32_trunc_sat_f64(l%" PRIu32 ");\n", lhs); | ||
| 2144 | } | ||
| 2145 | break; | ||
| 2080 | case WasmPrefixedOpcode_i64_trunc_sat_f32_s: | 2146 | case WasmPrefixedOpcode_i64_trunc_sat_f32_s: |
| 2147 | if (unreachable_depth == 0) { | ||
| 2148 | uint32_t lhs = FuncGen_stackPop(&fg); | ||
| 2149 | FuncGen_stackPush(&fg, out, WasmValType_i32); | ||
| 2150 | fprintf(out, "i64_trunc_sat_f32(l%" PRIu32 ");\n", lhs); | ||
| 2151 | } | ||
| 2152 | break; | ||
| 2081 | case WasmPrefixedOpcode_i64_trunc_sat_f32_u: | 2153 | case WasmPrefixedOpcode_i64_trunc_sat_f32_u: |
| 2154 | if (unreachable_depth == 0) { | ||
| 2155 | uint32_t lhs = FuncGen_stackPop(&fg); | ||
| 2156 | FuncGen_stackPush(&fg, out, WasmValType_i32); | ||
| 2157 | fprintf(out, "u64_trunc_sat_f32(l%" PRIu32 ");\n", lhs); | ||
| 2158 | } | ||
| 2159 | break; | ||
| 2082 | case WasmPrefixedOpcode_i64_trunc_sat_f64_s: | 2160 | case WasmPrefixedOpcode_i64_trunc_sat_f64_s: |
| 2161 | if (unreachable_depth == 0) { | ||
| 2162 | uint32_t lhs = FuncGen_stackPop(&fg); | ||
| 2163 | FuncGen_stackPush(&fg, out, WasmValType_i32); | ||
| 2164 | fprintf(out, "i64_trunc_sat_f64(l%" PRIu32 ");\n", lhs); | ||
| 2165 | } | ||
| 2166 | break; | ||
| 2083 | case WasmPrefixedOpcode_i64_trunc_sat_f64_u: | 2167 | case WasmPrefixedOpcode_i64_trunc_sat_f64_u: |
| 2084 | if (unreachable_depth == 0) panic("unimplemented opcode"); | 2168 | if (unreachable_depth == 0) { |
| 2169 | uint32_t lhs = FuncGen_stackPop(&fg); | ||
| 2170 | FuncGen_stackPush(&fg, out, WasmValType_i32); | ||
| 2171 | fprintf(out, "u64_trunc_sat_f64(l%" PRIu32 ");\n", lhs); | ||
| 2172 | } | ||
| 2173 | break; | ||
| 2085 | 2174 | ||
| 2086 | case WasmPrefixedOpcode_memory_init: | 2175 | case WasmPrefixedOpcode_memory_init: |
| 2087 | (void)InputStream_readLeb128_u32(&in); | 2176 | (void)InputStream_readLeb128_u32(&in); |
tools/update_cpu_features.zig+21| ... | @@ -1033,6 +1033,27 @@ const llvm_targets = [_]LlvmTarget{ | ... | @@ -1033,6 +1033,27 @@ const llvm_targets = [_]LlvmTarget{ |
| 1033 | .zig_name = "wasm", | 1033 | .zig_name = "wasm", |
| 1034 | .llvm_name = "WebAssembly", | 1034 | .llvm_name = "WebAssembly", |
| 1035 | .td_name = "WebAssembly.td", | 1035 | .td_name = "WebAssembly.td", |
| 1036 | .extra_features = &.{ | ||
| 1037 | .{ | ||
| 1038 | .zig_name = "nontrapping_bulk_memory_len0", | ||
| 1039 | .desc = "Bulk memory operations with a zero length do not trap", | ||
| 1040 | .deps = &.{"bulk_memory"}, | ||
| 1041 | }, | ||
| 1042 | }, | ||
| 1043 | .extra_cpus = &.{ | ||
| 1044 | .{ | ||
| 1045 | .llvm_name = null, | ||
| 1046 | .zig_name = "lime1", | ||
| 1047 | .features = &.{ | ||
| 1048 | "bulk_memory", | ||
| 1049 | "extended_const", | ||
| 1050 | "multivalue", | ||
| 1051 | "mutable_globals", | ||
| 1052 | "nontrapping_fptoint", | ||
| 1053 | "sign_ext", | ||
| 1054 | }, | ||
| 1055 | }, | ||
| 1056 | }, | ||
| 1036 | }, | 1057 | }, |
| 1037 | .{ | 1058 | .{ |
| 1038 | .zig_name = "x86", | 1059 | .zig_name = "x86", |