summaryrefslogtreecommitdiff
path: root/src/wasm/wasm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm.cpp')
-rw-r--r--src/wasm/wasm.cpp45
1 files changed, 30 insertions, 15 deletions
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index ef8cfb2f7..5eea3f315 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -180,9 +180,9 @@ void Block::finalize() {
type = Type::none;
return;
}
+ type = list.back()->type;
// The default type is what is at the end. Next we need to see if breaks and/
// or unreachabitily change that.
- type = list.back()->type;
if (!name.is()) {
// Nothing branches here, so this is easy.
handleUnreachable(this, NoBreak);
@@ -194,13 +194,12 @@ void Block::finalize() {
Expression* temp = this;
seeker.walk(temp);
if (seeker.found) {
- // Take the branch values into account.
- if (seeker.valueType != Type::none) {
- type = Type::getLeastUpperBound(type, seeker.valueType);
- } else {
- // No value is sent, but as we have a branch we are not unreachable.
- type = Type::none;
- }
+ // Calculate the supertype of the branch types and the flowed-out type. If
+ // there is no supertype among the available types, assume the current type
+ // is already correct. TODO: calculate proper LUBs to compute a new correct
+ // type in this situation.
+ seeker.types.insert(type);
+ Type::ensureSuperType(seeker.types, type);
} else {
// There are no branches, so this block may be unreachable.
handleUnreachable(this, NoBreak);
@@ -231,17 +230,24 @@ void If::finalize(Type type_) {
}
void If::finalize() {
- type = ifFalse ? Type::getLeastUpperBound(ifTrue->type, ifFalse->type)
- : Type::none;
+ if (ifFalse) {
+ // TODO: Calculate a proper LUB.
+ Type::ensureSuperType(std::array<Type, 2>{{ifTrue->type, ifFalse->type}},
+ type);
+ } else {
+ type = Type::none;
+ }
// if the arms return a value, leave it even if the condition
// is unreachable, we still mark ourselves as having that type, e.g.
// (if (result i32)
// (unreachable)
// (i32.const 10)
- // (i32.const 20
+ // (i32.const 20)
// )
// otherwise, if the condition is unreachable, so is the if
- if (type == Type::none && condition->type == Type::unreachable) {
+ if ((type == Type::none && condition->type == Type::unreachable) ||
+ (ifTrue->type == Type::unreachable && ifFalse &&
+ ifFalse->type == Type::unreachable)) {
type = Type::unreachable;
}
}
@@ -779,7 +785,9 @@ void Select::finalize() {
condition->type == Type::unreachable) {
type = Type::unreachable;
} else {
- type = Type::getLeastUpperBound(ifTrue->type, ifFalse->type);
+ // TODO: Calculate a proper LUB.
+ Type::ensureSuperType(std::array<Type, 2>{{ifTrue->type, ifFalse->type}},
+ type);
}
}
@@ -833,9 +841,16 @@ void RefEq::finalize() {
}
void Try::finalize() {
- type = body->type;
+ // If none of the component bodies' type is a supertype of the others, assume
+ // the current type is already correct. TODO: Calculate a proper LUB.
+ std::unordered_set<Type> types{body->type};
for (auto catchBody : catchBodies) {
- type = Type::getLeastUpperBound(type, catchBody->type);
+ types.insert(catchBody->type);
+ }
+ if (types.size() == 1 && *types.begin() == Type::unreachable) {
+ type = Type::unreachable;
+ } else {
+ Type::ensureSuperType(types, type);
}
}