diff options
Diffstat (limited to 'src/wast-parser.cc')
-rw-r--r-- | src/wast-parser.cc | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/src/wast-parser.cc b/src/wast-parser.cc index 11c2947a..e62b10da 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -1686,10 +1686,40 @@ Result WastParser::ParsePlainInstr(std::unique_ptr<Expr>* out_expr) { case TokenType::SimdShuffleOp: { Token token = Consume(); ErrorUnlessOpcodeEnabled(token); - Const const_; - CHECK_RESULT((ParseSimdConst(&const_, Type::I32, sizeof(v128)))); + uint8_t values[16]; + for (int lane = 0; lane < 16; ++lane) { + Location loc = GetLocation(); + + if (!PeekMatch(TokenType::Nat)) { + return ErrorExpected({"a natural number in range [0, 32)"}); + } + + Literal literal = Consume().literal(); + + string_view sv = literal.text; + const char* s = sv.begin(); + const char* end = sv.end(); + Result result; + + uint32_t value = 0; + result = ParseInt32(s, end, &value, ParseIntType::UnsignedOnly); + + if (Failed(result)) { + Error(loc, "invalid literal \"%s\"", literal.text.c_str()); + return Result::Error; + } + + if (value > 31) { + Error(loc, "shuffle index \"%s\" out-of-range [0, 32)", literal.text.c_str()); + return Result::Error; + } + + values[lane] = static_cast<uint8_t>(value); + } + v128 value = Bitcast<v128>(values); + out_expr->reset( - new SimdShuffleOpExpr(token.opcode(), const_.v128_bits, loc)); + new SimdShuffleOpExpr(token.opcode(), value, loc)); break; } |