diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binaryen-c.cpp | 36 | ||||
-rw-r--r-- | src/binaryen-c.h | 12 | ||||
-rw-r--r-- | src/gen-s-parser.inc | 114 | ||||
-rw-r--r-- | src/ir/cost.h | 20 | ||||
-rw-r--r-- | src/js/binaryen.js-post.js | 64 | ||||
-rw-r--r-- | src/literal.h | 12 | ||||
-rw-r--r-- | src/passes/Print.cpp | 37 | ||||
-rw-r--r-- | src/tools/fuzzing.h | 16 | ||||
-rw-r--r-- | src/wasm-binary.h | 12 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 25 | ||||
-rw-r--r-- | src/wasm.h | 16 | ||||
-rw-r--r-- | src/wasm/literal.cpp | 82 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 48 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 50 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 14 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 9 |
16 files changed, 542 insertions, 25 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index b991f39fa..0b2ff3b78 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -880,6 +880,42 @@ BinaryenOp BinaryenConvertSVecI64x2ToVecF64x2(void) { BinaryenOp BinaryenConvertUVecI64x2ToVecF64x2(void) { return ConvertUVecI64x2ToVecF64x2; } +BinaryenOp BinaryenNarrowSVecI16x8ToVecI8x16(void) { + return NarrowSVecI16x8ToVecI8x16; +} +BinaryenOp BinaryenNarrowUVecI16x8ToVecI8x16(void) { + return NarrowUVecI16x8ToVecI8x16; +} +BinaryenOp BinaryenNarrowSVecI32x4ToVecI16x8(void) { + return NarrowSVecI32x4ToVecI16x8; +} +BinaryenOp BinaryenNarrowUVecI32x4ToVecI16x8(void) { + return NarrowUVecI32x4ToVecI16x8; +} +BinaryenOp BinaryenWidenLowSVecI8x16ToVecI16x8(void) { + return WidenLowSVecI8x16ToVecI16x8; +} +BinaryenOp BinaryenWidenHighSVecI8x16ToVecI16x8(void) { + return WidenHighSVecI8x16ToVecI16x8; +} +BinaryenOp BinaryenWidenLowUVecI8x16ToVecI16x8(void) { + return WidenLowUVecI8x16ToVecI16x8; +} +BinaryenOp BinaryenWidenHighUVecI8x16ToVecI16x8(void) { + return WidenHighUVecI8x16ToVecI16x8; +} +BinaryenOp BinaryenWidenLowSVecI16x8ToVecI32x4(void) { + return WidenLowSVecI16x8ToVecI32x4; +} +BinaryenOp BinaryenWidenHighSVecI16x8ToVecI32x4(void) { + return WidenHighSVecI16x8ToVecI32x4; +} +BinaryenOp BinaryenWidenLowUVecI16x8ToVecI32x4(void) { + return WidenLowUVecI16x8ToVecI32x4; +} +BinaryenOp BinaryenWidenHighUVecI16x8ToVecI32x4(void) { + return WidenHighUVecI16x8ToVecI32x4; +} BinaryenExpressionRef BinaryenBlock(BinaryenModuleRef module, const char* name, diff --git a/src/binaryen-c.h b/src/binaryen-c.h index d306885b0..427edf230 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -514,6 +514,18 @@ BinaryenOp BinaryenConvertSVecI32x4ToVecF32x4(void); BinaryenOp BinaryenConvertUVecI32x4ToVecF32x4(void); BinaryenOp BinaryenConvertSVecI64x2ToVecF64x2(void); BinaryenOp BinaryenConvertUVecI64x2ToVecF64x2(void); +BinaryenOp BinaryenNarrowSVecI16x8ToVecI8x16(void); +BinaryenOp BinaryenNarrowUVecI16x8ToVecI8x16(void); +BinaryenOp BinaryenNarrowSVecI32x4ToVecI16x8(void); +BinaryenOp BinaryenNarrowUVecI32x4ToVecI16x8(void); +BinaryenOp BinaryenWidenLowSVecI8x16ToVecI16x8(void); +BinaryenOp BinaryenWidenHighSVecI8x16ToVecI16x8(void); +BinaryenOp BinaryenWidenLowUVecI8x16ToVecI16x8(void); +BinaryenOp BinaryenWidenHighUVecI8x16ToVecI16x8(void); +BinaryenOp BinaryenWidenLowSVecI16x8ToVecI32x4(void); +BinaryenOp BinaryenWidenHighSVecI16x8ToVecI32x4(void); +BinaryenOp BinaryenWidenLowUVecI16x8ToVecI32x4(void); +BinaryenOp BinaryenWidenHighUVecI16x8ToVecI32x4(void); typedef void* BinaryenExpressionRef; diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 08d911aef..adfeb061d 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -778,13 +778,29 @@ switch (op[0]) { if (strcmp(op, "i16x8.mul") == 0) { return makeBinary(s, BinaryOp::MulVecI16x8); } goto parse_error; case 'n': { - switch (op[8]) { - case '\0': - if (strcmp(op, "i16x8.ne") == 0) { return makeBinary(s, BinaryOp::NeVecI16x8); } - goto parse_error; - case 'g': - if (strcmp(op, "i16x8.neg") == 0) { return makeUnary(s, UnaryOp::NegVecI16x8); } - goto parse_error; + switch (op[7]) { + case 'a': { + switch (op[19]) { + case 's': + if (strcmp(op, "i16x8.narrow_i32x4_s") == 0) { return makeBinary(s, BinaryOp::NarrowSVecI32x4ToVecI16x8); } + goto parse_error; + case 'u': + if (strcmp(op, "i16x8.narrow_i32x4_u") == 0) { return makeBinary(s, BinaryOp::NarrowUVecI32x4ToVecI16x8); } + goto parse_error; + default: goto parse_error; + } + } + case 'e': { + switch (op[8]) { + case '\0': + if (strcmp(op, "i16x8.ne") == 0) { return makeBinary(s, BinaryOp::NeVecI16x8); } + goto parse_error; + case 'g': + if (strcmp(op, "i16x8.neg") == 0) { return makeUnary(s, UnaryOp::NegVecI16x8); } + goto parse_error; + default: goto parse_error; + } + } default: goto parse_error; } } @@ -837,6 +853,33 @@ switch (op[0]) { default: goto parse_error; } } + case 'w': { + switch (op[12]) { + case 'h': { + switch (op[23]) { + case 's': + if (strcmp(op, "i16x8.widen_high_i8x16_s") == 0) { return makeUnary(s, UnaryOp::WidenHighSVecI8x16ToVecI16x8); } + goto parse_error; + case 'u': + if (strcmp(op, "i16x8.widen_high_i8x16_u") == 0) { return makeUnary(s, UnaryOp::WidenHighUVecI8x16ToVecI16x8); } + goto parse_error; + default: goto parse_error; + } + } + case 'l': { + switch (op[22]) { + case 's': + if (strcmp(op, "i16x8.widen_low_i8x16_s") == 0) { return makeUnary(s, UnaryOp::WidenLowSVecI8x16ToVecI16x8); } + goto parse_error; + case 'u': + if (strcmp(op, "i16x8.widen_low_i8x16_u") == 0) { return makeUnary(s, UnaryOp::WidenLowUVecI8x16ToVecI16x8); } + goto parse_error; + default: goto parse_error; + } + } + default: goto parse_error; + } + } default: goto parse_error; } } @@ -1443,6 +1486,33 @@ switch (op[0]) { default: goto parse_error; } } + case 'w': { + switch (op[12]) { + case 'h': { + switch (op[23]) { + case 's': + if (strcmp(op, "i32x4.widen_high_i16x8_s") == 0) { return makeUnary(s, UnaryOp::WidenHighSVecI16x8ToVecI32x4); } + goto parse_error; + case 'u': + if (strcmp(op, "i32x4.widen_high_i16x8_u") == 0) { return makeUnary(s, UnaryOp::WidenHighUVecI16x8ToVecI32x4); } + goto parse_error; + default: goto parse_error; + } + } + case 'l': { + switch (op[22]) { + case 's': + if (strcmp(op, "i32x4.widen_low_i16x8_s") == 0) { return makeUnary(s, UnaryOp::WidenLowSVecI16x8ToVecI32x4); } + goto parse_error; + case 'u': + if (strcmp(op, "i32x4.widen_low_i16x8_u") == 0) { return makeUnary(s, UnaryOp::WidenLowUVecI16x8ToVecI32x4); } + goto parse_error; + default: goto parse_error; + } + } + default: goto parse_error; + } + } default: goto parse_error; } } @@ -2161,13 +2231,29 @@ switch (op[0]) { if (strcmp(op, "i8x16.mul") == 0) { return makeBinary(s, BinaryOp::MulVecI8x16); } goto parse_error; case 'n': { - switch (op[8]) { - case '\0': - if (strcmp(op, "i8x16.ne") == 0) { return makeBinary(s, BinaryOp::NeVecI8x16); } - goto parse_error; - case 'g': - if (strcmp(op, "i8x16.neg") == 0) { return makeUnary(s, UnaryOp::NegVecI8x16); } - goto parse_error; + switch (op[7]) { + case 'a': { + switch (op[19]) { + case 's': + if (strcmp(op, "i8x16.narrow_i16x8_s") == 0) { return makeBinary(s, BinaryOp::NarrowSVecI16x8ToVecI8x16); } + goto parse_error; + case 'u': + if (strcmp(op, "i8x16.narrow_i16x8_u") == 0) { return makeBinary(s, BinaryOp::NarrowUVecI16x8ToVecI8x16); } + goto parse_error; + default: goto parse_error; + } + } + case 'e': { + switch (op[8]) { + case '\0': + if (strcmp(op, "i8x16.ne") == 0) { return makeBinary(s, BinaryOp::NeVecI8x16); } + goto parse_error; + case 'g': + if (strcmp(op, "i8x16.neg") == 0) { return makeUnary(s, UnaryOp::NegVecI8x16); } + goto parse_error; + default: goto parse_error; + } + } default: goto parse_error; } } diff --git a/src/ir/cost.h b/src/ir/cost.h index 5fb32f933..9ff5370f7 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -178,6 +178,14 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> { case ConvertUVecI32x4ToVecF32x4: case ConvertSVecI64x2ToVecF64x2: case ConvertUVecI64x2ToVecF64x2: + case WidenLowSVecI8x16ToVecI16x8: + case WidenHighSVecI8x16ToVecI16x8: + case WidenLowUVecI8x16ToVecI16x8: + case WidenHighUVecI8x16ToVecI16x8: + case WidenLowSVecI16x8ToVecI32x4: + case WidenHighSVecI16x8ToVecI32x4: + case WidenLowUVecI16x8ToVecI32x4: + case WidenHighUVecI16x8ToVecI32x4: return 1; case InvalidUnary: WASM_UNREACHABLE(); @@ -643,6 +651,18 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> { case MaxVecF64x2: ret = 1; break; + case NarrowSVecI16x8ToVecI8x16: + ret = 1; + break; + case NarrowUVecI16x8ToVecI8x16: + ret = 1; + break; + case NarrowSVecI32x4ToVecI16x8: + ret = 1; + break; + case NarrowUVecI32x4ToVecI16x8: + ret = 1; + break; case InvalidBinary: WASM_UNREACHABLE(); } diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 328b0a27d..3cf3e1197 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -394,6 +394,18 @@ Module['ConvertSVecI32x4ToVecF32x4'] = Module['_BinaryenConvertSVecI32x4ToVecF32 Module['ConvertUVecI32x4ToVecF32x4'] = Module['_BinaryenConvertUVecI32x4ToVecF32x4'](); Module['ConvertSVecI64x2ToVecF64x2'] = Module['_BinaryenConvertSVecI64x2ToVecF64x2'](); Module['ConvertUVecI64x2ToVecF64x2'] = Module['_BinaryenConvertUVecI64x2ToVecF64x2'](); +Module['NarrowSVecI16x8ToVecI8x16'] = Module['_BinaryenNarrowSVecI16x8ToVecI8x16'](); +Module['NarrowUVecI16x8ToVecI8x16'] = Module['_BinaryenNarrowUVecI16x8ToVecI8x16'](); +Module['NarrowSVecI32x4ToVecI16x8'] = Module['_BinaryenNarrowSVecI32x4ToVecI16x8'](); +Module['NarrowUVecI32x4ToVecI16x8'] = Module['_BinaryenNarrowUVecI32x4ToVecI16x8'](); +Module['WidenLowSVecI8x16ToVecI16x8'] = Module['_BinaryenWidenLowSVecI8x16ToVecI16x8'](); +Module['WidenHighSVecI8x16ToVecI16x8'] = Module['_BinaryenWidenHighSVecI8x16ToVecI16x8'](); +Module['WidenLowUVecI8x16ToVecI16x8'] = Module['_BinaryenWidenLowUVecI8x16ToVecI16x8'](); +Module['WidenHighUVecI8x16ToVecI16x8'] = Module['_BinaryenWidenHighUVecI8x16ToVecI16x8'](); +Module['WidenLowSVecI16x8ToVecI32x4'] = Module['_BinaryenWidenLowSVecI16x8ToVecI32x4'](); +Module['WidenHighSVecI16x8ToVecI32x4'] = Module['_BinaryenWidenHighSVecI16x8ToVecI32x4'](); +Module['WidenLowUVecI16x8ToVecI32x4'] = Module['_BinaryenWidenLowUVecI16x8ToVecI32x4'](); +Module['WidenHighUVecI16x8ToVecI32x4'] = Module['_BinaryenWidenHighUVecI16x8ToVecI32x4'](); // The size of a single literal in memory as used in Const creation, // which is a little different: we don't want users to need to make @@ -1425,6 +1437,12 @@ function wrapModule(module, self) { 'mul': function(left, right) { return Module['_BinaryenBinary'](module, Module['MulVecI8x16'], left, right); }, + 'narrow_i16x8_s': function(left, right) { + return Module['_BinaryenBinary'](module, Module['NarrowSVecI16x8ToVecI8x16'], left, right); + }, + 'narrow_i16x8_u': function(left, right) { + return Module['_BinaryenBinary'](module, Module['NarrowUVecI16x8ToVecI8x16'], left, right); + }, }; self['i16x8'] = { @@ -1509,6 +1527,24 @@ function wrapModule(module, self) { 'mul': function(left, right) { return Module['_BinaryenBinary'](module, Module['MulVecI16x8'], left, right); }, + 'narrow_i32x4_s': function(left, right) { + return Module['_BinaryenBinary'](module, Module['NarrowSVecI32x4ToVecI16x8'], left, right); + }, + 'narrow_i32x4_u': function(left, right) { + return Module['_BinaryenBinary'](module, Module['NarrowUVecI32x4ToVecI16x8'], left, right); + }, + 'widen_low_i8x16_s': function(value) { + return Module['_BinaryenUnary'](module, Module['WidenLowSVecI8x16ToVecI16x8'], value); + }, + 'widen_high_i8x16_s': function(value) { + return Module['_BinaryenUnary'](module, Module['WidenHighSVecI8x16ToVecI16x8'], value); + }, + 'widen_low_i8x16_u': function(value) { + return Module['_BinaryenUnary'](module, Module['WidenLowUVecI8x16ToVecI16x8'], value); + }, + 'widen_high_i8x16_u': function(value) { + return Module['_BinaryenUnary'](module, Module['WidenHighUVecI8x16ToVecI16x8'], value); + }, }; self['i32x4'] = { @@ -1578,12 +1614,24 @@ function wrapModule(module, self) { 'mul': function(left, right) { return Module['_BinaryenBinary'](module, Module['MulVecI32x4'], left, right); }, - 'trunc_s/f32x4:sat': function(value) { + 'trunc_sat_f32x4_s': function(value) { return Module['_BinaryenUnary'](module, Module['TruncSatSVecF32x4ToVecI32x4'], value); }, - 'trunc_u/f32x4:sat': function(value) { + 'trunc_sat_f32x4_u': function(value) { return Module['_BinaryenUnary'](module, Module['TruncSatUVecF32x4ToVecI32x4'], value); }, + 'widen_low_i16x8_s': function(value) { + return Module['_BinaryenUnary'](module, Module['WidenLowSVecI16x8ToVecI32x4'], value); + }, + 'widen_high_i16x8_s': function(value) { + return Module['_BinaryenUnary'](module, Module['WidenHighSVecI16x8ToVecI32x4'], value); + }, + 'widen_low_i16x8_u': function(value) { + return Module['_BinaryenUnary'](module, Module['WidenLowUVecI16x8ToVecI32x4'], value); + }, + 'widen_high_i16x8_u': function(value) { + return Module['_BinaryenUnary'](module, Module['WidenHighUVecI16x8ToVecI32x4'], value); + }, }; self['i64x2'] = { @@ -1620,10 +1668,10 @@ function wrapModule(module, self) { 'sub': function(left, right) { return Module['_BinaryenBinary'](module, Module['SubVecI64x2'], left, right); }, - 'trunc_s/f64x2:sat': function(value) { + 'trunc_sat_f64x2_s': function(value) { return Module['_BinaryenUnary'](module, Module['TruncSatSVecF64x2ToVecI64x2'], value); }, - 'trunc_u/f64x2:sat': function(value) { + 'trunc_sat_f64x2_u': function(value) { return Module['_BinaryenUnary'](module, Module['TruncSatUVecF64x2ToVecI64x2'], value); }, }; @@ -1689,10 +1737,10 @@ function wrapModule(module, self) { 'max': function(left, right) { return Module['_BinaryenBinary'](module, Module['MaxVecF32x4'], left, right); }, - 'convert_s/i32x4': function(value) { + 'convert_i32x4_s': function(value) { return Module['_BinaryenUnary'](module, Module['ConvertSVecI32x4ToVecF32x4'], value); }, - 'convert_u/i32x4': function(value) { + 'convert_i32x4_u': function(value) { return Module['_BinaryenUnary'](module, Module['ConvertUVecI32x4ToVecF32x4'], value); }, }; @@ -1758,10 +1806,10 @@ function wrapModule(module, self) { 'max': function(left, right) { return Module['_BinaryenBinary'](module, Module['MaxVecF64x2'], left, right); }, - 'convert_s/i64x2': function(value) { + 'convert_i64x2_s': function(value) { return Module['_BinaryenUnary'](module, Module['ConvertSVecI64x2ToVecF64x2'], value); }, - 'convert_u/i64x2': function(value) { + 'convert_i64x2_u': function(value) { return Module['_BinaryenUnary'](module, Module['ConvertUVecI64x2ToVecF64x2'], value); }, }; diff --git a/src/literal.h b/src/literal.h index 9865b8707..98bb1aa7b 100644 --- a/src/literal.h +++ b/src/literal.h @@ -386,6 +386,18 @@ public: Literal convertUToF32x4() const; Literal convertSToF64x2() const; Literal convertUToF64x2() const; + Literal narrowSToVecI8x16(const Literal& other) const; + Literal narrowUToVecI8x16(const Literal& other) const; + Literal narrowSToVecI16x8(const Literal& other) const; + Literal narrowUToVecI16x8(const Literal& other) const; + Literal widenLowSToVecI16x8() const; + Literal widenHighSToVecI16x8() const; + Literal widenLowUToVecI16x8() const; + Literal widenHighUToVecI16x8() const; + Literal widenLowSToVecI32x4() const; + Literal widenHighSToVecI32x4() const; + Literal widenLowUToVecI32x4() const; + Literal widenHighUToVecI32x4() const; private: Literal addSatSI8(const Literal& other) const; diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 20c585859..f8f5c1a56 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -690,6 +690,30 @@ struct PrintExpressionContents case ConvertUVecI64x2ToVecF64x2: o << "f64x2.convert_i64x2_u"; break; + case WidenLowSVecI8x16ToVecI16x8: + o << "i16x8.widen_low_i8x16_s"; + break; + case WidenHighSVecI8x16ToVecI16x8: + o << "i16x8.widen_high_i8x16_s"; + break; + case WidenLowUVecI8x16ToVecI16x8: + o << "i16x8.widen_low_i8x16_u"; + break; + case WidenHighUVecI8x16ToVecI16x8: + o << "i16x8.widen_high_i8x16_u"; + break; + case WidenLowSVecI16x8ToVecI32x4: + o << "i32x4.widen_low_i16x8_s"; + break; + case WidenHighSVecI16x8ToVecI32x4: + o << "i32x4.widen_high_i16x8_s"; + break; + case WidenLowUVecI16x8ToVecI32x4: + o << "i32x4.widen_low_i16x8_u"; + break; + case WidenHighUVecI16x8ToVecI32x4: + o << "i32x4.widen_high_i16x8_u"; + break; case InvalidUnary: WASM_UNREACHABLE(); } @@ -1161,6 +1185,19 @@ struct PrintExpressionContents o << "f64x2.max"; break; + case NarrowSVecI16x8ToVecI8x16: + o << "i8x16.narrow_i16x8_s"; + break; + case NarrowUVecI16x8ToVecI8x16: + o << "i8x16.narrow_i16x8_u"; + break; + case NarrowSVecI32x4ToVecI16x8: + o << "i16x8.narrow_i32x4_s"; + break; + case NarrowUVecI32x4ToVecI16x8: + o << "i16x8.narrow_i32x4_u"; + break; + case InvalidBinary: WASM_UNREACHABLE(); } diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index 82a269740..bc2f54ecd 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -1946,7 +1946,15 @@ private: ConvertSVecI32x4ToVecF32x4, ConvertUVecI32x4ToVecF32x4, ConvertSVecI64x2ToVecF64x2, - ConvertUVecI64x2ToVecF64x2), + ConvertUVecI64x2ToVecF64x2, + WidenLowSVecI8x16ToVecI16x8, + WidenHighSVecI8x16ToVecI16x8, + WidenLowUVecI8x16ToVecI16x8, + WidenHighUVecI8x16ToVecI16x8, + WidenLowSVecI16x8ToVecI32x4, + WidenHighSVecI16x8ToVecI32x4, + WidenLowUVecI16x8ToVecI32x4, + WidenHighUVecI16x8ToVecI32x4), make(v128)}); } WASM_UNREACHABLE(); @@ -2161,7 +2169,11 @@ private: MulVecF64x2, DivVecF64x2, MinVecF64x2, - MaxVecF64x2), + MaxVecF64x2, + NarrowSVecI16x8ToVecI8x16, + NarrowUVecI16x8ToVecI8x16, + NarrowSVecI32x4ToVecI16x8, + NarrowUVecI32x4ToVecI16x8), make(v128), make(v128)}); } diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 1c5fa774a..02f21455e 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -856,6 +856,18 @@ enum ASTNodes { F32x4ConvertUI32x4 = 0xb0, F64x2ConvertSI64x2 = 0xb1, F64x2ConvertUI64x2 = 0xb2, + I8x16NarrowSI16x8 = 0xc6, + I8x16NarrowUI16x8 = 0xc7, + I16x8NarrowSI32x4 = 0xc8, + I16x8NarrowUI32x4 = 0xc9, + I16x8WidenLowSI8x16 = 0xca, + I16x8WidenHighSI8x16 = 0xcb, + I16x8WidenLowUI8x16 = 0xcc, + I16x8WidenHighUI8x16 = 0xcd, + I32x4WidenLowSI16x8 = 0xce, + I32x4WidenHighSI16x8 = 0xcf, + I32x4WidenLowUI16x8 = 0xd0, + I32x4WidenHighUI16x8 = 0xd1, // bulk memory opcodes diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 2c4496f3f..95503fb09 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -448,6 +448,22 @@ public: return value.convertSToF64x2(); case ConvertUVecI64x2ToVecF64x2: return value.convertUToF64x2(); + case WidenLowSVecI8x16ToVecI16x8: + return value.widenLowSToVecI16x8(); + case WidenHighSVecI8x16ToVecI16x8: + return value.widenHighSToVecI16x8(); + case WidenLowUVecI8x16ToVecI16x8: + return value.widenLowUToVecI16x8(); + case WidenHighUVecI8x16ToVecI16x8: + return value.widenHighUToVecI16x8(); + case WidenLowSVecI16x8ToVecI32x4: + return value.widenLowSToVecI32x4(); + case WidenHighSVecI16x8ToVecI32x4: + return value.widenHighSToVecI32x4(); + case WidenLowUVecI16x8ToVecI32x4: + return value.widenLowUToVecI32x4(); + case WidenHighUVecI16x8ToVecI32x4: + return value.widenHighUToVecI32x4(); case InvalidUnary: WASM_UNREACHABLE(); } @@ -789,6 +805,15 @@ public: case MaxVecF64x2: return left.maxF64x2(right); + case NarrowSVecI16x8ToVecI8x16: + return left.narrowSToVecI8x16(right); + case NarrowUVecI16x8ToVecI8x16: + return left.narrowUToVecI8x16(right); + case NarrowSVecI32x4ToVecI16x8: + return left.narrowSToVecI16x8(right); + case NarrowUVecI32x4ToVecI16x8: + return left.narrowUToVecI16x8(right); + case InvalidBinary: WASM_UNREACHABLE(); } diff --git a/src/wasm.h b/src/wasm.h index 9c0f5dec8..2c057b7a4 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -174,6 +174,8 @@ enum UnaryOp { AbsVecF64x2, NegVecF64x2, SqrtVecF64x2, + + // SIMD conversions TruncSatSVecF32x4ToVecI32x4, TruncSatUVecF32x4ToVecI32x4, TruncSatSVecF64x2ToVecI64x2, @@ -182,6 +184,14 @@ enum UnaryOp { ConvertUVecI32x4ToVecF32x4, ConvertSVecI64x2ToVecF64x2, ConvertUVecI64x2ToVecF64x2, + WidenLowSVecI8x16ToVecI16x8, + WidenHighSVecI8x16ToVecI16x8, + WidenLowUVecI8x16ToVecI16x8, + WidenHighUVecI8x16ToVecI16x8, + WidenLowSVecI16x8ToVecI32x4, + WidenHighSVecI16x8ToVecI32x4, + WidenLowUVecI16x8ToVecI32x4, + WidenHighUVecI16x8ToVecI32x4, InvalidUnary }; @@ -375,6 +385,12 @@ enum BinaryOp { MinVecF64x2, MaxVecF64x2, + // SIMD Conversion + NarrowSVecI16x8ToVecI8x16, + NarrowUVecI16x8ToVecI8x16, + NarrowSVecI32x4ToVecI16x8, + NarrowUVecI32x4ToVecI16x8, + InvalidBinary }; diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 43adec6f6..b382d1a3d 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -1785,4 +1785,86 @@ Literal Literal::bitselectV128(const Literal& left, return andV128(left).orV128(notV128().andV128(right)); } +template<typename T> struct TwiceWidth {}; +template<> struct TwiceWidth<int8_t> { using type = int16_t; }; +template<> struct TwiceWidth<int16_t> { using type = int32_t; }; + +template<typename T> +Literal saturating_narrow( + typename TwiceWidth<typename std::make_signed<T>::type>::type val) { + using WideT = typename TwiceWidth<typename std::make_signed<T>::type>::type; + if (val > WideT(std::numeric_limits<T>::max())) { + val = std::numeric_limits<T>::max(); + } else if (val < WideT(std::numeric_limits<T>::min())) { + val = std::numeric_limits<T>::min(); + } + return Literal(int32_t(val)); +} + +template<size_t Lanes, + typename T, + LaneArray<Lanes / 2> (Literal::*IntoLanes)() const> +Literal narrow(const Literal& low, const Literal& high) { + LaneArray<Lanes / 2> lowLanes = (low.*IntoLanes)(); + LaneArray<Lanes / 2> highLanes = (high.*IntoLanes)(); + LaneArray<Lanes> result; + for (size_t i = 0; i < Lanes / 2; ++i) { + result[i] = saturating_narrow<T>(lowLanes[i].geti32()); + result[Lanes / 2 + i] = saturating_narrow<T>(highLanes[i].geti32()); + } + return Literal(result); +} + +Literal Literal::narrowSToVecI8x16(const Literal& other) const { + return narrow<16, int8_t, &Literal::getLanesSI16x8>(*this, other); +} +Literal Literal::narrowUToVecI8x16(const Literal& other) const { + return narrow<16, uint8_t, &Literal::getLanesSI16x8>(*this, other); +} +Literal Literal::narrowSToVecI16x8(const Literal& other) const { + return narrow<8, int16_t, &Literal::getLanesI32x4>(*this, other); +} +Literal Literal::narrowUToVecI16x8(const Literal& other) const { + return narrow<8, uint16_t, &Literal::getLanesI32x4>(*this, other); +} + +enum class LaneOrder { Low, High }; + +template<size_t Lanes, + LaneArray<Lanes * 2> (Literal::*IntoLanes)() const, + LaneOrder Side> +Literal widen(const Literal& vec) { + LaneArray<Lanes* 2> lanes = (vec.*IntoLanes)(); + LaneArray<Lanes> result; + for (size_t i = 0; i < Lanes; ++i) { + result[i] = lanes[(Side == LaneOrder::Low) ? i : i + Lanes]; + } + return Literal(result); +} + +Literal Literal::widenLowSToVecI16x8() const { + return widen<8, &Literal::getLanesSI8x16, LaneOrder::Low>(*this); +} +Literal Literal::widenHighSToVecI16x8() const { + return widen<8, &Literal::getLanesSI8x16, LaneOrder::High>(*this); +} +Literal Literal::widenLowUToVecI16x8() const { + return widen<8, &Literal::getLanesUI8x16, LaneOrder::Low>(*this); +} +Literal Literal::widenHighUToVecI16x8() const { + return widen<8, &Literal::getLanesUI8x16, LaneOrder::High>(*this); +} +Literal Literal::widenLowSToVecI32x4() const { + return widen<4, &Literal::getLanesSI16x8, LaneOrder::Low>(*this); +} +Literal Literal::widenHighSToVecI32x4() const { + return widen<4, &Literal::getLanesSI16x8, LaneOrder::High>(*this); +} +Literal Literal::widenLowUToVecI32x4() const { + return widen<4, &Literal::getLanesUI16x8, LaneOrder::Low>(*this); +} +Literal Literal::widenHighUToVecI32x4() const { + return widen<4, &Literal::getLanesUI16x8, LaneOrder::High>(*this); +} + } // namespace wasm diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 529a3ff52..7b9d9c624 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -3943,6 +3943,22 @@ bool WasmBinaryBuilder::maybeVisitSIMDBinary(Expression*& out, uint32_t code) { curr = allocator.alloc<Binary>(); curr->op = MaxVecF64x2; break; + case BinaryConsts::I8x16NarrowSI16x8: + curr = allocator.alloc<Binary>(); + curr->op = NarrowSVecI16x8ToVecI8x16; + break; + case BinaryConsts::I8x16NarrowUI16x8: + curr = allocator.alloc<Binary>(); + curr->op = NarrowUVecI16x8ToVecI8x16; + break; + case BinaryConsts::I16x8NarrowSI32x4: + curr = allocator.alloc<Binary>(); + curr->op = NarrowSVecI32x4ToVecI16x8; + break; + case BinaryConsts::I16x8NarrowUI32x4: + curr = allocator.alloc<Binary>(); + curr->op = NarrowUVecI32x4ToVecI16x8; + break; default: return false; } @@ -4090,6 +4106,38 @@ bool WasmBinaryBuilder::maybeVisitSIMDUnary(Expression*& out, uint32_t code) { curr = allocator.alloc<Unary>(); curr->op = ConvertUVecI64x2ToVecF64x2; break; + case BinaryConsts::I16x8WidenLowSI8x16: + curr = allocator.alloc<Unary>(); + curr->op = WidenLowSVecI8x16ToVecI16x8; + break; + case BinaryConsts::I16x8WidenHighSI8x16: + curr = allocator.alloc<Unary>(); + curr->op = WidenHighSVecI8x16ToVecI16x8; + break; + case BinaryConsts::I16x8WidenLowUI8x16: + curr = allocator.alloc<Unary>(); + curr->op = WidenLowUVecI8x16ToVecI16x8; + break; + case BinaryConsts::I16x8WidenHighUI8x16: + curr = allocator.alloc<Unary>(); + curr->op = WidenHighUVecI8x16ToVecI16x8; + break; + case BinaryConsts::I32x4WidenLowSI16x8: + curr = allocator.alloc<Unary>(); + curr->op = WidenLowSVecI16x8ToVecI32x4; + break; + case BinaryConsts::I32x4WidenHighSI16x8: + curr = allocator.alloc<Unary>(); + curr->op = WidenHighSVecI16x8ToVecI32x4; + break; + case BinaryConsts::I32x4WidenLowUI16x8: + curr = allocator.alloc<Unary>(); + curr->op = WidenLowUVecI16x8ToVecI32x4; + break; + case BinaryConsts::I32x4WidenHighUI16x8: + curr = allocator.alloc<Unary>(); + curr->op = WidenHighUVecI16x8ToVecI32x4; + break; default: return false; } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 498a53cb2..1da6e9015 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -917,6 +917,38 @@ void BinaryInstWriter::visitUnary(Unary* curr) { o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F64x2ConvertUI64x2); break; + case WidenLowSVecI8x16ToVecI16x8: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I16x8WidenLowSI8x16); + break; + case WidenHighSVecI8x16ToVecI16x8: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I16x8WidenHighSI8x16); + break; + case WidenLowUVecI8x16ToVecI16x8: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I16x8WidenLowUI8x16); + break; + case WidenHighUVecI8x16ToVecI16x8: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I16x8WidenHighUI8x16); + break; + case WidenLowSVecI16x8ToVecI32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I32x4WidenLowSI16x8); + break; + case WidenHighSVecI16x8ToVecI32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I32x4WidenHighSI16x8); + break; + case WidenLowUVecI16x8ToVecI32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I32x4WidenLowUI16x8); + break; + case WidenHighUVecI16x8ToVecI32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I32x4WidenHighUI16x8); + break; case InvalidUnary: WASM_UNREACHABLE(); } @@ -1394,6 +1426,24 @@ void BinaryInstWriter::visitBinary(Binary* curr) { case MaxVecF64x2: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F64x2Max); break; + + case NarrowSVecI16x8ToVecI8x16: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I8x16NarrowSI16x8); + break; + case NarrowUVecI16x8ToVecI8x16: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I8x16NarrowUI16x8); + break; + case NarrowSVecI32x4ToVecI16x8: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I16x8NarrowSI32x4); + break; + case NarrowUVecI32x4ToVecI16x8: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I16x8NarrowUI32x4); + break; + case InvalidBinary: WASM_UNREACHABLE(); } diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index f2d6c259b..e64e2ef73 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -1330,7 +1330,11 @@ void FunctionValidator::visitBinary(Binary* curr) { case MulVecF64x2: case DivVecF64x2: case MinVecF64x2: - case MaxVecF64x2: { + case MaxVecF64x2: + case NarrowSVecI16x8ToVecI8x16: + case NarrowUVecI16x8ToVecI8x16: + case NarrowSVecI32x4ToVecI16x8: + case NarrowUVecI32x4ToVecI16x8: { shouldBeEqualOrFirstIsUnreachable( curr->left->type, v128, curr, "v128 op"); shouldBeEqualOrFirstIsUnreachable( @@ -1528,6 +1532,14 @@ void FunctionValidator::visitUnary(Unary* curr) { case ConvertUVecI32x4ToVecF32x4: case ConvertSVecI64x2ToVecF64x2: case ConvertUVecI64x2ToVecF64x2: + case WidenLowSVecI8x16ToVecI16x8: + case WidenHighSVecI8x16ToVecI16x8: + case WidenLowUVecI8x16ToVecI16x8: + case WidenHighUVecI8x16ToVecI16x8: + case WidenLowSVecI16x8ToVecI32x4: + case WidenHighSVecI16x8ToVecI32x4: + case WidenLowUVecI16x8ToVecI32x4: + case WidenHighUVecI16x8ToVecI32x4: shouldBeEqual(curr->type, v128, curr, "expected v128 type"); shouldBeEqual(curr->value->type, v128, curr, "expected v128 operand"); break; diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index ec23b5c94..f8439ea96 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -749,6 +749,14 @@ void Unary::finalize() { case ConvertUVecI32x4ToVecF32x4: case ConvertSVecI64x2ToVecF64x2: case ConvertUVecI64x2ToVecF64x2: + case WidenLowSVecI8x16ToVecI16x8: + case WidenHighSVecI8x16ToVecI16x8: + case WidenLowUVecI8x16ToVecI16x8: + case WidenHighUVecI8x16ToVecI16x8: + case WidenLowSVecI16x8ToVecI32x4: + case WidenHighSVecI16x8ToVecI32x4: + case WidenLowUVecI16x8ToVecI32x4: + case WidenHighUVecI16x8ToVecI32x4: type = v128; break; case AnyTrueVecI8x16: @@ -761,6 +769,7 @@ void Unary::finalize() { case AllTrueVecI64x2: type = i32; break; + case InvalidUnary: WASM_UNREACHABLE(); } |