summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binaryen-c.cpp36
-rw-r--r--src/binaryen-c.h12
-rw-r--r--src/gen-s-parser.inc114
-rw-r--r--src/ir/cost.h20
-rw-r--r--src/js/binaryen.js-post.js64
-rw-r--r--src/literal.h12
-rw-r--r--src/passes/Print.cpp37
-rw-r--r--src/tools/fuzzing.h16
-rw-r--r--src/wasm-binary.h12
-rw-r--r--src/wasm-interpreter.h25
-rw-r--r--src/wasm.h16
-rw-r--r--src/wasm/literal.cpp82
-rw-r--r--src/wasm/wasm-binary.cpp48
-rw-r--r--src/wasm/wasm-stack.cpp50
-rw-r--r--src/wasm/wasm-validator.cpp14
-rw-r--r--src/wasm/wasm.cpp9
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();
}