summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-validator.cpp
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2020-03-05 15:52:44 -0800
committerGitHub <noreply@github.com>2020-03-05 15:52:44 -0800
commit9e3dbb1f668a14341e9aebae479537d4a26095a5 (patch)
tree9857d50c3373c3f6320ca3f2586bd499bc40b224 /src/wasm/wasm-validator.cpp
parent3a275d0627da443cce93631a64d78e7b3f441416 (diff)
downloadbinaryen-9e3dbb1f668a14341e9aebae479537d4a26095a5.tar.gz
binaryen-9e3dbb1f668a14341e9aebae479537d4a26095a5.tar.bz2
binaryen-9e3dbb1f668a14341e9aebae479537d4a26095a5.zip
Initial multivalue support (#2675)
Implements parsing and emitting of tuple creation and extraction and tuple-typed control flow for both the text and binary formats. TODO: - Extend Precompute/interpreter to handle tuple values - C and JS API support/testing - Figure out how to lower in stack IR - Fuzzing
Diffstat (limited to 'src/wasm/wasm-validator.cpp')
-rw-r--r--src/wasm/wasm-validator.cpp68
1 files changed, 65 insertions, 3 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 484376358..1db8ed7c0 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -319,6 +319,8 @@ public:
void visitThrow(Throw* curr);
void visitRethrow(Rethrow* curr);
void visitBrOnExn(BrOnExn* curr);
+ void visitTupleMake(TupleMake* curr);
+ void visitTupleExtract(TupleExtract* curr);
void visitFunction(Function* curr);
// helpers
@@ -386,6 +388,11 @@ void FunctionValidator::noteLabelName(Name name) {
}
void FunctionValidator::visitBlock(Block* curr) {
+ if (!getModule()->features.hasMultivalue()) {
+ shouldBeTrue(!curr->type.isMulti(),
+ curr,
+ "Multivalue block type (multivalue is not enabled)");
+ }
// if we are break'ed to, then the value must be right for us
if (curr->name.is()) {
noteLabelName(curr->name);
@@ -1744,6 +1751,14 @@ void FunctionValidator::visitSelect(Select* curr) {
curr->condition->type == Type::i32,
curr,
"select condition must be valid");
+ if (curr->ifTrue->type != Type::unreachable) {
+ shouldBeTrue(
+ curr->ifTrue->type.isSingle(), curr, "select value may not be a tuple");
+ }
+ if (curr->ifFalse->type != Type::unreachable) {
+ shouldBeTrue(
+ curr->ifFalse->type.isSingle(), curr, "select value may not be a tuple");
+ }
if (curr->type != Type::unreachable) {
shouldBeTrue(Type::isSubType(curr->ifTrue->type, curr->type),
curr,
@@ -1887,10 +1902,46 @@ void FunctionValidator::visitBrOnExn(BrOnExn* curr) {
}
}
+void FunctionValidator::visitTupleMake(TupleMake* curr) {
+ std::vector<Type> types;
+ for (auto* op : curr->operands) {
+ if (op->type == Type::unreachable) {
+ shouldBeTrue(
+ curr->type == Type::unreachable,
+ curr,
+ "If tuple.make has an unreachable operand, it must be unreachable");
+ return;
+ }
+ types.push_back(op->type);
+ }
+ shouldBeTrue(Type(types) == curr->type,
+ curr,
+ "Type of tuple.make does not match types of its operands");
+}
+
+void FunctionValidator::visitTupleExtract(TupleExtract* curr) {
+ if (curr->tuple->type == Type::unreachable) {
+ shouldBeTrue(
+ curr->type == Type::unreachable,
+ curr,
+ "If tuple.extract has an unreachable operand, it must be unreachable");
+ } else {
+ shouldBeTrue(curr->index < curr->tuple->type.size(),
+ curr,
+ "tuple.extract index out of bounds");
+ shouldBeTrue(
+ curr->type == curr->tuple->type.expand()[curr->index],
+ curr,
+ "tuple.extract type does not match the type of the extracted element");
+ }
+}
+
void FunctionValidator::visitFunction(Function* curr) {
- shouldBeTrue(!curr->sig.results.isMulti(),
- curr->body,
- "Multivalue functions not allowed yet");
+ if (curr->sig.results.isMulti()) {
+ shouldBeTrue(getModule()->features.hasMultivalue(),
+ curr->body,
+ "Multivalue function results (multivalue is not enabled)");
+ }
FeatureSet features;
for (auto type : curr->sig.params.expand()) {
features |= type.getFeatures();
@@ -2053,6 +2104,12 @@ static void validateBinaryenIR(Module& wasm, ValidationInfo& info) {
static void validateImports(Module& module, ValidationInfo& info) {
ModuleUtils::iterImportedFunctions(module, [&](Function* curr) {
+ if (curr->sig.results.isMulti()) {
+ info.shouldBeTrue(module.features.hasMultivalue(),
+ curr->name,
+ "Imported multivalue function "
+ "(multivalue is not enabled)");
+ }
if (info.validateWeb) {
for (Type param : curr->sig.params.expand()) {
info.shouldBeUnequal(param,
@@ -2252,6 +2309,11 @@ static void validateEvents(Module& module, ValidationInfo& info) {
Type(Type::none),
curr->name,
"Event type's result type should be none");
+ if (curr->sig.params.isMulti()) {
+ info.shouldBeTrue(module.features.hasMultivalue(),
+ curr->name,
+ "Multivalue event type (multivalue is not enabled)");
+ }
for (auto type : curr->sig.params.expand()) {
info.shouldBeTrue(type.isConcrete(),
curr->name,