diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binaryen-c.cpp | 9 | ||||
-rw-r--r-- | src/binaryen-c.h | 3 | ||||
-rw-r--r-- | src/js/binaryen.js-post.js | 4 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 2 | ||||
-rw-r--r-- | src/passes/RemoveUnusedBrs.cpp | 2 | ||||
-rw-r--r-- | src/passes/SSAify.cpp | 2 | ||||
-rw-r--r-- | src/passes/TypeSSA.cpp | 1 | ||||
-rw-r--r-- | src/tools/fuzzing.h | 2 | ||||
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 7 | ||||
-rw-r--r-- | src/wasm-builder.h | 33 | ||||
-rw-r--r-- | src/wasm.h | 1 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 11 | ||||
-rw-r--r-- | src/wasm/wasm-ir-builder.cpp | 4 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 8 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 10 |
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 || |