Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 67 additions & 31 deletions src/parser/wast-parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,73 @@ Result<NaNKind> nan(Lexer& in) {
}

Result<ExpectedResult> result(Lexer& in) {
if (in.takeSExprStart("v128.const"sv)) {
LaneResults results;
auto& lanes = results.lanes;
results.type = in.buffer[in.getPos()] == 'f' ? LaneResults::LaneType::Float
: LaneResults::LaneType::Int;
Comment thread
stevenfontanella marked this conversation as resolved.
Outdated

if (in.takeKeyword("i8x16"sv)) {
for (int i = 0; i < 16; ++i) {
auto int_ = in.takeI8();
if (!int_) {
return in.err("expected i8 immediate");
}
lanes.push_back(Literal(static_cast<uint32_t>(*int_)));
}
} else if (in.takeKeyword("i16x8"sv)) {
for (int i = 0; i < 8; ++i) {
auto int_ = in.takeI16();
if (!int_) {
return in.err("expected i16 immediate");
}
lanes.push_back(Literal(static_cast<uint32_t>(*int_)));
}
} else if (in.takeKeyword("i32x4"sv)) {
for (int i = 0; i < 4; ++i) {
auto int_ = in.takeI32();
if (!int_) {
return in.err("expected i32 immediate");
}
lanes.push_back(Literal(static_cast<uint32_t>(*int_)));
}
} else if (in.takeKeyword("i64x2"sv)) {
for (int i = 0; i < 2; ++i) {
auto int_ = in.takeI64();
if (!int_) {
return in.err("expected i64 immediate");
}
lanes.push_back(Literal(*int_));
}
} else if (in.takeKeyword("f32x4"sv)) {
for (int i = 0; i < 4; ++i) {
if (auto f = in.takeF32()) {
lanes.push_back(Literal(*f));
} else {
auto kind = nan(in);
CHECK_ERR(kind);
lanes.push_back(NaNResult{*kind, Type::f32});
}
}
} else if (in.takeKeyword("f64x2"sv)) {
for (int i = 0; i < 2; ++i) {
if (auto f = in.takeF64()) {
lanes.push_back(Literal(*f));
} else {
auto kind = nan(in);
CHECK_ERR(kind);
lanes.push_back(NaNResult{*kind, Type::f64});
}
}
} else {
return in.err("unexpected vector shape");
}
if (!in.takeRParen()) {
return in.err("expected end of v128.const");
}
return results;
}

Lexer constLexer = in;
auto c = const_(constLexer);
// TODO: Generating and discarding errors like this can lead to quadratic
Expand Down Expand Up @@ -198,37 +265,6 @@ Result<ExpectedResult> result(Lexer& in) {
return NaNResult{*kind, Type::f64};
}

if (in.takeSExprStart("v128.const"sv)) {
LaneResults lanes;
if (in.takeKeyword("f32x4"sv)) {
for (int i = 0; i < 4; ++i) {
if (auto f = in.takeF32()) {
lanes.push_back(Literal(*f));
} else {
auto kind = nan(in);
CHECK_ERR(kind);
lanes.push_back(NaNResult{*kind, Type::f32});
}
}
} else if (in.takeKeyword("f64x2"sv)) {
for (int i = 0; i < 2; ++i) {
if (auto f = in.takeF64()) {
lanes.push_back(Literal(*f));
} else {
auto kind = nan(in);
CHECK_ERR(kind);
lanes.push_back(NaNResult{*kind, Type::f64});
}
}
} else {
return in.err("unexpected vector shape");
}
if (!in.takeRParen()) {
return in.err("expected end of v128.const");
}
return lanes;
}

if (in.takeSExprStart("ref.null")) {
if (!in.takeRParen()) {
return in.err("expected end of ref.null");
Expand Down
10 changes: 9 additions & 1 deletion src/parser/wat-parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,15 @@ struct NaNResult {

using LaneResult = std::variant<Literal, NaNResult>;

using LaneResults = std::vector<LaneResult>;
struct LaneResults {
enum class LaneType {
Unknown,
Comment thread
stevenfontanella marked this conversation as resolved.
Outdated
Int,
Float,
};
std::vector<LaneResult> lanes;
LaneType type = LaneType::Unknown;
};

using ExpectedResult =
std::variant<Literal, NullRefResult, RefResult, NaNResult, LaneResults>;
Expand Down
49 changes: 32 additions & 17 deletions src/tools/wasm-shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,28 +400,43 @@ struct Shell {
err << e->msg << atIndex();
return Err{err.str()};
}
} else if (auto* lanes = std::get_if<LaneResults>(&expected)) {
} else if (auto* l = std::get_if<LaneResults>(&expected)) {
auto* lanes = &l->lanes;

auto check = [&](int size, const auto& vals) -> Result<> {
for (int i = 0; i < size; ++i) {
Comment thread
stevenfontanella marked this conversation as resolved.
Outdated
auto check = checkLane(vals[i], (*lanes)[i], i);
if (auto* e = check.getErr()) {
err << e->msg << atIndex();
return Err{err.str()};
}
}
return Ok{};
};

bool isFloat = l->type == WATParser::LaneResults::LaneType::Float;
switch (lanes->size()) {
// Use unsigned values for the smaller types here to avoid sign
// extension when storing 8/16-bit values in 32-bit ints. This isn't
// needed for i32 and i64.
case 16: {
// There is no f8.
CHECK_ERR(check(16, val.getLanesUI8x16()));
break;
}
case 8: {
CHECK_ERR(
check(8, isFloat ? val.getLanesF16x8() : val.getLanesUI16x8()));
break;
}
case 4: {
auto vals = val.getLanesF32x4();
for (Index i = 0; i < 4; ++i) {
auto check = checkLane(vals[i], (*lanes)[i], i);
if (auto* e = check.getErr()) {
err << e->msg << atIndex();
return Err{err.str()};
}
}
CHECK_ERR(
check(4, isFloat ? val.getLanesF32x4() : val.getLanesI32x4()));
break;
}
case 2: {
auto vals = val.getLanesF64x2();
for (Index i = 0; i < 2; ++i) {
auto check = checkLane(vals[i], (*lanes)[i], i);
if (auto* e = check.getErr()) {
err << e->msg << atIndex();
return Err{err.str()};
}
}
CHECK_ERR(
check(2, isFloat ? val.getLanesF64x2() : val.getLanesI64x2()));
break;
}
default:
Expand Down
Loading