Bug 1561513 - Wasm: Add bottom type and tweak validation algorithm. r=lth

This commit renames TVar to represent the new Bottom type introduced in the
reference types spec.

Issue: https://github.com/WebAssembly/reference-types/issues/42

The only observable spec change so far is in validation of br_table which
requires that the operand type is a subtype of all label types. With a bottom
type, this may allow more code to validate than before.

Differential Revision: https://phabricator.services.mozilla.com/D46641

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ryan Hunt 2019-09-25 21:54:56 +00:00
Родитель 5b5444ada9
Коммит c994f1409d
5 изменённых файлов: 184 добавлений и 88 удалений

Просмотреть файл

@ -202,7 +202,7 @@ wasmFailValidateText(`
(br_table 1 0 (i32.const 15))
)
)
)`, /br_table targets must all have the same value type/);
)`, /br_table operand must be subtype of all target types/);
wasmFailValidateText(`
(module
@ -212,7 +212,7 @@ wasmFailValidateText(`
(br_table 1 0 (i32.const 15))
)
)
)`, /br_table targets must all have the same value type/);
)`, /br_table operand must be subtype of all target types/);
wasmValidateText(`
(module

Просмотреть файл

@ -260,74 +260,71 @@ assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60
// unreached-invalid.wast:526
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x40\x02\x7d\x00\x41\x01\x0e\x02\x00\x01\x00\x0b\x1a\x0b\x0b");
// unreached-invalid.wast:538
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\xa1\x80\x80\x80\x00\x01\x9b\x80\x80\x80\x00\x00\x02\x7c\x02\x7d\x00\x41\x01\x0e\x02\x00\x01\x01\x0b\x1a\x44\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x1a\x0b");
// unreached-invalid.wast:553
// unreached-invalid.wast:539
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x00\x0b\x0b\x0b");
// unreached-invalid.wast:559
// unreached-invalid.wast:545
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8f\x80\x80\x80\x00\x01\x89\x80\x80\x80\x00\x00\x02\x40\x02\x40\x00\x0b\x0b\x0b");
// unreached-invalid.wast:565
// unreached-invalid.wast:551
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x7e\x42\x00\x02\x40\x00\x0b\x0b\x0b");
// unreached-invalid.wast:571
// unreached-invalid.wast:557
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x00\x0b\x0b\x41\x09\x0b");
// unreached-invalid.wast:578
// unreached-invalid.wast:564
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x92\x80\x80\x80\x00\x01\x8c\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x0c\x01\x0b\x0b\x0b");
// unreached-invalid.wast:584
// unreached-invalid.wast:570
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x92\x80\x80\x80\x00\x01\x8c\x80\x80\x80\x00\x00\x02\x7f\x02\x40\x41\x00\x0c\x01\x0b\x0b\x0b");
// unreached-invalid.wast:590
// unreached-invalid.wast:576
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x94\x80\x80\x80\x00\x01\x8e\x80\x80\x80\x00\x00\x02\x7f\x42\x00\x02\x40\x41\x00\x0c\x01\x0b\x0b\x0b");
// unreached-invalid.wast:597
// unreached-invalid.wast:583
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x40\x02\x40\x41\x03\x02\x40\x0c\x02\x0b\x0b\x0b\x0b");
// unreached-invalid.wast:603
// unreached-invalid.wast:589
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x7f\x02\x40\x02\x40\x41\x00\x0c\x02\x0b\x0b\x0b\x0b");
// unreached-invalid.wast:609
// unreached-invalid.wast:595
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x7f\x02\x7e\x42\x00\x02\x40\x41\x00\x0c\x02\x0b\x0b\x0b\x0b");
// unreached-invalid.wast:617
// unreached-invalid.wast:603
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x96\x80\x80\x80\x00\x01\x90\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x0c\x01\x0b\x0b\x41\x09\x0b");
// unreached-invalid.wast:624
// unreached-invalid.wast:610
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x0f\x0b\x0b\x0b");
// unreached-invalid.wast:630
// unreached-invalid.wast:616
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x40\x02\x40\x41\x00\x0f\x0b\x0b\x0b");
// unreached-invalid.wast:636
// unreached-invalid.wast:622
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x93\x80\x80\x80\x00\x01\x8d\x80\x80\x80\x00\x00\x02\x7e\x42\x00\x02\x40\x41\x00\x0f\x0b\x0b\x0b");
// unreached-invalid.wast:642
// unreached-invalid.wast:628
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x41\x00\x0f\x0b\x0b\x41\x09\x0b");
// unreached-invalid.wast:650
// unreached-invalid.wast:636
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x03\x40\x41\x03\x02\x40\x00\x0b\x0b\x0b");
// unreached-invalid.wast:656
// unreached-invalid.wast:642
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8f\x80\x80\x80\x00\x01\x89\x80\x80\x80\x00\x00\x03\x40\x02\x40\x00\x0b\x0b\x0b");
// unreached-invalid.wast:662
// unreached-invalid.wast:648
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x03\x7e\x42\x00\x02\x40\x00\x0b\x0b\x0b");
// unreached-invalid.wast:669
// unreached-invalid.wast:655
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8e\x80\x80\x80\x00\x01\x88\x80\x80\x80\x00\x00\x03\x40\x01\x0c\x00\x0b\x0b");
// unreached-invalid.wast:675
// unreached-invalid.wast:661
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8f\x80\x80\x80\x00\x01\x89\x80\x80\x80\x00\x00\x03\x40\x41\x00\x0c\x00\x0b\x0b");
// unreached-invalid.wast:682
// unreached-invalid.wast:668
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8d\x80\x80\x80\x00\x01\x87\x80\x80\x80\x00\x01\x01\x7f\x00\x22\x00\x0b");
// unreached-invalid.wast:689
// unreached-invalid.wast:675
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x7f\x02\x40\x00\x41\x00\x0d\x01\x0b\x41\x00\x0b\x0b");
// unreached-invalid.wast:700
// unreached-invalid.wast:686
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7e\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8c\x80\x80\x80\x00\x01\x86\x80\x80\x80\x00\x00\x00\x0d\x00\xad\x0b");

Просмотреть файл

@ -9556,7 +9556,7 @@ bool BaseCompiler::emitSelect() {
BranchState b(&done);
emitBranchSetup(&b);
switch (NonTVarToValType(type).code()) {
switch (NonBottomToValType(type).code()) {
case ValType::I32: {
RegI32 r, rs;
pop2xI32(&r, &rs);

Просмотреть файл

@ -69,7 +69,7 @@ class StackType {
Ref = uint8_t(ValType::Ref),
NullRef = uint8_t(ValType::NullRef),
TVar = uint8_t(TypeCode::Limit),
Bottom = uint8_t(TypeCode::Limit),
};
StackType() : tc_(InvalidPackedTypeCode()) {}
@ -86,7 +86,7 @@ class StackType {
bool isNumeric() const {
switch (code()) {
case Code::TVar:
case Code::Bottom:
case Code::I32:
case Code::I64:
case Code::F32:
@ -111,8 +111,8 @@ class StackType {
bool operator!=(Code that) const { return !(*this == that); }
};
static inline ValType NonTVarToValType(StackType type) {
MOZ_ASSERT(type != StackType::TVar);
static inline ValType NonBottomToValType(StackType type) {
MOZ_ASSERT(type != StackType::Bottom);
return ValType(type.packed());
}
@ -246,7 +246,7 @@ class TypeAndValue {
mozilla::Pair<StackType, Value> tv_;
public:
TypeAndValue() : tv_(StackType::TVar, Value()) {}
TypeAndValue() : tv_(StackType::Bottom, Value()) {}
explicit TypeAndValue(StackType type) : tv_(type, Value()) {}
explicit TypeAndValue(ValType type) : tv_(StackType(type), Value()) {}
TypeAndValue(StackType type, Value value) : tv_(type, value) {}
@ -307,6 +307,8 @@ class MOZ_STACK_CLASS OpIter : private Policy {
MOZ_MUST_USE bool popWithType(ExprType expectedType, Value* value);
MOZ_MUST_USE bool topWithType(ExprType expectedType, Value* value);
MOZ_MUST_USE bool topWithType(ValType valType, Value* value);
MOZ_MUST_USE bool topIsType(ValType expectedType, StackType* actualType,
Value* value);
MOZ_MUST_USE bool pushControl(LabelKind kind, ExprType type);
MOZ_MUST_USE bool checkStackAtEndOfBlock(ExprType* type, Value* value);
@ -315,6 +317,7 @@ class MOZ_STACK_CLASS OpIter : private Policy {
MOZ_MUST_USE bool checkBranchValue(uint32_t relativeDepth, ExprType* type,
Value* value);
MOZ_MUST_USE bool checkBrTableEntry(uint32_t* relativeDepth,
uint32_t* branchValueArity,
ExprType* branchValueType,
Value* branchValue);
@ -339,6 +342,11 @@ class MOZ_STACK_CLASS OpIter : private Policy {
controlStack_.back().setPolymorphicBase();
}
// Compute a type that is a supertype of one and two. This type is not
// guaranteed to be minimal; there may be a more specific supertype of one
// and two that this type is a supertype of.
inline bool weakMeet(ExprType one, ExprType two, ExprType* result) const;
inline bool checkIsSubtypeOf(ValType lhs, ValType rhs);
public:
@ -525,6 +533,22 @@ class MOZ_STACK_CLASS OpIter : private Policy {
bool controlStackEmpty() const { return controlStack_.empty(); }
};
template <typename Policy>
inline bool OpIter<Policy>::weakMeet(ExprType one, ExprType two,
ExprType* result) const {
if (MOZ_LIKELY(one == two)) {
*result = one;
return true;
}
if (one.isReference() && two.isReference()) {
*result = ExprType::AnyRef;
return true;
}
return false;
}
template <typename Policy>
inline bool OpIter<Policy>::checkIsSubtypeOf(ValType actual, ValType expected) {
if (actual == expected) {
@ -577,9 +601,9 @@ inline bool OpIter<Policy>::failEmptyStack() {
: fail("popping value from outside block");
}
// This function pops exactly one value from the stack, yielding TVar types in
// This function pops exactly one value from the stack, yielding Bottom types in
// various cases and therefore making it the caller's responsibility to do the
// right thing for StackType::TVar. Prefer (pop|top)WithType.
// right thing for StackType::Bottom. Prefer (pop|top)WithType.
template <typename Policy>
inline bool OpIter<Policy>::popStackType(StackType* type, Value* value) {
ControlStackEntry<ControlItem>& block = controlStack_.back();
@ -590,7 +614,7 @@ inline bool OpIter<Policy>::popStackType(StackType* type, Value* value) {
// dummy value of any type; it won't be used since we're in unreachable
// code.
if (block.polymorphicBase()) {
*type = StackType::TVar;
*type = StackType::Bottom;
*value = Value();
// Maintain the invariant that, after a pop, there is always memory
@ -617,8 +641,8 @@ inline bool OpIter<Policy>::popWithType(ValType expectedType, Value* value) {
return false;
}
return stackType == StackType::TVar ||
checkIsSubtypeOf(NonTVarToValType(stackType), expectedType);
return stackType == StackType::Bottom ||
checkIsSubtypeOf(NonBottomToValType(stackType), expectedType);
}
// This function pops as many types from the stack as determined by the given
@ -635,7 +659,8 @@ inline bool OpIter<Policy>::popWithType(ExprType expectedType, Value* value) {
return popWithType(NonVoidToValType(expectedType), value);
}
// This function is just an optimization of popWithType + push.
// This function is equivalent to: popWithType(expectedType);
// push(expectedType);
template <typename Policy>
inline bool OpIter<Policy>::topWithType(ValType expectedType, Value* value) {
ControlStackEntry<ControlItem>& block = controlStack_.back();
@ -661,13 +686,13 @@ inline bool OpIter<Policy>::topWithType(ValType expectedType, Value* value) {
TypeAndValue<Value>& observed = valueStack_.back();
if (observed.type() == StackType::TVar) {
if (observed.type() == StackType::Bottom) {
observed.typeRef() = StackType(expectedType);
*value = Value();
return true;
}
if (!checkIsSubtypeOf(NonTVarToValType(observed.type()), expectedType)) {
if (!checkIsSubtypeOf(NonBottomToValType(observed.type()), expectedType)) {
return false;
}
@ -685,6 +710,44 @@ inline bool OpIter<Policy>::topWithType(ExprType expectedType, Value* value) {
return topWithType(NonVoidToValType(expectedType), value);
}
// This function checks that the top of the stack is a subtype of expectedType
// and returns the value if so.
template <typename Policy>
inline bool OpIter<Policy>::topIsType(ValType expectedType,
StackType* actualType, Value* value) {
ControlStackEntry<ControlItem>& block = controlStack_.back();
MOZ_ASSERT(valueStack_.length() >= block.valueStackStart());
if (valueStack_.length() == block.valueStackStart()) {
// If the base of this block's stack is polymorphic, then we can just
// pull out a dummy value of the expected type; it won't be used since
// we're in unreachable code.
if (block.polymorphicBase()) {
*actualType = StackType::Bottom;
*value = Value();
return true;
}
return failEmptyStack();
}
TypeAndValue<Value>& observed = valueStack_.back();
if (observed.type() == StackType::Bottom) {
*actualType = StackType::Bottom;
*value = Value();
return true;
}
if (!checkIsSubtypeOf(NonBottomToValType(observed.type()), expectedType)) {
return false;
}
*actualType = observed.type();
*value = observed.value();
return true;
}
template <typename Policy>
inline bool OpIter<Policy>::pushControl(LabelKind kind, ExprType type) {
return controlStack_.emplaceBack(kind, type, valueStack_.length());
@ -969,32 +1032,66 @@ inline bool OpIter<Policy>::readBrIf(uint32_t* relativeDepth, ExprType* type,
return checkBranchValue(*relativeDepth, type, value);
}
#define UNKNOWN_ARITY UINT32_MAX
template <typename Policy>
inline bool OpIter<Policy>::checkBrTableEntry(uint32_t* relativeDepth,
uint32_t* branchValueArity,
ExprType* branchValueType,
Value* branchValue) {
if (!readVarU32(relativeDepth)) {
return false;
}
ControlStackEntry<ControlItem>* block = nullptr;
if (!getControl(*relativeDepth, &block)) {
return false;
}
// For the first encountered branch target, do a normal branch value type
// check which will change *branchValueType to a non-sentinel value. For all
// subsequent branch targets, check that the branch target matches the
// now-known branch value type.
// check which will change *branchValueArity and *branchValueType to a
// non-sentinel value. For all subsequent branch targets, check that the
// branch target arity and type matches the now-known branch value arity
// and type. This will need to change with multi-value.
uint32_t labelTypeArity = IsVoid(block->branchTargetType()) ? 0 : 1;
if (*branchValueArity == UNKNOWN_ARITY) {
*branchValueArity = labelTypeArity;
} else if (*branchValueArity != labelTypeArity) {
return fail("br_table operand must be subtype of all target types");
}
// If the label types are void, no need to check type on the stack
if (labelTypeArity == 0) {
*branchValueType = ExprType::Void;
*branchValue = Value();
return true;
}
// Check that the value on the stack is a subtype of the label
StackType actualBranchValueType;
if (!topIsType(NonVoidToValType(block->branchTargetType()),
&actualBranchValueType, branchValue)) {
return false;
}
// If the value on the stack is the bottom type, it will by definition be a
// subtype of every possible label type. This also implies that the label
// types may not have a subtype relation, and so we cannot report a branch
// value type. Fortunately this only happens in unreachable code, where we
// don't use the branch value type.
if (actualBranchValueType == StackType::Bottom) {
*branchValueType = ExprType::Limit;
return true;
}
// Compute the branch value type in all other cases
if (*branchValueType == ExprType::Limit) {
if (!checkBranchValue(*relativeDepth, branchValueType, branchValue)) {
return false;
}
} else {
ControlStackEntry<ControlItem>* block = nullptr;
if (!getControl(*relativeDepth, &block)) {
return false;
}
if (*branchValueType != block->branchTargetType()) {
return fail("br_table targets must all have the same value type");
}
*branchValueType = block->branchTargetType();
} else if (!weakMeet(*branchValueType, block->branchTargetType(),
branchValueType)) {
return fail("br_table operand must be subtype of all target types");
}
return true;
@ -1024,24 +1121,29 @@ inline bool OpIter<Policy>::readBrTable(Uint32Vector* depths,
return false;
}
uint32_t branchValueArity = UNKNOWN_ARITY;
*branchValueType = ExprType::Limit;
for (uint32_t i = 0; i < tableLength; i++) {
if (!checkBrTableEntry(&(*depths)[i], branchValueType, branchValue)) {
if (!checkBrTableEntry(&(*depths)[i], &branchValueArity, branchValueType,
branchValue)) {
return false;
}
}
if (!checkBrTableEntry(defaultDepth, branchValueType, branchValue)) {
if (!checkBrTableEntry(defaultDepth, &branchValueArity, branchValueType,
branchValue)) {
return false;
}
MOZ_ASSERT(*branchValueType != ExprType::Limit);
MOZ_ASSERT(branchValueArity != UNKNOWN_ARITY);
afterUnconditionalBranch();
return true;
}
#undef UNKNOWN_ARITY
template <typename Policy>
inline bool OpIter<Policy>::readUnreachable() {
MOZ_ASSERT(Classify(op_) == OpKind::Unreachable);
@ -1315,9 +1417,9 @@ inline bool OpIter<Policy>::readSelect(StackType* type, Value* trueValue,
return fail("select operand types must be numeric");
}
if (falseType.code() == StackType::TVar) {
if (falseType.code() == StackType::Bottom) {
*type = trueType;
} else if (trueType.code() == StackType::TVar || falseType == trueType) {
} else if (trueType.code() == StackType::Bottom || falseType == trueType) {
*type = falseType;
} else {
return fail("select operand types must match");

Просмотреть файл

@ -261,76 +261,73 @@ assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60
// unreached-invalid.wast:526
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x40\x02\x7d\x00\x41\x01\x0e\x02\x00\x01\x00\x0b\x1a\x0b\x0b");
// unreached-invalid.wast:538
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\xa1\x80\x80\x80\x00\x01\x9b\x80\x80\x80\x00\x00\x02\x7c\x02\x7d\x00\x41\x01\x0e\x02\x00\x01\x01\x0b\x1a\x44\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x1a\x0b");
// unreached-invalid.wast:553
// unreached-invalid.wast:539
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x00\x0b\x0b\x0b");
// unreached-invalid.wast:559
// unreached-invalid.wast:545
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8f\x80\x80\x80\x00\x01\x89\x80\x80\x80\x00\x00\x02\x40\x02\x40\x00\x0b\x0b\x0b");
// unreached-invalid.wast:565
// unreached-invalid.wast:551
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x7e\x42\x00\x02\x40\x00\x0b\x0b\x0b");
// unreached-invalid.wast:571
// unreached-invalid.wast:557
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x00\x0b\x0b\x41\x09\x0b");
// unreached-invalid.wast:578
// unreached-invalid.wast:564
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x92\x80\x80\x80\x00\x01\x8c\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x0c\x01\x0b\x0b\x0b");
// unreached-invalid.wast:584
// unreached-invalid.wast:570
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x92\x80\x80\x80\x00\x01\x8c\x80\x80\x80\x00\x00\x02\x7f\x02\x40\x41\x00\x0c\x01\x0b\x0b\x0b");
// unreached-invalid.wast:590
// unreached-invalid.wast:576
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x94\x80\x80\x80\x00\x01\x8e\x80\x80\x80\x00\x00\x02\x7f\x42\x00\x02\x40\x41\x00\x0c\x01\x0b\x0b\x0b");
// unreached-invalid.wast:597
// unreached-invalid.wast:583
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x40\x02\x40\x41\x03\x02\x40\x0c\x02\x0b\x0b\x0b\x0b");
// unreached-invalid.wast:603
// unreached-invalid.wast:589
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x7f\x02\x40\x02\x40\x41\x00\x0c\x02\x0b\x0b\x0b\x0b");
// unreached-invalid.wast:609
// unreached-invalid.wast:595
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x7f\x02\x7e\x42\x00\x02\x40\x41\x00\x0c\x02\x0b\x0b\x0b\x0b");
// unreached-invalid.wast:617
// unreached-invalid.wast:603
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x96\x80\x80\x80\x00\x01\x90\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x0c\x01\x0b\x0b\x41\x09\x0b");
// unreached-invalid.wast:624
// unreached-invalid.wast:610
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x0f\x0b\x0b\x0b");
// unreached-invalid.wast:630
// unreached-invalid.wast:616
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x02\x40\x02\x40\x41\x00\x0f\x0b\x0b\x0b");
// unreached-invalid.wast:636
// unreached-invalid.wast:622
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x93\x80\x80\x80\x00\x01\x8d\x80\x80\x80\x00\x00\x02\x7e\x42\x00\x02\x40\x41\x00\x0f\x0b\x0b\x0b");
// unreached-invalid.wast:642
// unreached-invalid.wast:628
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x97\x80\x80\x80\x00\x01\x91\x80\x80\x80\x00\x00\x02\x40\x41\x03\x02\x40\x42\x01\x41\x00\x0f\x0b\x0b\x41\x09\x0b");
// unreached-invalid.wast:650
// unreached-invalid.wast:636
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x03\x40\x41\x03\x02\x40\x00\x0b\x0b\x0b");
// unreached-invalid.wast:656
// unreached-invalid.wast:642
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8f\x80\x80\x80\x00\x01\x89\x80\x80\x80\x00\x00\x03\x40\x02\x40\x00\x0b\x0b\x0b");
// unreached-invalid.wast:662
// unreached-invalid.wast:648
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x91\x80\x80\x80\x00\x01\x8b\x80\x80\x80\x00\x00\x03\x7e\x42\x00\x02\x40\x00\x0b\x0b\x0b");
// unreached-invalid.wast:669
// unreached-invalid.wast:655
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8e\x80\x80\x80\x00\x01\x88\x80\x80\x80\x00\x00\x03\x40\x01\x0c\x00\x0b\x0b");
// unreached-invalid.wast:675
// unreached-invalid.wast:661
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8f\x80\x80\x80\x00\x01\x89\x80\x80\x80\x00\x00\x03\x40\x41\x00\x0c\x00\x0b\x0b");
// unreached-invalid.wast:682
// unreached-invalid.wast:668
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8d\x80\x80\x80\x00\x01\x87\x80\x80\x80\x00\x01\x01\x7f\x00\x22\x00\x0b");
// unreached-invalid.wast:689
// unreached-invalid.wast:675
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x95\x80\x80\x80\x00\x01\x8f\x80\x80\x80\x00\x00\x02\x7f\x02\x40\x00\x41\x00\x0d\x01\x0b\x41\x00\x0b\x0b");
// unreached-invalid.wast:700
// unreached-invalid.wast:686
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7e\x03\x82\x80\x80\x80\x00\x01\x00\x0a\x8c\x80\x80\x80\x00\x01\x86\x80\x80\x80\x00\x00\x00\x0d\x00\xad\x0b");
reinitializeRegistry();
})();