summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binaryen-c.cpp9
-rw-r--r--src/binaryen-c.h3
-rw-r--r--src/js/binaryen.js-post.js4
-rw-r--r--src/passes/OptimizeInstructions.cpp2
-rw-r--r--src/passes/RemoveUnusedBrs.cpp2
-rw-r--r--src/passes/SSAify.cpp2
-rw-r--r--src/passes/TypeSSA.cpp1
-rw-r--r--src/tools/fuzzing.h2
-rw-r--r--src/tools/fuzzing/fuzzing.cpp7
-rw-r--r--src/wasm-builder.h33
-rw-r--r--src/wasm.h1
-rw-r--r--src/wasm/wasm-binary.cpp11
-rw-r--r--src/wasm/wasm-ir-builder.cpp4
-rw-r--r--src/wasm/wasm-validator.cpp8
-rw-r--r--src/wasm/wasm.cpp10
15 files changed, 36 insertions, 63 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index 854b0c995..a278f7778 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -1276,17 +1276,12 @@ BinaryenExpressionRef BinaryenBinary(BinaryenModuleRef module,
BinaryenExpressionRef BinaryenSelect(BinaryenModuleRef module,
BinaryenExpressionRef condition,
BinaryenExpressionRef ifTrue,
- BinaryenExpressionRef ifFalse,
- BinaryenType type) {
+ BinaryenExpressionRef ifFalse) {
auto* ret = ((Module*)module)->allocator.alloc<Select>();
ret->condition = (Expression*)condition;
ret->ifTrue = (Expression*)ifTrue;
ret->ifFalse = (Expression*)ifFalse;
- if (type != BinaryenTypeAuto()) {
- ret->finalize(Type(type));
- } else {
- ret->finalize();
- }
+ ret->finalize();
return static_cast<Expression*>(ret);
}
BinaryenExpressionRef BinaryenDrop(BinaryenModuleRef module,
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index b23945d18..d24b2bb56 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -821,8 +821,7 @@ BINARYEN_API BinaryenExpressionRef
BinaryenSelect(BinaryenModuleRef module,
BinaryenExpressionRef condition,
BinaryenExpressionRef ifTrue,
- BinaryenExpressionRef ifFalse,
- BinaryenType type);
+ BinaryenExpressionRef ifFalse);
BINARYEN_API BinaryenExpressionRef BinaryenDrop(BinaryenModuleRef module,
BinaryenExpressionRef value);
// Return: value can be NULL
diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js
index 40d08dceb..a90b79d49 100644
--- a/src/js/binaryen.js-post.js
+++ b/src/js/binaryen.js-post.js
@@ -2331,8 +2331,8 @@ function wrapModule(module, self = {}) {
}
};
- self['select'] = function(condition, ifTrue, ifFalse, type) {
- return Module['_BinaryenSelect'](module, condition, ifTrue, ifFalse, typeof type !== 'undefined' ? type : Module['auto']);
+ self['select'] = function(condition, ifTrue, ifFalse) {
+ return Module['_BinaryenSelect'](module, condition, ifTrue, ifFalse);
};
self['drop'] = function(value) {
return Module['_BinaryenDrop'](module, value);
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index c9fe5f652..881b7ea1f 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -5248,7 +5248,7 @@ private:
curr->ifTrue = updateArm(curr->ifTrue);
curr->ifFalse = updateArm(curr->ifFalse);
un->value = curr;
- curr->finalize(newType);
+ curr->finalize();
return replaceCurrent(un);
}
}
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index 2ccf3c761..96db281d8 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -1420,7 +1420,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
return nullptr;
}
return Builder(*getModule())
- .makeSelect(iff->condition, iff->ifTrue, iff->ifFalse, iff->type);
+ .makeSelect(iff->condition, iff->ifTrue, iff->ifFalse);
}
void visitLocalSet(LocalSet* curr) {
diff --git a/src/passes/SSAify.cpp b/src/passes/SSAify.cpp
index c220fdd06..8e827d0fc 100644
--- a/src/passes/SSAify.cpp
+++ b/src/passes/SSAify.cpp
@@ -150,7 +150,7 @@ struct SSAify : public Pass {
LiteralUtils::makeZero(get->type, *module);
// If we replace a local.get with a null then we are refining the
// type that the parent receives to a bottom type.
- if (get->type.isRef()) {
+ if (get->type.hasRef()) {
refinalize = true;
}
} else {
diff --git a/src/passes/TypeSSA.cpp b/src/passes/TypeSSA.cpp
index cda78474b..3d68c9913 100644
--- a/src/passes/TypeSSA.cpp
+++ b/src/passes/TypeSSA.cpp
@@ -200,6 +200,7 @@ struct TypeSSA : public Pass {
// Finally, refinalize to propagate the new types to parents.
ReFinalize().run(getPassRunner(), module);
+ ReFinalize().runOnModuleCode(getPassRunner(), module);
}
News newsToModify;
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index 3e8ec5b97..1afb4bf36 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -358,7 +358,7 @@ private:
Expression* makeUnary(Type type);
Expression* buildBinary(const BinaryArgs& args);
Expression* makeBinary(Type type);
- Expression* buildSelect(const ThreeArgs& args, Type type);
+ Expression* buildSelect(const ThreeArgs& args);
Expression* makeSelect(Type type);
Expression* makeSwitch(Type type);
Expression* makeDrop(Type type);
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index a283aae91..7e87f4f58 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -3808,15 +3808,14 @@ Expression* TranslateToFuzzReader::makeBinary(Type type) {
WASM_UNREACHABLE("invalid type");
}
-Expression* TranslateToFuzzReader::buildSelect(const ThreeArgs& args,
- Type type) {
- return builder.makeSelect(args.a, args.b, args.c, type);
+Expression* TranslateToFuzzReader::buildSelect(const ThreeArgs& args) {
+ return builder.makeSelect(args.a, args.b, args.c);
}
Expression* TranslateToFuzzReader::makeSelect(Type type) {
Type subType1 = getSubType(type);
Type subType2 = getSubType(type);
- return buildSelect({make(Type::i32), make(subType1), make(subType2)}, type);
+ return buildSelect({make(Type::i32), make(subType1), make(subType2)});
}
Expression* TranslateToFuzzReader::makeSwitch(Type type) {
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index 15b7a2059..20485f14d 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -632,17 +632,6 @@ public:
ret->finalize();
return ret;
}
- Select* makeSelect(Expression* condition,
- Expression* ifTrue,
- Expression* ifFalse,
- Type type) {
- auto* ret = wasm.allocator.alloc<Select>();
- ret->condition = condition;
- ret->ifTrue = ifTrue;
- ret->ifFalse = ifFalse;
- ret->finalize(type);
- return ret;
- }
Return* makeReturn(Expression* value = nullptr) {
auto* ret = wasm.allocator.alloc<Return>();
ret->value = value;
@@ -1381,21 +1370,23 @@ public:
// Returns a replacement with the precise same type, and with minimal contents
// as best we can. As a replacement, this may reuse the input node.
template<typename T> Expression* replaceWithIdenticalType(T* curr) {
+ auto type = curr->type;
+ // Anything that would otherwise have a more refined type than the original
+ // expression needs to be wrapped in a block with the original type.
+ auto maybeWrap = [&](Expression* expr) -> Expression* {
+ return expr->type == type ? expr : makeBlock({expr}, type);
+ };
if (curr->type.isTuple() && curr->type.isDefaultable()) {
- return makeConstantExpression(Literal::makeZeros(curr->type));
+ return maybeWrap(makeConstantExpression(Literal::makeZeros(curr->type)));
}
- if (curr->type.isNullable() && curr->type.isNull()) {
- return ExpressionManipulator::refNull(curr, curr->type);
+ if (curr->type.isNullable()) {
+ return maybeWrap(ExpressionManipulator::refNull(
+ curr, Type(curr->type.getHeapType().getBottom(), Nullable)));
}
if (curr->type.isRef() &&
curr->type.getHeapType().isMaybeShared(HeapType::i31)) {
- Expression* ret =
- makeRefI31(makeConst(0), curr->type.getHeapType().getShared());
- if (curr->type.isNullable()) {
- // To keep the type identical, wrap it in a block that adds nullability.
- ret = makeBlock({ret}, curr->type);
- }
- return ret;
+ return maybeWrap(
+ makeRefI31(makeConst(0), curr->type.getHeapType().getShared()));
}
if (!curr->type.isBasic()) {
// We can't do any better, keep the original.
diff --git a/src/wasm.h b/src/wasm.h
index 22e71560f..a5fc070e6 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -1271,7 +1271,6 @@ public:
Expression* condition;
void finalize();
- void finalize(Type type_);
};
class Drop : public SpecificExpression<Expression::DropId> {
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 73718e636..21842e19b 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -7042,6 +7042,7 @@ bool WasmBinaryReader::maybeVisitSIMDLoadStoreLane(Expression*& out,
}
void WasmBinaryReader::visitSelect(Select* curr, uint8_t code) {
+ Type annotated = Type::none;
if (code == BinaryConsts::SelectWithType) {
size_t numTypes = getU32LEB();
std::vector<Type> types;
@@ -7052,15 +7053,15 @@ void WasmBinaryReader::visitSelect(Select* curr, uint8_t code) {
}
types.push_back(t);
}
- curr->type = Type(types);
+ annotated = Type(types);
}
curr->condition = popNonVoidExpression();
curr->ifFalse = popNonVoidExpression();
curr->ifTrue = popNonVoidExpression();
- if (code == BinaryConsts::SelectWithType) {
- curr->finalize(curr->type);
- } else {
- curr->finalize();
+ curr->finalize();
+ if (code == BinaryConsts::SelectWithType &&
+ !Type::isSubType(curr->type, annotated)) {
+ throwError("select type does not match annotation");
}
}
diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp
index a73c7f2ac..54cd0149e 100644
--- a/src/wasm/wasm-ir-builder.cpp
+++ b/src/wasm/wasm-ir-builder.cpp
@@ -1412,9 +1412,7 @@ Result<> IRBuilder::makeBinary(BinaryOp op) {
Result<> IRBuilder::makeSelect(std::optional<Type> type) {
Select curr;
CHECK_ERR(visitSelect(&curr));
- auto* built =
- type ? builder.makeSelect(curr.condition, curr.ifTrue, curr.ifFalse, *type)
- : builder.makeSelect(curr.condition, curr.ifTrue, curr.ifFalse);
+ auto* built = builder.makeSelect(curr.condition, curr.ifTrue, curr.ifFalse);
if (type && !Type::isSubType(built->type, *type)) {
return Err{"select type does not match expected type"};
}
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 339a3c7a1..516bb86e1 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -3671,10 +3671,10 @@ static void validateBinaryenIR(Module& wasm, ValidationInfo& info) {
auto oldType = curr->type;
ReFinalizeNode().visit(curr);
auto newType = curr->type;
- // It's ok for types to be further refinable, but they must admit a
- // superset of the values allowed by the most precise possible type, i.e.
- // they must not be strict subtypes of or unrelated to the refined type.
- if (!Type::isSubType(newType, oldType)) {
+ // It's ok for control flow structures to be further refinable, but all
+ // other instructions must have the most-precise possible types.
+ if (oldType != newType && !(Properties::isControlFlowStructure(curr) &&
+ Type::isSubType(newType, oldType))) {
std::ostringstream ss;
ss << "stale type found in " << scope << " on " << curr
<< "\n(marked as " << oldType << ", should be " << newType << ")\n";
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index a1ac076e0..f89ef80c2 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -777,16 +777,6 @@ void Binary::finalize() {
}
}
-void Select::finalize(Type type_) {
- assert(ifTrue && ifFalse);
- if (ifTrue->type == Type::unreachable || ifFalse->type == Type::unreachable ||
- condition->type == Type::unreachable) {
- type = Type::unreachable;
- } else {
- type = type_;
- }
-}
-
void Select::finalize() {
assert(ifTrue && ifFalse);
if (ifTrue->type == Type::unreachable || ifFalse->type == Type::unreachable ||