diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2019-11-22 12:46:04 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-22 12:46:04 -0800 |
commit | e2587f30827cd3d35dd409c2958b25a6c5517092 (patch) | |
tree | 22a372a3986cbfbc6db09df45bffe00631083f69 /src/wasm/wasm-validator.cpp | |
parent | a0c423ef501ea7267c24c46e645296e713b2ea42 (diff) | |
download | binaryen-e2587f30827cd3d35dd409c2958b25a6c5517092.tar.gz binaryen-e2587f30827cd3d35dd409c2958b25a6c5517092.tar.bz2 binaryen-e2587f30827cd3d35dd409c2958b25a6c5517092.zip |
Multivalue type creation and inspection (#2459)
Adds the ability to create multivalue types from vectors of concrete value
types. All types are transparently interned, so their representation is still a
single uint32_t. Types can be extracted into vectors of their component parts,
and all the single value types expand into vectors containing themselves.
Multivalue types are not yet used in the IR, but their creation and inspection
functionality is exposed and tested in the C and JS APIs.
Also makes common type predicates methods of Type and improves the ergonomics of
type printing.
Diffstat (limited to 'src/wasm/wasm-validator.cpp')
-rw-r--r-- | src/wasm/wasm-validator.cpp | 47 |
1 files changed, 23 insertions, 24 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 82cd6d6f0..05cb45d25 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -352,7 +352,7 @@ void FunctionValidator::visitBlock(Block* curr) { assert(iter != breakInfos.end()); // we set it ourselves auto& info = iter->second; if (info.hasBeenSet()) { - if (isConcreteType(curr->type)) { + if (curr->type.isConcrete()) { shouldBeTrue(info.arity != 0, curr, "break arities must be > 0 if block has a value"); @@ -363,15 +363,14 @@ void FunctionValidator::visitBlock(Block* curr) { } // none or unreachable means a poison value that we should ignore - if // consumed, it will error - if (isConcreteType(info.type) && isConcreteType(curr->type)) { + if (info.type.isConcrete() && curr->type.isConcrete()) { shouldBeEqual( curr->type, info.type, curr, "block+breaks must have right type if breaks return a value"); } - if (isConcreteType(curr->type) && info.arity && - info.type != unreachable) { + if (curr->type.isConcrete() && info.arity && info.type != unreachable) { shouldBeEqual(curr->type, info.type, curr, @@ -381,7 +380,7 @@ void FunctionValidator::visitBlock(Block* curr) { info.arity != BreakInfo::PoisonArity, curr, "break arities must match"); if (curr->list.size() > 0) { auto last = curr->list.back()->type; - if (isConcreteType(last) && info.type != unreachable) { + if (last.isConcrete() && info.type != unreachable) { shouldBeEqual(last, info.type, curr, @@ -401,7 +400,7 @@ void FunctionValidator::visitBlock(Block* curr) { if (curr->list.size() > 1) { for (Index i = 0; i < curr->list.size() - 1; i++) { if (!shouldBeTrue( - !isConcreteType(curr->list[i]->type), + !curr->list[i]->type.isConcrete(), curr, "non-final block elements returning a value must be drop()ed " "(binaryen's autodrop option might help you)") && @@ -414,13 +413,13 @@ void FunctionValidator::visitBlock(Block* curr) { } if (curr->list.size() > 0) { auto backType = curr->list.back()->type; - if (!isConcreteType(curr->type)) { - shouldBeFalse(isConcreteType(backType), + if (!curr->type.isConcrete()) { + shouldBeFalse(backType.isConcrete(), curr, "if block is not returning a value, final element should " "not flow out a value"); } else { - if (isConcreteType(backType)) { + if (backType.isConcrete()) { shouldBeEqual( curr->type, backType, @@ -435,7 +434,7 @@ void FunctionValidator::visitBlock(Block* curr) { } } } - if (isConcreteType(curr->type)) { + if (curr->type.isConcrete()) { shouldBeTrue( curr->list.size() > 0, curr, "block with a value must not be empty"); } @@ -454,7 +453,7 @@ void FunctionValidator::visitLoop(Loop* curr) { breakInfos.erase(iter); } if (curr->type == none) { - shouldBeFalse(isConcreteType(curr->body->type), + shouldBeFalse(curr->body->type.isConcrete(), curr, "bad body for a loop that has no value"); } @@ -466,7 +465,7 @@ void FunctionValidator::visitIf(If* curr) { curr, "if condition must be valid"); if (!curr->ifFalse) { - shouldBeFalse(isConcreteType(curr->ifTrue->type), + shouldBeFalse(curr->ifTrue->type.isConcrete(), curr, "if without else must not return a value in body"); if (curr->condition->type != unreachable) { @@ -499,7 +498,7 @@ void FunctionValidator::visitIf(If* curr) { "unreachable if-else must have unreachable false"); } } - if (isConcreteType(curr->ifTrue->type)) { + if (curr->ifTrue->type.isConcrete()) { shouldBeEqual(curr->type, curr->ifTrue->type, curr, @@ -509,7 +508,7 @@ void FunctionValidator::visitIf(If* curr) { curr, "other arm must match concrete ifTrue"); } - if (isConcreteType(curr->ifFalse->type)) { + if (curr->ifFalse->type.isConcrete()) { shouldBeEqual(curr->type, curr->ifFalse->type, curr, @@ -705,7 +704,7 @@ void FunctionValidator::visitLocalGet(LocalGet* curr) { shouldBeTrue(curr->index < getFunction()->getNumLocals(), curr, "local.get index must be small enough"); - shouldBeTrue(isConcreteType(curr->type), + shouldBeTrue(curr->type.isConcrete(), curr, "local.get must have a valid type - check what you provided " "when you constructed the node"); @@ -1626,7 +1625,7 @@ void FunctionValidator::visitSelect(Select* curr) { } void FunctionValidator::visitDrop(Drop* curr) { - shouldBeTrue(isConcreteType(curr->value->type) || + shouldBeTrue(curr->value->type.isConcrete() || curr->value->type == unreachable, curr, "can only drop a valid value"); @@ -1678,14 +1677,14 @@ void FunctionValidator::visitTry(Try* curr) { curr->catchBody, "try's type does not match catch's body type"); } - if (isConcreteType(curr->body->type)) { + if (curr->body->type.isConcrete()) { shouldBeEqualOrFirstIsUnreachable( curr->catchBody->type, curr->body->type, curr->catchBody, "try's body type must match catch's body type"); } - if (isConcreteType(curr->catchBody->type)) { + if (curr->catchBody->type.isConcrete()) { shouldBeEqualOrFirstIsUnreachable( curr->body->type, curr->catchBody->type, @@ -1757,11 +1756,11 @@ void FunctionValidator::visitFunction(Function* curr) { FeatureSet typeFeatures = getFeatures(curr->result); for (auto type : curr->params) { typeFeatures |= getFeatures(type); - shouldBeTrue(isConcreteType(type), curr, "params must be concretely typed"); + shouldBeTrue(type.isConcrete(), curr, "params must be concretely typed"); } for (auto type : curr->vars) { typeFeatures |= getFeatures(type); - shouldBeTrue(isConcreteType(type), curr, "vars must be concretely typed"); + shouldBeTrue(type.isConcrete(), curr, "vars must be concretely typed"); } shouldBeTrue(typeFeatures <= getModule()->features, curr, @@ -1895,11 +1894,11 @@ static void validateBinaryenIR(Module& wasm, ValidationInfo& info) { // // The block has an added type, not derived from the ast itself, so it // is ok for it to be either i32 or unreachable. - if (!(isConcreteType(oldType) && newType == unreachable)) { + if (!(oldType.isConcrete() && newType == unreachable)) { std::ostringstream ss; ss << "stale type found in " << scope << " on " << curr - << "\n(marked as " << printType(oldType) << ", should be " - << printType(newType) << ")\n"; + << "\n(marked as " << oldType << ", should be " << newType + << ")\n"; info.fail(ss.str(), curr, getFunction()); } curr->type = oldType; @@ -2121,7 +2120,7 @@ static void validateEvents(Module& module, ValidationInfo& info) { curr->attribute, "Currently only attribute 0 is supported"); for (auto type : curr->params) { - info.shouldBeTrue(isIntegerType(type) || isFloatType(type), + info.shouldBeTrue(type.isInteger() || type.isFloat(), curr->name, "Values in an event should have integer or float type"); } |