summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@chromium.org>2016-03-09 13:05:41 -0800
committerDerek Schuff <dschuff@chromium.org>2016-03-09 13:05:41 -0800
commit0c0850ed5e2a2e82ad42f803894defcc53692ccd (patch)
treec7225399210801476deaf21f093a865fbf5b54ef
parent1b45938aadd6e03e9210d88436be9c393623fb42 (diff)
downloadbinaryen-0c0850ed5e2a2e82ad42f803894defcc53692ccd.tar.gz
binaryen-0c0850ed5e2a2e82ad42f803894defcc53692ccd.tar.bz2
binaryen-0c0850ed5e2a2e82ad42f803894defcc53692ccd.zip
Implement rotates
-rwxr-xr-xcheck.py2
-rw-r--r--src/passes/Print.cpp2
-rw-r--r--src/wasm-binary.h8
-rw-r--r--src/wasm-interpreter.h4
-rw-r--r--src/wasm-s-parser.h6
-rw-r--r--src/wasm.h29
m---------test/spec0
7 files changed, 48 insertions, 3 deletions
diff --git a/check.py b/check.py
index 926282eab..272e1394c 100755
--- a/check.py
+++ b/check.py
@@ -354,7 +354,7 @@ for t in tests:
print '\n[ checking binaryen-shell spec testcases... ]\n'
if len(requested) == 0:
- BLACKLIST = ['i32.wast', 'i64.wast']
+ BLACKLIST = []
spec_tests = [os.path.join('spec', t) for t in sorted(os.listdir(os.path.join('test', 'spec'))) if t not in BLACKLIST]
else:
spec_tests = requested[:]
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 91c4040f6..b69f7a977 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -284,6 +284,8 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
case Shl: o << "shl"; break;
case ShrU: o << "shr_u"; break;
case ShrS: o << "shr_s"; break;
+ case RotL: o << "rotl"; break;
+ case RotR: o << "rotr"; break;
case Div: o << "div"; break;
case CopySign: o << "copysign"; break;
case Min: o << "min"; break;
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 47da374c1..715c06287 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -287,6 +287,10 @@ enum ASTNodes {
F64ConvertF32 = 0xb2,
F64ReinterpretI64 = 0xb3,
I64ReinterpretF64 = 0xb5,
+ I32RotR = 0xb6,
+ I32RotL = 0xb7,
+ I64RotR = 0xb8,
+ I64RotL = 0xb9,
I32ReinterpretF32 = 0xfe, // XXX not in v8 spec doc
I32LoadMem8S = 0x20,
@@ -883,6 +887,8 @@ public:
case Shl: INT_TYPED_CODE(Shl);;
case ShrU: INT_TYPED_CODE(ShrU);
case ShrS: INT_TYPED_CODE(ShrS);
+ case RotL: INT_TYPED_CODE(RotL);
+ case RotR: INT_TYPED_CODE(RotR);
case Div: FLOAT_TYPED_CODE(Div);
case CopySign: FLOAT_TYPED_CODE(CopySign);
case Min: FLOAT_TYPED_CODE(Min);
@@ -1593,6 +1599,8 @@ public:
INT_TYPED_CODE(Shl);
INT_TYPED_CODE(ShrU);
INT_TYPED_CODE(ShrS);
+ INT_TYPED_CODE(RotL);
+ INT_TYPED_CODE(RotR);
FLOAT_TYPED_CODE(Div);
FLOAT_TYPED_CODE(CopySign);
FLOAT_TYPED_CODE(Min);
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 2edaad846..f6a3e1027 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -464,6 +464,8 @@ private:
case Shl: return left.shl(right.and_(Literal(int32_t(31))));
case ShrU: return left.shrU(right.and_(Literal(int32_t(31))));
case ShrS: return left.shrS(right.and_(Literal(int32_t(31))));
+ case RotL: return left.rotL(right);
+ case RotR: return left.rotR(right);
case Eq: return left.eq(right);
case Ne: return left.ne(right);
case LtS: return left.ltS(right);
@@ -505,6 +507,8 @@ private:
case Shl: return left.shl(right.and_(Literal(int64_t(63))));
case ShrU: return left.shrU(right.and_(Literal(int64_t(63))));
case ShrS: return left.shrS(right.and_(Literal(int64_t(63))));
+ case RotL: return left.rotL(right);
+ case RotR: return left.rotR(right);
case Eq: return left.eq(right);
case Ne: return left.ne(right);
case LtS: return left.ltS(right);
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 1cd614c1d..cfabbf52d 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -430,7 +430,8 @@ public:
WasmType type = stringToWasmType(str, false, true);
// Local copy to index into op without bounds checking.
constexpr size_t maxNameSize = 15;
- char op[maxNameSize + 1] = { '\0' };
+ char op[maxNameSize + 1];
+ memset(op, 0, maxNameSize + 1); // ensure the whole string is cleared.
strncpy(op, dot + 1, maxNameSize);
switch (op[0]) {
case 'a': {
@@ -523,6 +524,9 @@ public:
if (op[2] == 'm') return makeBinary(s, op[4] == 'u' ? BinaryOp::RemU : BinaryOp::RemS, type);
if (op[2] == 'i') return makeUnary(s, isWasmTypeFloat(type) ? UnaryOp::ReinterpretInt : UnaryOp::ReinterpretFloat, type);
}
+ if (op[1] == 'o' && op[2] == 't') {
+ return makeBinary(s, op[3] == 'l' ? BinaryOp::RotL : BinaryOp::RotR, type);
+ }
abort_on(op);
}
case 's': {
diff --git a/src/wasm.h b/src/wasm.h
index ce6b9d294..26b5e18e1 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -45,6 +45,7 @@
#include <cassert>
#include <cmath>
+#include <climits>
#include <cstddef>
#include <cstdint>
#include <cstring>
@@ -503,6 +504,32 @@ public:
default: WASM_UNREACHABLE();
}
}
+ template <typename T>
+ static T rol(T val, T count) {
+ T mask = sizeof(T) * CHAR_BIT - 1;
+ count &= mask;
+ return (val << count) | (val >> (-count & mask));
+ }
+ Literal rotL(const Literal& other) const {
+ switch (type) {
+ case WasmType::i32: return Literal(rol(uint32_t(i32), uint32_t(other.i32)));
+ case WasmType::i64: return Literal(rol(uint64_t(i64), uint64_t(other.i64)));
+ default: WASM_UNREACHABLE();
+ }
+ }
+ template <typename T>
+ static T ror (T val, T count) {
+ T mask = sizeof(T) * CHAR_BIT - 1;
+ count &= mask;
+ return (val >> count) | (val << (-count & mask));
+ }
+ Literal rotR(const Literal& other) const {
+ switch (type) {
+ case WasmType::i32: return Literal(ror(uint32_t(i32), uint32_t(other.i32)));
+ case WasmType::i64: return Literal(ror(uint64_t(i64), uint64_t(other.i64)));
+ default: WASM_UNREACHABLE();
+ }
+ }
Literal eq(const Literal& other) const {
switch (type) {
@@ -676,7 +703,7 @@ enum UnaryOp {
enum BinaryOp {
Add, Sub, Mul, // int or float
- DivS, DivU, RemS, RemU, And, Or, Xor, Shl, ShrU, ShrS, // int
+ DivS, DivU, RemS, RemU, And, Or, Xor, Shl, ShrU, ShrS, RotL, RotR, // int
Div, CopySign, Min, Max, // float
// relational ops
Eq, Ne, // int or float
diff --git a/test/spec b/test/spec
-Subproject 3fdec99e94434b58d7477834c2be6b81c1aea91
+Subproject 6e6134562e70299bea9e85fc845e5ce210e96db