summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-validator.cpp
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2019-11-22 12:46:04 -0800
committerGitHub <noreply@github.com>2019-11-22 12:46:04 -0800
commite2587f30827cd3d35dd409c2958b25a6c5517092 (patch)
tree22a372a3986cbfbc6db09df45bffe00631083f69 /src/wasm/wasm-validator.cpp
parenta0c423ef501ea7267c24c46e645296e713b2ea42 (diff)
downloadbinaryen-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.cpp47
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");
}