diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2021-03-11 13:53:19 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-11 21:53:19 +0000 |
commit | 484563771dbca78e5323cc3f5129890aea03aed5 (patch) | |
tree | 50c869eb9ebd43cba0c5a7bd11c57129ccf61e6e /src/wasm/wasm-validator.cpp | |
parent | d369cd6474364e5797e40af94676339af03723a9 (diff) | |
download | binaryen-484563771dbca78e5323cc3f5129890aea03aed5.tar.gz binaryen-484563771dbca78e5323cc3f5129890aea03aed5.tar.bz2 binaryen-484563771dbca78e5323cc3f5129890aea03aed5.zip |
Remove LUB calculation (#3669)
Since correct LUB calculation for recursive types is complicated, stop depending
on LUBs throughout the code base. This also fixes a validation bug in which the
validator required blocks to be typed with the LUB of all the branch types, when
in fact any upper bound should have been valid. In addition to fixing that bug,
this PR simplifies the code for break handling by not storing redundant
information about the arity of types.
Diffstat (limited to 'src/wasm/wasm-validator.cpp')
-rw-r--r-- | src/wasm/wasm-validator.cpp | 103 |
1 files changed, 23 insertions, 80 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 057243fd3..80b7eb874 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -209,21 +209,7 @@ struct FunctionValidator : public WalkerPass<PostWalker<FunctionValidator>> { FunctionValidator(ValidationInfo* info) : info(*info) {} - struct BreakInfo { - enum { UnsetArity = Index(-1), PoisonArity = Index(-2) }; - - Type type; - Index arity; - BreakInfo() : arity(UnsetArity) {} - BreakInfo(Type type, Index arity) : type(type), arity(arity) {} - - bool hasBeenSet() { - // Compare to the impossible value. - return arity != UnsetArity; - } - }; - - std::unordered_map<Name, BreakInfo> breakInfos; + std::unordered_map<Name, std::unordered_set<Type>> breakTypes; std::unordered_set<Name> delegateTargetNames; std::unordered_set<Name> rethrowTargetNames; @@ -248,7 +234,7 @@ public: static void visitPreBlock(FunctionValidator* self, Expression** currp) { auto* curr = (*currp)->cast<Block>(); if (curr->name.is()) { - self->breakInfos[curr->name]; + self->breakTypes[curr->name]; } } @@ -259,7 +245,7 @@ public: static void visitPreLoop(FunctionValidator* self, Expression** currp) { auto* curr = (*currp)->cast<Loop>(); if (curr->name.is()) { - self->breakInfos[curr->name]; + self->breakTypes[curr->name]; } } @@ -533,49 +519,17 @@ void FunctionValidator::visitBlock(Block* curr) { // if we are break'ed to, then the value must be right for us if (curr->name.is()) { noteLabelName(curr->name); - auto iter = breakInfos.find(curr->name); - assert(iter != breakInfos.end()); // we set it ourselves - auto& info = iter->second; - if (info.hasBeenSet()) { - if (curr->type.isConcrete()) { - shouldBeTrue(info.arity != 0, - curr, - "break arities must be > 0 if block has a value"); - } else { - shouldBeTrue(info.arity == 0, - curr, - "break arities must be 0 if block has no value"); - } + auto iter = breakTypes.find(curr->name); + assert(iter != breakTypes.end()); // we set it ourselves + for (Type breakType : iter->second) { // none or unreachable means a poison value that we should ignore - if // consumed, it will error - if (info.type.isConcrete() && curr->type.isConcrete()) { - shouldBeSubType( - info.type, - curr->type, - curr, - "block+breaks must have right type if breaks return a value"); - } - if (curr->type.isConcrete() && info.arity && - info.type != Type::unreachable) { - shouldBeSubType( - info.type, - curr->type, - curr, - "block+breaks must have right type if breaks have arity"); - } - shouldBeTrue( - info.arity != BreakInfo::PoisonArity, curr, "break arities must match"); - if (curr->list.size() > 0) { - auto last = curr->list.back()->type; - if (last == Type::none) { - shouldBeTrue(info.arity == Index(0), - curr, - "if block ends with a none, breaks cannot send a value " - "of any type"); - } - } + shouldBeSubType(breakType, + curr->type, + curr, + "break type must be a subtype of the target block type"); } - breakInfos.erase(iter); + breakTypes.erase(iter); } switch (getFunction()->profile) { case IRProfile::Normal: @@ -679,14 +633,15 @@ void FunctionValidator::validatePoppyBlockElements(Block* curr) { void FunctionValidator::visitLoop(Loop* curr) { if (curr->name.is()) { noteLabelName(curr->name); - auto iter = breakInfos.find(curr->name); - assert(iter != breakInfos.end()); // we set it ourselves - auto& info = iter->second; - if (info.hasBeenSet()) { - shouldBeEqual( - info.arity, Index(0), curr, "breaks to a loop cannot pass a value"); + auto iter = breakTypes.find(curr->name); + assert(iter != breakTypes.end()); // we set it ourselves + for (Type breakType : iter->second) { + shouldBeEqual(breakType, + Type(Type::none), + curr, + "breaks to a loop cannot pass a value"); } - breakInfos.erase(iter); + breakTypes.erase(iter); } if (curr->type == Type::none) { shouldBeFalse(curr->body->type.isConcrete(), @@ -775,24 +730,12 @@ void FunctionValidator::noteBreak(Name name, } void FunctionValidator::noteBreak(Name name, Type valueType, Expression* curr) { - Index arity = 0; - if (valueType != Type::none) { - arity = 1; - } - auto iter = breakInfos.find(name); + auto iter = breakTypes.find(name); if (!shouldBeTrue( - iter != breakInfos.end(), curr, "all break targets must be valid")) { + iter != breakTypes.end(), curr, "all break targets must be valid")) { return; } - auto& info = iter->second; - if (!info.hasBeenSet()) { - info = BreakInfo(valueType, arity); - } else { - info.type = Type::getLeastUpperBound(info.type, valueType); - if (arity != info.arity) { - info.arity = BreakInfo::PoisonArity; - } - } + iter->second.insert(valueType); } void FunctionValidator::visitBreak(Break* curr) { @@ -2518,7 +2461,7 @@ void FunctionValidator::visitFunction(Function* curr) { "function result must match, if function has returns"); } - assert(breakInfos.empty()); + assert(breakTypes.empty()); assert(delegateTargetNames.empty()); assert(rethrowTargetNames.empty()); returnTypes.clear(); |