diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2020-01-07 11:16:44 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-07 11:16:44 -0800 |
commit | e8f9d207427bda2f6e22c28ff0210b294b1f70e1 (patch) | |
tree | 503b20fb06274e38af7e25e3a1a4106827c52693 /src/wasm/wasm-validator.cpp | |
parent | f73b40c7873dbd2dd46a962f3afe5b97a7fc8b0a (diff) | |
download | binaryen-e8f9d207427bda2f6e22c28ff0210b294b1f70e1.tar.gz binaryen-e8f9d207427bda2f6e22c28ff0210b294b1f70e1.tar.bz2 binaryen-e8f9d207427bda2f6e22c28ff0210b294b1f70e1.zip |
[NFC] Enforce use of `Type::` on type names (#2434)
Diffstat (limited to 'src/wasm/wasm-validator.cpp')
-rw-r--r-- | src/wasm/wasm-validator.cpp | 526 |
1 files changed, 306 insertions, 220 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index b19ed096f..30e182f0b 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -147,7 +147,7 @@ struct ValidationInfo { template<typename T, typename S> bool shouldBeEqualOrFirstIsUnreachable( S left, S right, T curr, const char* text, Function* func = nullptr) { - if (left != unreachable && left != right) { + if (left != Type::unreachable && left != right) { std::ostringstream ss; ss << left << " != " << right << ": " << text; fail(ss.str(), curr, func); @@ -173,9 +173,9 @@ struct ValidationInfo { const char* text, Function* func = nullptr) { switch (ty) { - case i32: - case i64: - case unreachable: { + case Type::i32: + case Type::i64: + case Type::unreachable: { break; } default: @@ -411,7 +411,8 @@ void FunctionValidator::visitBlock(Block* curr) { curr, "block+breaks must have right type if breaks return a value"); } - if (curr->type.isConcrete() && info.arity && info.type != unreachable) { + if (curr->type.isConcrete() && info.arity && + info.type != Type::unreachable) { shouldBeSubType( info.type, curr->type, @@ -422,7 +423,7 @@ void FunctionValidator::visitBlock(Block* curr) { info.arity != BreakInfo::PoisonArity, curr, "break arities must match"); if (curr->list.size() > 0) { auto last = curr->list.back()->type; - if (last == none) { + if (last == Type::none) { shouldBeTrue(info.arity == Index(0), curr, "if block ends with a none, breaks cannot send a value " @@ -463,7 +464,7 @@ void FunctionValidator::visitBlock(Block* curr) { } else { shouldBeUnequal( backType, - none, + Type(Type::none), curr, "block with value must not have last element that is none"); } @@ -487,7 +488,7 @@ void FunctionValidator::visitLoop(Loop* curr) { } breakInfos.erase(iter); } - if (curr->type == none) { + if (curr->type == Type::none) { shouldBeFalse(curr->body->type.isConcrete(), curr, "bad body for a loop that has no value"); @@ -513,22 +514,22 @@ void FunctionValidator::visitLoop(Loop* curr) { } void FunctionValidator::visitIf(If* curr) { - shouldBeTrue(curr->condition->type == unreachable || - curr->condition->type == i32, + shouldBeTrue(curr->condition->type == Type::unreachable || + curr->condition->type == Type::i32, curr, "if condition must be valid"); if (!curr->ifFalse) { shouldBeFalse(curr->ifTrue->type.isConcrete(), curr, "if without else must not return a value in body"); - if (curr->condition->type != unreachable) { + if (curr->condition->type != Type::unreachable) { shouldBeEqual(curr->type, - none, + Type(Type::none), curr, "if without else and reachable condition must be none"); } } else { - if (curr->type != unreachable) { + if (curr->type != Type::unreachable) { shouldBeSubTypeOrFirstIsUnreachable( curr->ifTrue->type, curr->type, @@ -540,13 +541,13 @@ void FunctionValidator::visitIf(If* curr) { curr, "returning if-else's false must have right type"); } else { - if (curr->condition->type != unreachable) { + if (curr->condition->type != Type::unreachable) { shouldBeEqual(curr->ifTrue->type, - unreachable, + Type(Type::unreachable), curr, "unreachable if-else must have unreachable true"); shouldBeEqual(curr->ifFalse->type, - unreachable, + Type(Type::unreachable), curr, "unreachable if-else must have unreachable false"); } @@ -570,14 +571,15 @@ void FunctionValidator::noteBreak(Name name, Expression* value, Expression* curr) { if (value) { - shouldBeUnequal(value->type, none, curr, "breaks must have a valid value"); + shouldBeUnequal( + value->type, Type(Type::none), curr, "breaks must have a valid value"); } - noteBreak(name, value ? value->type : none, curr); + noteBreak(name, value ? value->type : Type::none, curr); } void FunctionValidator::noteBreak(Name name, Type valueType, Expression* curr) { Index arity = 0; - if (valueType != none) { + if (valueType != Type::none) { arity = 1; } auto iter = breakInfos.find(name); @@ -598,12 +600,13 @@ void FunctionValidator::noteBreak(Name name, Type valueType, Expression* curr) { void FunctionValidator::visitBreak(Break* curr) { noteBreak(curr->name, curr->value, curr); if (curr->value) { - shouldBeTrue( - curr->value->type != none, curr, "break value must not have none type"); + shouldBeTrue(curr->value->type != Type::none, + curr, + "break value must not have none type"); } if (curr->condition) { - shouldBeTrue(curr->condition->type == unreachable || - curr->condition->type == i32, + shouldBeTrue(curr->condition->type == Type::unreachable || + curr->condition->type == Type::i32, curr, "break condition must be i32"); } @@ -614,8 +617,8 @@ void FunctionValidator::visitSwitch(Switch* curr) { noteBreak(target, curr->value, curr); } noteBreak(curr->default_, curr->value, curr); - shouldBeTrue(curr->condition->type == unreachable || - curr->condition->type == i32, + shouldBeTrue(curr->condition->type == Type::unreachable || + curr->condition->type == Type::i32, curr, "br_table condition must be i32"); } @@ -648,7 +651,7 @@ void FunctionValidator::visitCall(Call* curr) { } if (curr->isReturn) { shouldBeEqual(curr->type, - unreachable, + Type(Type::unreachable), curr, "return_call should have unreachable type"); shouldBeEqual( @@ -657,11 +660,11 @@ void FunctionValidator::visitCall(Call* curr) { curr, "return_call callee return type must match caller return type"); } else { - if (curr->type == unreachable) { - bool hasUnreachableOperand = - std::any_of(curr->operands.begin(), - curr->operands.end(), - [](Expression* op) { return op->type == unreachable; }); + if (curr->type == Type::unreachable) { + bool hasUnreachableOperand = std::any_of( + curr->operands.begin(), curr->operands.end(), [](Expression* op) { + return op->type == Type::unreachable; + }); shouldBeTrue( hasUnreachableOperand, curr, @@ -683,8 +686,10 @@ void FunctionValidator::visitCallIndirect(CallIndirect* curr) { return; } const std::vector<Type>& params = curr->sig.params.expand(); - shouldBeEqualOrFirstIsUnreachable( - curr->target->type, i32, curr, "indirect call target must be an i32"); + shouldBeEqualOrFirstIsUnreachable(curr->target->type, + Type(Type::i32), + curr, + "indirect call target must be an i32"); if (!shouldBeTrue(curr->operands.size() == params.size(), curr, "call param number must match")) { @@ -701,7 +706,7 @@ void FunctionValidator::visitCallIndirect(CallIndirect* curr) { } if (curr->isReturn) { shouldBeEqual(curr->type, - unreachable, + Type(Type::unreachable), curr, "return_call_indirect should have unreachable type"); shouldBeEqual( @@ -710,12 +715,12 @@ void FunctionValidator::visitCallIndirect(CallIndirect* curr) { curr, "return_call_indirect callee return type must match caller return type"); } else { - if (curr->type == unreachable) { - if (curr->target->type != unreachable) { - bool hasUnreachableOperand = - std::any_of(curr->operands.begin(), - curr->operands.end(), - [](Expression* op) { return op->type == unreachable; }); + if (curr->type == Type::unreachable) { + if (curr->target->type != Type::unreachable) { + bool hasUnreachableOperand = std::any_of( + curr->operands.begin(), curr->operands.end(), [](Expression* op) { + return op->type == Type::unreachable; + }); shouldBeTrue(hasUnreachableOperand, curr, "call_indirects may only be unreachable if they have " @@ -754,8 +759,8 @@ void FunctionValidator::visitLocalSet(LocalSet* curr) { if (shouldBeTrue(curr->index < getFunction()->getNumLocals(), curr, "local.set index must be small enough")) { - if (curr->value->type != unreachable) { - if (curr->type != none) { // tee is ok anyhow + if (curr->value->type != Type::unreachable) { + if (curr->type != Type::none) { // tee is ok anyhow shouldBeEqual(getFunction()->getLocalType(curr->index), curr->type, curr, @@ -803,12 +808,12 @@ void FunctionValidator::visitLoad(Load* curr) { shouldBeTrue(getModule()->features.hasAtomics(), curr, "Atomic operation (atomics are disabled)"); - shouldBeTrue(curr->type == i32 || curr->type == i64 || - curr->type == unreachable, + shouldBeTrue(curr->type == Type::i32 || curr->type == Type::i64 || + curr->type == Type::unreachable, curr, "Atomic load should be i32 or i64"); } - if (curr->type == v128) { + if (curr->type == Type::v128) { shouldBeTrue(getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)"); @@ -819,7 +824,7 @@ void FunctionValidator::visitLoad(Load* curr) { validateMemBytes(curr->bytes, curr->type, curr); validateAlignment(curr->align, curr->type, curr->bytes, curr->isAtomic, curr); shouldBeEqualOrFirstIsUnreachable( - curr->ptr->type, i32, curr, "load pointer type must be i32"); + curr->ptr->type, Type(Type::i32), curr, "load pointer type must be i32"); if (curr->isAtomic) { shouldBeFalse(curr->signed_, curr, "atomic loads must be unsigned"); shouldBeIntOrUnreachable( @@ -834,12 +839,12 @@ void FunctionValidator::visitStore(Store* curr) { shouldBeTrue(getModule()->features.hasAtomics(), curr, "Atomic operation (atomics are disabled)"); - shouldBeTrue(curr->valueType == i32 || curr->valueType == i64 || - curr->valueType == unreachable, + shouldBeTrue(curr->valueType == Type::i32 || curr->valueType == Type::i64 || + curr->valueType == Type::unreachable, curr, "Atomic store should be i32 or i64"); } - if (curr->valueType == v128) { + if (curr->valueType == Type::v128) { shouldBeTrue(getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)"); @@ -851,9 +856,11 @@ void FunctionValidator::visitStore(Store* curr) { validateAlignment( curr->align, curr->valueType, curr->bytes, curr->isAtomic, curr); shouldBeEqualOrFirstIsUnreachable( - curr->ptr->type, i32, curr, "store pointer type must be i32"); - shouldBeUnequal( - curr->value->type, none, curr, "store value type must not be none"); + curr->ptr->type, Type(Type::i32), curr, "store pointer type must be i32"); + shouldBeUnequal(curr->value->type, + Type(Type::none), + curr, + "store value type must not be none"); shouldBeEqualOrFirstIsUnreachable( curr->value->type, curr->valueType, curr, "store value type must match"); if (curr->isAtomic) { @@ -872,8 +879,10 @@ void FunctionValidator::visitAtomicRMW(AtomicRMW* curr) { curr, "Atomic operation with non-shared memory"); validateMemBytes(curr->bytes, curr->type, curr); - shouldBeEqualOrFirstIsUnreachable( - curr->ptr->type, i32, curr, "AtomicRMW pointer type must be i32"); + shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, + Type(Type::i32), + curr, + "AtomicRMW pointer type must be i32"); shouldBeEqualOrFirstIsUnreachable(curr->type, curr->value->type, curr, @@ -893,9 +902,9 @@ void FunctionValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) { "Atomic operation with non-shared memory"); validateMemBytes(curr->bytes, curr->type, curr); shouldBeEqualOrFirstIsUnreachable( - curr->ptr->type, i32, curr, "cmpxchg pointer type must be i32"); - if (curr->expected->type != unreachable && - curr->replacement->type != unreachable) { + curr->ptr->type, Type(Type::i32), curr, "cmpxchg pointer type must be i32"); + if (curr->expected->type != Type::unreachable && + curr->replacement->type != Type::unreachable) { shouldBeEqual(curr->expected->type, curr->replacement->type, curr, @@ -925,9 +934,11 @@ void FunctionValidator::visitAtomicWait(AtomicWait* curr) { curr, "Atomic operation with non-shared memory"); shouldBeEqualOrFirstIsUnreachable( - curr->type, i32, curr, "AtomicWait must have type i32"); - shouldBeEqualOrFirstIsUnreachable( - curr->ptr->type, i32, curr, "AtomicWait pointer type must be i32"); + curr->type, Type(Type::i32), curr, "AtomicWait must have type i32"); + shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, + Type(Type::i32), + curr, + "AtomicWait pointer type must be i32"); shouldBeIntOrUnreachable( curr->expected->type, curr, "AtomicWait expected type must be int"); shouldBeEqualOrFirstIsUnreachable( @@ -935,8 +946,10 @@ void FunctionValidator::visitAtomicWait(AtomicWait* curr) { curr->expectedType, curr, "AtomicWait expected type must match operand"); - shouldBeEqualOrFirstIsUnreachable( - curr->timeout->type, i64, curr, "AtomicWait timeout type must be i64"); + shouldBeEqualOrFirstIsUnreachable(curr->timeout->type, + Type(Type::i64), + curr, + "AtomicWait timeout type must be i64"); } void FunctionValidator::visitAtomicNotify(AtomicNotify* curr) { @@ -949,12 +962,14 @@ void FunctionValidator::visitAtomicNotify(AtomicNotify* curr) { curr, "Atomic operation with non-shared memory"); shouldBeEqualOrFirstIsUnreachable( - curr->type, i32, curr, "AtomicNotify must have type i32"); - shouldBeEqualOrFirstIsUnreachable( - curr->ptr->type, i32, curr, "AtomicNotify pointer type must be i32"); + curr->type, Type(Type::i32), curr, "AtomicNotify must have type i32"); + shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, + Type(Type::i32), + curr, + "AtomicNotify pointer type must be i32"); shouldBeEqualOrFirstIsUnreachable( curr->notifyCount->type, - i32, + Type(Type::i32), curr, "AtomicNotify notifyCount type must be i32"); } @@ -977,35 +992,37 @@ void FunctionValidator::visitAtomicFence(AtomicFence* curr) { void FunctionValidator::visitSIMDExtract(SIMDExtract* curr) { shouldBeTrue( getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)"); - shouldBeEqualOrFirstIsUnreachable( - curr->vec->type, v128, curr, "extract_lane must operate on a v128"); - Type lane_t = none; + shouldBeEqualOrFirstIsUnreachable(curr->vec->type, + Type(Type::v128), + curr, + "extract_lane must operate on a v128"); + Type lane_t = Type::none; size_t lanes = 0; switch (curr->op) { case ExtractLaneSVecI8x16: case ExtractLaneUVecI8x16: - lane_t = i32; + lane_t = Type::i32; lanes = 16; break; case ExtractLaneSVecI16x8: case ExtractLaneUVecI16x8: - lane_t = i32; + lane_t = Type::i32; lanes = 8; break; case ExtractLaneVecI32x4: - lane_t = i32; + lane_t = Type::i32; lanes = 4; break; case ExtractLaneVecI64x2: - lane_t = i64; + lane_t = Type::i64; lanes = 2; break; case ExtractLaneVecF32x4: - lane_t = f32; + lane_t = Type::f32; lanes = 4; break; case ExtractLaneVecF64x2: - lane_t = f64; + lane_t = Type::f64; lanes = 2; break; } @@ -1021,34 +1038,36 @@ void FunctionValidator::visitSIMDReplace(SIMDReplace* curr) { shouldBeTrue( getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)"); shouldBeEqualOrFirstIsUnreachable( - curr->type, v128, curr, "replace_lane must have type v128"); - shouldBeEqualOrFirstIsUnreachable( - curr->vec->type, v128, curr, "replace_lane must operate on a v128"); - Type lane_t = none; + curr->type, Type(Type::v128), curr, "replace_lane must have type v128"); + shouldBeEqualOrFirstIsUnreachable(curr->vec->type, + Type(Type::v128), + curr, + "replace_lane must operate on a v128"); + Type lane_t = Type::none; size_t lanes = 0; switch (curr->op) { case ReplaceLaneVecI8x16: - lane_t = i32; + lane_t = Type::i32; lanes = 16; break; case ReplaceLaneVecI16x8: - lane_t = i32; + lane_t = Type::i32; lanes = 8; break; case ReplaceLaneVecI32x4: - lane_t = i32; + lane_t = Type::i32; lanes = 4; break; case ReplaceLaneVecI64x2: - lane_t = i64; + lane_t = Type::i64; lanes = 2; break; case ReplaceLaneVecF32x4: - lane_t = f32; + lane_t = Type::f32; lanes = 4; break; case ReplaceLaneVecF64x2: - lane_t = f64; + lane_t = Type::f64; lanes = 2; break; } @@ -1061,11 +1080,11 @@ void FunctionValidator::visitSIMDShuffle(SIMDShuffle* curr) { shouldBeTrue( getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)"); shouldBeEqualOrFirstIsUnreachable( - curr->type, v128, curr, "v128.shuffle must have type v128"); + curr->type, Type(Type::v128), curr, "v128.shuffle must have type v128"); shouldBeEqualOrFirstIsUnreachable( - curr->left->type, v128, curr, "expected operand of type v128"); + curr->left->type, Type(Type::v128), curr, "expected operand of type v128"); shouldBeEqualOrFirstIsUnreachable( - curr->right->type, v128, curr, "expected operand of type v128"); + curr->right->type, Type(Type::v128), curr, "expected operand of type v128"); for (uint8_t index : curr->mask) { shouldBeTrue(index < 32, curr, "Invalid lane index in mask"); } @@ -1075,24 +1094,26 @@ void FunctionValidator::visitSIMDTernary(SIMDTernary* curr) { shouldBeTrue( getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)"); shouldBeEqualOrFirstIsUnreachable( - curr->type, v128, curr, "SIMD ternary must have type v128"); + curr->type, Type(Type::v128), curr, "SIMD ternary must have type v128"); shouldBeEqualOrFirstIsUnreachable( - curr->a->type, v128, curr, "expected operand of type v128"); + curr->a->type, Type(Type::v128), curr, "expected operand of type v128"); shouldBeEqualOrFirstIsUnreachable( - curr->b->type, v128, curr, "expected operand of type v128"); + curr->b->type, Type(Type::v128), curr, "expected operand of type v128"); shouldBeEqualOrFirstIsUnreachable( - curr->c->type, v128, curr, "expected operand of type v128"); + curr->c->type, Type(Type::v128), curr, "expected operand of type v128"); } void FunctionValidator::visitSIMDShift(SIMDShift* curr) { shouldBeTrue( getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)"); shouldBeEqualOrFirstIsUnreachable( - curr->type, v128, curr, "vector shift must have type v128"); + curr->type, Type(Type::v128), curr, "vector shift must have type v128"); shouldBeEqualOrFirstIsUnreachable( - curr->vec->type, v128, curr, "expected operand of type v128"); - shouldBeEqualOrFirstIsUnreachable( - curr->shift->type, i32, curr, "expected shift amount to have type i32"); + curr->vec->type, Type(Type::v128), curr, "expected operand of type v128"); + shouldBeEqualOrFirstIsUnreachable(curr->shift->type, + Type(Type::i32), + curr, + "expected shift amount to have type i32"); } void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) { @@ -1101,15 +1122,17 @@ void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) { shouldBeTrue( getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)"); shouldBeEqualOrFirstIsUnreachable( - curr->type, v128, curr, "load_splat must have type v128"); - shouldBeEqualOrFirstIsUnreachable( - curr->ptr->type, i32, curr, "load_splat address must have type i32"); - Type memAlignType = none; + curr->type, Type(Type::v128), curr, "load_splat must have type v128"); + shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, + Type(Type::i32), + curr, + "load_splat address must have type i32"); + Type memAlignType = Type::none; switch (curr->op) { case LoadSplatVec8x16: case LoadSplatVec16x8: case LoadSplatVec32x4: - memAlignType = i32; + memAlignType = Type::i32; break; case LoadSplatVec64x2: case LoadExtSVec8x8ToVecI16x8: @@ -1118,7 +1141,7 @@ void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) { case LoadExtUVec16x4ToVecI32x4: case LoadExtSVec32x2ToVecI64x2: case LoadExtUVec32x2ToVecI64x2: - memAlignType = i64; + memAlignType = Type::i64; break; } Index bytes = curr->getMemBytes(); @@ -1130,13 +1153,15 @@ void FunctionValidator::visitMemoryInit(MemoryInit* curr) { curr, "Bulk memory operation (bulk memory is disabled)"); shouldBeEqualOrFirstIsUnreachable( - curr->type, none, curr, "memory.init must have type none"); - shouldBeEqualOrFirstIsUnreachable( - curr->dest->type, i32, curr, "memory.init dest must be an i32"); + curr->type, Type(Type::none), curr, "memory.init must have type none"); shouldBeEqualOrFirstIsUnreachable( - curr->offset->type, i32, curr, "memory.init offset must be an i32"); + curr->dest->type, Type(Type::i32), curr, "memory.init dest must be an i32"); + shouldBeEqualOrFirstIsUnreachable(curr->offset->type, + Type(Type::i32), + curr, + "memory.init offset must be an i32"); shouldBeEqualOrFirstIsUnreachable( - curr->size->type, i32, curr, "memory.init size must be an i32"); + curr->size->type, Type(Type::i32), curr, "memory.init size must be an i32"); if (!shouldBeTrue(getModule()->memory.exists, curr, "Memory operations require a memory")) { @@ -1152,7 +1177,7 @@ void FunctionValidator::visitDataDrop(DataDrop* curr) { curr, "Bulk memory operation (bulk memory is disabled)"); shouldBeEqualOrFirstIsUnreachable( - curr->type, none, curr, "data.drop must have type none"); + curr->type, Type(Type::none), curr, "data.drop must have type none"); if (!shouldBeTrue(getModule()->memory.exists, curr, "Memory operations require a memory")) { @@ -1168,13 +1193,15 @@ void FunctionValidator::visitMemoryCopy(MemoryCopy* curr) { curr, "Bulk memory operation (bulk memory is disabled)"); shouldBeEqualOrFirstIsUnreachable( - curr->type, none, curr, "memory.copy must have type none"); - shouldBeEqualOrFirstIsUnreachable( - curr->dest->type, i32, curr, "memory.copy dest must be an i32"); + curr->type, Type(Type::none), curr, "memory.copy must have type none"); shouldBeEqualOrFirstIsUnreachable( - curr->source->type, i32, curr, "memory.copy source must be an i32"); + curr->dest->type, Type(Type::i32), curr, "memory.copy dest must be an i32"); + shouldBeEqualOrFirstIsUnreachable(curr->source->type, + Type(Type::i32), + curr, + "memory.copy source must be an i32"); shouldBeEqualOrFirstIsUnreachable( - curr->size->type, i32, curr, "memory.copy size must be an i32"); + curr->size->type, Type(Type::i32), curr, "memory.copy size must be an i32"); shouldBeTrue( getModule()->memory.exists, curr, "Memory operations require a memory"); } @@ -1184,13 +1211,15 @@ void FunctionValidator::visitMemoryFill(MemoryFill* curr) { curr, "Bulk memory operation (bulk memory is disabled)"); shouldBeEqualOrFirstIsUnreachable( - curr->type, none, curr, "memory.fill must have type none"); - shouldBeEqualOrFirstIsUnreachable( - curr->dest->type, i32, curr, "memory.fill dest must be an i32"); + curr->type, Type(Type::none), curr, "memory.fill must have type none"); shouldBeEqualOrFirstIsUnreachable( - curr->value->type, i32, curr, "memory.fill value must be an i32"); + curr->dest->type, Type(Type::i32), curr, "memory.fill dest must be an i32"); + shouldBeEqualOrFirstIsUnreachable(curr->value->type, + Type(Type::i32), + curr, + "memory.fill value must be an i32"); shouldBeEqualOrFirstIsUnreachable( - curr->size->type, i32, curr, "memory.fill size must be an i32"); + curr->size->type, Type(Type::i32), curr, "memory.fill size must be an i32"); shouldBeTrue( getModule()->memory.exists, curr, "Memory operations require a memory"); } @@ -1199,41 +1228,42 @@ void FunctionValidator::validateMemBytes(uint8_t bytes, Type type, Expression* curr) { switch (type) { - case i32: + case Type::i32: shouldBeTrue(bytes == 1 || bytes == 2 || bytes == 4, curr, "expected i32 operation to touch 1, 2, or 4 bytes"); break; - case i64: + case Type::i64: shouldBeTrue(bytes == 1 || bytes == 2 || bytes == 4 || bytes == 8, curr, "expected i64 operation to touch 1, 2, 4, or 8 bytes"); break; - case f32: + case Type::f32: shouldBeEqual( bytes, uint8_t(4), curr, "expected f32 operation to touch 4 bytes"); break; - case f64: + case Type::f64: shouldBeEqual( bytes, uint8_t(8), curr, "expected f64 operation to touch 8 bytes"); break; - case v128: + case Type::v128: shouldBeEqual( bytes, uint8_t(16), curr, "expected v128 operation to touch 16 bytes"); break; - case unreachable: + case Type::unreachable: break; - case funcref: - case anyref: - case nullref: - case exnref: - case none: + case Type::funcref: + case Type::anyref: + case Type::nullref: + case Type::exnref: + case Type::none: WASM_UNREACHABLE("unexpected type"); } } void FunctionValidator::visitBinary(Binary* curr) { - if (curr->left->type != unreachable && curr->right->type != unreachable) { + if (curr->left->type != Type::unreachable && + curr->right->type != Type::unreachable) { shouldBeEqual(curr->left->type, curr->right->type, curr, @@ -1265,7 +1295,8 @@ void FunctionValidator::visitBinary(Binary* curr) { case GtUInt32: case GeSInt32: case GeUInt32: { - shouldBeEqualOrFirstIsUnreachable(curr->left->type, i32, curr, "i32 op"); + shouldBeEqualOrFirstIsUnreachable( + curr->left->type, Type(Type::i32), curr, "i32 op"); break; } case AddInt64: @@ -1293,7 +1324,8 @@ void FunctionValidator::visitBinary(Binary* curr) { case GtUInt64: case GeSInt64: case GeUInt64: { - shouldBeEqualOrFirstIsUnreachable(curr->left->type, i64, curr, "i64 op"); + shouldBeEqualOrFirstIsUnreachable( + curr->left->type, Type(Type::i64), curr, "i64 op"); break; } case AddFloat32: @@ -1309,7 +1341,8 @@ void FunctionValidator::visitBinary(Binary* curr) { case LeFloat32: case GtFloat32: case GeFloat32: { - shouldBeEqualOrFirstIsUnreachable(curr->left->type, f32, curr, "f32 op"); + shouldBeEqualOrFirstIsUnreachable( + curr->left->type, Type(Type::f32), curr, "f32 op"); break; } case AddFloat64: @@ -1325,7 +1358,8 @@ void FunctionValidator::visitBinary(Binary* curr) { case LeFloat64: case GtFloat64: case GeFloat64: { - shouldBeEqualOrFirstIsUnreachable(curr->left->type, f64, curr, "f64 op"); + shouldBeEqualOrFirstIsUnreachable( + curr->left->type, Type(Type::f64), curr, "f64 op"); break; } case EqVecI8x16: @@ -1426,9 +1460,9 @@ void FunctionValidator::visitBinary(Binary* curr) { case NarrowUVecI32x4ToVecI16x8: case SwizzleVec8x16: { shouldBeEqualOrFirstIsUnreachable( - curr->left->type, v128, curr, "v128 op"); + curr->left->type, Type(Type::v128), curr, "v128 op"); shouldBeEqualOrFirstIsUnreachable( - curr->right->type, v128, curr, "v128 op"); + curr->right->type, Type(Type::v128), curr, "v128 op"); break; } case InvalidBinary: @@ -1441,25 +1475,29 @@ void FunctionValidator::visitBinary(Binary* curr) { void FunctionValidator::visitUnary(Unary* curr) { shouldBeUnequal(curr->value->type, - none, + Type(Type::none), curr, "unaries must not receive a none as their input"); - if (curr->value->type == unreachable) { + if (curr->value->type == Type::unreachable) { return; // nothing to check } switch (curr->op) { case ClzInt32: case CtzInt32: case PopcntInt32: { - shouldBeEqual( - curr->value->type, i32, curr, "i32 unary value type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::i32), + curr, + "i32 unary value type must be correct"); break; } case ClzInt64: case CtzInt64: case PopcntInt64: { - shouldBeEqual( - curr->value->type, i64, curr, "i64 unary value type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::i64), + curr, + "i64 unary value type must be correct"); break; } case NegFloat32: @@ -1469,8 +1507,10 @@ void FunctionValidator::visitUnary(Unary* curr) { case TruncFloat32: case NearestFloat32: case SqrtFloat32: { - shouldBeEqual( - curr->value->type, f32, curr, "f32 unary value type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::f32), + curr, + "f32 unary value type must be correct"); break; } case NegFloat64: @@ -1480,128 +1520,166 @@ void FunctionValidator::visitUnary(Unary* curr) { case TruncFloat64: case NearestFloat64: case SqrtFloat64: { - shouldBeEqual( - curr->value->type, f64, curr, "f64 unary value type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::f64), + curr, + "f64 unary value type must be correct"); break; } case EqZInt32: { - shouldBeTrue(curr->value->type == i32, curr, "i32.eqz input must be i32"); + shouldBeTrue( + curr->value->type == Type::i32, curr, "i32.eqz input must be i32"); break; } case EqZInt64: { - shouldBeTrue(curr->value->type == i64, curr, "i64.eqz input must be i64"); + shouldBeTrue(curr->value->type == Type(Type::i64), + curr, + "i64.eqz input must be i64"); break; } case ExtendSInt32: case ExtendUInt32: case ExtendS8Int32: case ExtendS16Int32: { - shouldBeEqual( - curr->value->type, i32, curr, "extend type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::i32), + curr, + "extend type must be correct"); break; } case ExtendS8Int64: case ExtendS16Int64: case ExtendS32Int64: { - shouldBeEqual( - curr->value->type, i64, curr, "extend type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::i64), + curr, + "extend type must be correct"); break; } case WrapInt64: { - shouldBeEqual(curr->value->type, i64, curr, "wrap type must be correct"); + shouldBeEqual( + curr->value->type, Type(Type::i64), curr, "wrap type must be correct"); break; } case TruncSFloat32ToInt32: case TruncSFloat32ToInt64: case TruncUFloat32ToInt32: case TruncUFloat32ToInt64: { - shouldBeEqual(curr->value->type, f32, curr, "trunc type must be correct"); + shouldBeEqual( + curr->value->type, Type(Type::f32), curr, "trunc type must be correct"); break; } case TruncSatSFloat32ToInt32: case TruncSatSFloat32ToInt64: case TruncSatUFloat32ToInt32: case TruncSatUFloat32ToInt64: { - shouldBeEqual(curr->value->type, f32, curr, "trunc type must be correct"); + shouldBeEqual( + curr->value->type, Type(Type::f32), curr, "trunc type must be correct"); break; } case TruncSFloat64ToInt32: case TruncSFloat64ToInt64: case TruncUFloat64ToInt32: case TruncUFloat64ToInt64: { - shouldBeEqual(curr->value->type, f64, curr, "trunc type must be correct"); + shouldBeEqual( + curr->value->type, Type(Type::f64), curr, "trunc type must be correct"); break; } case TruncSatSFloat64ToInt32: case TruncSatSFloat64ToInt64: case TruncSatUFloat64ToInt32: case TruncSatUFloat64ToInt64: { - shouldBeEqual(curr->value->type, f64, curr, "trunc type must be correct"); + shouldBeEqual( + curr->value->type, Type(Type::f64), curr, "trunc type must be correct"); break; } case ReinterpretFloat32: { - shouldBeEqual( - curr->value->type, f32, curr, "reinterpret/f32 type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::f32), + curr, + "reinterpret/f32 type must be correct"); break; } case ReinterpretFloat64: { - shouldBeEqual( - curr->value->type, f64, curr, "reinterpret/f64 type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::f64), + curr, + "reinterpret/f64 type must be correct"); break; } case ConvertUInt32ToFloat32: case ConvertUInt32ToFloat64: case ConvertSInt32ToFloat32: case ConvertSInt32ToFloat64: { - shouldBeEqual( - curr->value->type, i32, curr, "convert type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::i32), + curr, + "convert type must be correct"); break; } case ConvertUInt64ToFloat32: case ConvertUInt64ToFloat64: case ConvertSInt64ToFloat32: case ConvertSInt64ToFloat64: { - shouldBeEqual( - curr->value->type, i64, curr, "convert type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::i64), + curr, + "convert type must be correct"); break; } case PromoteFloat32: { - shouldBeEqual( - curr->value->type, f32, curr, "promote type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::f32), + curr, + "promote type must be correct"); break; } case DemoteFloat64: { - shouldBeEqual( - curr->value->type, f64, curr, "demote type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::f64), + curr, + "demote type must be correct"); break; } case ReinterpretInt32: { - shouldBeEqual( - curr->value->type, i32, curr, "reinterpret/i32 type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::i32), + curr, + "reinterpret/i32 type must be correct"); break; } case ReinterpretInt64: { - shouldBeEqual( - curr->value->type, i64, curr, "reinterpret/i64 type must be correct"); + shouldBeEqual(curr->value->type, + Type(Type::i64), + curr, + "reinterpret/i64 type must be correct"); break; } case SplatVecI8x16: case SplatVecI16x8: case SplatVecI32x4: - shouldBeEqual(curr->type, v128, curr, "expected splat to have v128 type"); - shouldBeEqual(curr->value->type, i32, curr, "expected i32 splat value"); + shouldBeEqual( + curr->type, Type(Type::v128), curr, "expected splat to have v128 type"); + shouldBeEqual( + curr->value->type, Type(Type::i32), curr, "expected i32 splat value"); break; case SplatVecI64x2: - shouldBeEqual(curr->type, v128, curr, "expected splat to have v128 type"); - shouldBeEqual(curr->value->type, i64, curr, "expected i64 splat value"); + shouldBeEqual( + curr->type, Type(Type::v128), curr, "expected splat to have v128 type"); + shouldBeEqual( + curr->value->type, Type(Type::i64), curr, "expected i64 splat value"); break; case SplatVecF32x4: - shouldBeEqual(curr->type, v128, curr, "expected splat to have v128 type"); - shouldBeEqual(curr->value->type, f32, curr, "expected f32 splat value"); + shouldBeEqual( + curr->type, Type(Type::v128), curr, "expected splat to have v128 type"); + shouldBeEqual( + curr->value->type, Type(Type::f32), curr, "expected f32 splat value"); break; case SplatVecF64x2: - shouldBeEqual(curr->type, v128, curr, "expected splat to have v128 type"); - shouldBeEqual(curr->value->type, f64, curr, "expected i64 splat value"); + shouldBeEqual( + curr->type, Type(Type::v128), curr, "expected splat to have v128 type"); + shouldBeEqual( + curr->value->type, Type(Type::f64), curr, "expected f64 splat value"); break; case NotVec128: case NegVecI8x16: @@ -1630,8 +1708,9 @@ void FunctionValidator::visitUnary(Unary* curr) { case WidenHighSVecI16x8ToVecI32x4: case WidenLowUVecI16x8ToVecI32x4: case WidenHighUVecI16x8ToVecI32x4: - shouldBeEqual(curr->type, v128, curr, "expected v128 type"); - shouldBeEqual(curr->value->type, v128, curr, "expected v128 operand"); + shouldBeEqual(curr->type, Type(Type::v128), curr, "expected v128 type"); + shouldBeEqual( + curr->value->type, Type(Type::v128), curr, "expected v128 operand"); break; case AnyTrueVecI8x16: case AllTrueVecI8x16: @@ -1641,9 +1720,12 @@ void FunctionValidator::visitUnary(Unary* curr) { case AllTrueVecI32x4: case AnyTrueVecI64x2: case AllTrueVecI64x2: + shouldBeEqual(curr->type, + Type(Type::i32), + curr, + "expected boolean reduction to have i32 type"); shouldBeEqual( - curr->type, i32, curr, "expected boolean reduction to have i32 type"); - shouldBeEqual(curr->value->type, v128, curr, "expected v128 operand"); + curr->value->type, Type(Type::v128), curr, "expected v128 operand"); break; case InvalidUnary: WASM_UNREACHABLE("invalid unary op"); @@ -1654,15 +1736,15 @@ void FunctionValidator::visitUnary(Unary* curr) { } void FunctionValidator::visitSelect(Select* curr) { - shouldBeUnequal(curr->ifTrue->type, none, curr, "select left must be valid"); shouldBeUnequal( - curr->ifFalse->type, none, curr, "select right must be valid"); - shouldBeUnequal(curr->type, none, curr, "select type must be valid"); - shouldBeTrue(curr->condition->type == unreachable || - curr->condition->type == i32, + curr->ifFalse->type, Type(Type::none), curr, "select right must be valid"); + shouldBeUnequal( + curr->type, Type(Type::none), curr, "select type must be valid"); + shouldBeTrue(curr->condition->type == Type::unreachable || + curr->condition->type == Type::i32, curr, "select condition must be valid"); - if (curr->type != unreachable) { + if (curr->type != Type::unreachable) { shouldBeTrue(Type::isSubType(curr->ifTrue->type, curr->type), curr, "select's left expression must be subtype of select's type"); @@ -1674,7 +1756,7 @@ void FunctionValidator::visitSelect(Select* curr) { void FunctionValidator::visitDrop(Drop* curr) { shouldBeTrue(curr->value->type.isConcrete() || - curr->value->type == unreachable, + curr->value->type == Type::unreachable, curr, "can only drop a valid value"); } @@ -1693,7 +1775,7 @@ void FunctionValidator::visitHost(Host* curr) { curr, "memory.grow must have 1 operand"); shouldBeEqualOrFirstIsUnreachable(curr->operands[0]->type, - i32, + Type(Type::i32), curr, "memory.grow must have i32 operand"); break; @@ -1716,7 +1798,7 @@ void FunctionValidator::visitRefFunc(RefFunc* curr) { } void FunctionValidator::visitTry(Try* curr) { - if (curr->type != unreachable) { + if (curr->type != Type::unreachable) { shouldBeSubTypeOrFirstIsUnreachable( curr->body->type, curr->type, @@ -1729,11 +1811,11 @@ void FunctionValidator::visitTry(Try* curr) { "try's type does not match catch's body type"); } else { shouldBeEqual(curr->body->type, - unreachable, + Type(Type::unreachable), curr, "unreachable try-catch must have unreachable try body"); shouldBeEqual(curr->catchBody->type, - unreachable, + Type(Type::unreachable), curr, "unreachable try-catch must have unreachable catch body"); } @@ -1743,8 +1825,10 @@ void FunctionValidator::visitThrow(Throw* curr) { if (!info.validateGlobally) { return; } - shouldBeEqual( - curr->type, unreachable, curr, "throw's type must be unreachable"); + shouldBeEqual(curr->type, + Type(Type::unreachable), + curr, + "throw's type must be unreachable"); auto* event = getModule()->getEventOrNull(curr->event); if (!shouldBeTrue(!!event, curr, "throw's event must exist")) { return; @@ -1767,8 +1851,10 @@ void FunctionValidator::visitThrow(Throw* curr) { } void FunctionValidator::visitRethrow(Rethrow* curr) { - shouldBeEqual( - curr->type, unreachable, curr, "rethrow's type must be unreachable"); + shouldBeEqual(curr->type, + Type(Type::unreachable), + curr, + "rethrow's type must be unreachable"); shouldBeSubTypeOrFirstIsUnreachable( curr->exnref->type, Type::exnref, @@ -1788,13 +1874,13 @@ void FunctionValidator::visitBrOnExn(BrOnExn* curr) { Type::exnref, curr, "br_on_exn's argument must be unreachable or exnref type or its subtype"); - if (curr->exnref->type == unreachable) { - shouldBeTrue(curr->type == unreachable, + if (curr->exnref->type == Type::unreachable) { + shouldBeTrue(curr->type == Type::unreachable, curr, "If exnref argument's type is unreachable, br_on_exn should " "be unreachable too"); } else { - shouldBeTrue(curr->type == exnref, + shouldBeTrue(curr->type == Type::exnref, curr, "br_on_exn's type should be exnref unless its exnref argument " "is unreachable"); @@ -1890,24 +1976,24 @@ void FunctionValidator::validateAlignment( } shouldBeTrue(align <= bytes, curr, "alignment must not exceed natural"); switch (type) { - case i32: - case f32: { + case Type::i32: + case Type::f32: { shouldBeTrue(align <= 4, curr, "alignment must not exceed natural"); break; } - case i64: - case f64: { + case Type::i64: + case Type::f64: { shouldBeTrue(align <= 8, curr, "alignment must not exceed natural"); break; } - case v128: - case unreachable: + case Type::v128: + case Type::unreachable: break; - case funcref: - case anyref: - case nullref: - case exnref: - case none: + case Type::funcref: + case Type::anyref: + case Type::nullref: + case Type::exnref: + case Type::none: WASM_UNREACHABLE("invalid type"); } } @@ -1970,13 +2056,13 @@ static void validateImports(Module& module, ValidationInfo& info) { if (info.validateWeb) { for (Type param : curr->sig.params.expand()) { info.shouldBeUnequal(param, - i64, + Type(Type::i64), curr->name, "Imported function must not have i64 parameters"); } for (Type result : curr->sig.results.expand()) { info.shouldBeUnequal(result, - i64, + Type(Type::i64), curr->name, "Imported function must not have i64 results"); } @@ -1998,13 +2084,13 @@ static void validateExports(Module& module, ValidationInfo& info) { for (auto param : f->sig.params.expand()) { info.shouldBeUnequal( param, - i64, + Type(Type::i64), f->name, "Exported function must not have i64 parameters"); } for (auto result : f->sig.results.expand()) { info.shouldBeUnequal(result, - i64, + Type(Type::i64), f->name, "Exported function must not have i64 results"); } @@ -2103,7 +2189,7 @@ static void validateMemory(Module& module, ValidationInfo& info) { "passive segment should not have an offset"); } else { if (!info.shouldBeEqual(segment.offset->type, - i32, + Type(Type::i32), segment.offset, "segment offset should be i32")) { continue; @@ -2136,7 +2222,7 @@ static void validateTable(Module& module, ValidationInfo& info) { auto& curr = module.table; for (auto& segment : curr.segments) { info.shouldBeEqual(segment.offset->type, - i32, + Type(Type::i32), segment.offset, "segment offset should be i32"); info.shouldBeTrue(checkOffset(segment.offset, |