summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-validator.cpp
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2020-01-07 11:16:44 -0800
committerGitHub <noreply@github.com>2020-01-07 11:16:44 -0800
commite8f9d207427bda2f6e22c28ff0210b294b1f70e1 (patch)
tree503b20fb06274e38af7e25e3a1a4106827c52693 /src/wasm/wasm-validator.cpp
parentf73b40c7873dbd2dd46a962f3afe5b97a7fc8b0a (diff)
downloadbinaryen-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.cpp526
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,