summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-validator.cpp
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2022-11-01 13:07:36 -0700
committerGitHub <noreply@github.com>2022-11-01 20:07:36 +0000
commit0db7b571b23a09f96810c9d65d5f88d8eae4ba52 (patch)
treeb4bc44983623a09a0cca93b1d3b8ec9fc3d4a4ae /src/wasm/wasm-validator.cpp
parent5892f493706558a95d57b3731014b400fd832d70 (diff)
downloadbinaryen-0db7b571b23a09f96810c9d65d5f88d8eae4ba52.tar.gz
binaryen-0db7b571b23a09f96810c9d65d5f88d8eae4ba52.tar.bz2
binaryen-0db7b571b23a09f96810c9d65d5f88d8eae4ba52.zip
[NFC] Mention relevant flags in validator errors (#5203)
E.g. Atomic operation (atomics are disabled) => Atomic operations require threads [--enable-threads]
Diffstat (limited to 'src/wasm/wasm-validator.cpp')
-rw-r--r--src/wasm/wasm-validator.cpp209
1 files changed, 116 insertions, 93 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 642efac19..44ecbe9c9 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -504,7 +504,7 @@ private:
template<typename T> void validateReturnCall(T* curr) {
shouldBeTrue(!curr->isReturn || getModule()->features.hasTailCall(),
curr,
- "return_call* requires tail calls to be enabled");
+ "return_call* requires tail calls [--enable-tail-call]");
}
// |printable| is the expression to print in case of an error. That may differ
@@ -612,9 +612,10 @@ void FunctionValidator::validatePoppyExpression(Expression* curr) {
void FunctionValidator::visitBlock(Block* curr) {
if (!getModule()->features.hasMultivalue()) {
- shouldBeTrue(!curr->type.isTuple(),
- curr,
- "Multivalue block type (multivalue is not enabled)");
+ shouldBeTrue(
+ !curr->type.isTuple(),
+ curr,
+ "Multivalue block type require multivalue [--enable-multivalue]");
}
// if we are break'ed to, then the value must be right for us
if (curr->name.is()) {
@@ -1003,7 +1004,7 @@ void FunctionValidator::visitLoad(Load* curr) {
if (curr->isAtomic) {
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
- "Atomic operation (atomics are disabled)");
+ "Atomic operations require threads [--enable-threads]");
shouldBeTrue(curr->type == Type::i32 || curr->type == Type::i64 ||
curr->type == Type::unreachable,
curr,
@@ -1012,7 +1013,7 @@ void FunctionValidator::visitLoad(Load* curr) {
if (curr->type == Type::v128) {
shouldBeTrue(getModule()->features.hasSIMD(),
curr,
- "SIMD operation (SIMD is disabled)");
+ "SIMD operations require SIMD [--enable-simd]");
}
validateMemBytes(curr->bytes, curr->type, curr);
validateAlignment(curr->align, curr->type, curr->bytes, curr->isAtomic, curr);
@@ -1034,7 +1035,7 @@ void FunctionValidator::visitStore(Store* curr) {
if (curr->isAtomic) {
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
- "Atomic operation (atomics are disabled)");
+ "Atomic operations require threads [--enable-threads]");
shouldBeTrue(curr->valueType == Type::i32 || curr->valueType == Type::i64 ||
curr->valueType == Type::unreachable,
curr,
@@ -1043,7 +1044,7 @@ void FunctionValidator::visitStore(Store* curr) {
if (curr->valueType == Type::v128) {
shouldBeTrue(getModule()->features.hasSIMD(),
curr,
- "SIMD operation (SIMD is disabled)");
+ "SIMD operations require SIMD [--enable-simd]");
}
validateMemBytes(curr->bytes, curr->valueType, curr);
validateAlignment(
@@ -1070,7 +1071,7 @@ void FunctionValidator::visitAtomicRMW(AtomicRMW* curr) {
shouldBeTrue(!!memory, curr, "memory.atomicRMW memory must exist");
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
- "Atomic operation (atomics are disabled)");
+ "Atomic operations require threads [--enable-threads]");
validateMemBytes(curr->bytes, curr->type, curr);
shouldBeEqualOrFirstIsUnreachable(
curr->ptr->type,
@@ -1090,7 +1091,7 @@ void FunctionValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) {
shouldBeTrue(!!memory, curr, "memory.atomicCmpxchg memory must exist");
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
- "Atomic operation (atomics are disabled)");
+ "Atomic operations require threads [--enable-threads]");
validateMemBytes(curr->bytes, curr->type, curr);
shouldBeEqualOrFirstIsUnreachable(
curr->ptr->type,
@@ -1123,7 +1124,7 @@ void FunctionValidator::visitAtomicWait(AtomicWait* curr) {
shouldBeTrue(!!memory, curr, "memory.atomicWait memory must exist");
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
- "Atomic operation (atomics are disabled)");
+ "Atomic operations require threads [--enable-threads]");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::i32), curr, "AtomicWait must have type i32");
shouldBeEqualOrFirstIsUnreachable(
@@ -1149,7 +1150,7 @@ void FunctionValidator::visitAtomicNotify(AtomicNotify* curr) {
shouldBeTrue(!!memory, curr, "memory.atomicNotify memory must exist");
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
- "Atomic operation (atomics are disabled)");
+ "Atomic operations require threads [--enable-threads]");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::i32), curr, "AtomicNotify must have type i32");
shouldBeEqualOrFirstIsUnreachable(
@@ -1169,7 +1170,7 @@ void FunctionValidator::visitAtomicFence(AtomicFence* curr) {
getModule()->memories.empty(), curr, "Memory operations require a memory");
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
- "Atomic operation (atomics are disabled)");
+ "Atomic operations require threads [--enable-threads]");
shouldBeTrue(curr->order == 0,
curr,
"Currently only sequentially consistent atomics are supported, "
@@ -1177,8 +1178,9 @@ void FunctionValidator::visitAtomicFence(AtomicFence* curr) {
}
void FunctionValidator::visitSIMDExtract(SIMDExtract* curr) {
- shouldBeTrue(
- getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)");
+ shouldBeTrue(getModule()->features.hasSIMD(),
+ curr,
+ "SIMD operations require SIMD [--enable-simd]");
shouldBeEqualOrFirstIsUnreachable(curr->vec->type,
Type(Type::v128),
curr,
@@ -1222,8 +1224,9 @@ void FunctionValidator::visitSIMDExtract(SIMDExtract* curr) {
}
void FunctionValidator::visitSIMDReplace(SIMDReplace* curr) {
- shouldBeTrue(
- getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)");
+ shouldBeTrue(getModule()->features.hasSIMD(),
+ curr,
+ "SIMD operations require SIMD [--enable-simd]");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::v128), curr, "replace_lane must have type v128");
shouldBeEqualOrFirstIsUnreachable(curr->vec->type,
@@ -1264,8 +1267,9 @@ void FunctionValidator::visitSIMDReplace(SIMDReplace* curr) {
}
void FunctionValidator::visitSIMDShuffle(SIMDShuffle* curr) {
- shouldBeTrue(
- getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)");
+ shouldBeTrue(getModule()->features.hasSIMD(),
+ curr,
+ "SIMD operations require SIMD [--enable-simd]");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::v128), curr, "i8x16.shuffle must have type v128");
shouldBeEqualOrFirstIsUnreachable(
@@ -1278,8 +1282,9 @@ void FunctionValidator::visitSIMDShuffle(SIMDShuffle* curr) {
}
void FunctionValidator::visitSIMDTernary(SIMDTernary* curr) {
- shouldBeTrue(
- getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)");
+ shouldBeTrue(getModule()->features.hasSIMD(),
+ curr,
+ "SIMD operations require SIMD [--enable-simd]");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::v128), curr, "SIMD ternary must have type v128");
shouldBeEqualOrFirstIsUnreachable(
@@ -1291,8 +1296,9 @@ void FunctionValidator::visitSIMDTernary(SIMDTernary* curr) {
}
void FunctionValidator::visitSIMDShift(SIMDShift* curr) {
- shouldBeTrue(
- getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)");
+ shouldBeTrue(getModule()->features.hasSIMD(),
+ curr,
+ "SIMD operations require SIMD [--enable-simd]");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::v128), curr, "vector shift must have type v128");
shouldBeEqualOrFirstIsUnreachable(
@@ -1306,8 +1312,9 @@ void FunctionValidator::visitSIMDShift(SIMDShift* curr) {
void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) {
auto* memory = getModule()->getMemoryOrNull(curr->memory);
shouldBeTrue(!!memory, curr, "memory.SIMDLoad memory must exist");
- shouldBeTrue(
- getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)");
+ shouldBeTrue(getModule()->features.hasSIMD(),
+ curr,
+ "SIMD operations require SIMD [--enable-simd]");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::v128), curr, "load_splat must have type v128");
shouldBeEqualOrFirstIsUnreachable(
@@ -1341,8 +1348,9 @@ void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) {
void FunctionValidator::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
auto* memory = getModule()->getMemoryOrNull(curr->memory);
shouldBeTrue(!!memory, curr, "memory.SIMDLoadStoreLane memory must exist");
- shouldBeTrue(
- getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)");
+ shouldBeTrue(getModule()->features.hasSIMD(),
+ curr,
+ "SIMD operations require SIMD [--enable-simd]");
if (curr->isLoad()) {
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::v128), curr, "loadX_lane must have type v128");
@@ -1392,9 +1400,10 @@ void FunctionValidator::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
}
void FunctionValidator::visitMemoryInit(MemoryInit* curr) {
- shouldBeTrue(getModule()->features.hasBulkMemory(),
- curr,
- "Bulk memory operation (bulk memory is disabled)");
+ shouldBeTrue(
+ getModule()->features.hasBulkMemory(),
+ curr,
+ "Bulk memory operations require bulk memory [--enable-bulk-memory]");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::none), curr, "memory.init must have type none");
shouldBeEqualOrFirstIsUnreachable(
@@ -1418,9 +1427,10 @@ void FunctionValidator::visitMemoryInit(MemoryInit* curr) {
}
void FunctionValidator::visitDataDrop(DataDrop* curr) {
- shouldBeTrue(getModule()->features.hasBulkMemory(),
- curr,
- "Bulk memory operation (bulk memory is disabled)");
+ shouldBeTrue(
+ getModule()->features.hasBulkMemory(),
+ curr,
+ "Bulk memory operations require bulk memory [--enable-bulk-memory]");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::none), curr, "data.drop must have type none");
if (!shouldBeFalse(getModule()->memories.empty(),
@@ -1434,9 +1444,10 @@ void FunctionValidator::visitDataDrop(DataDrop* curr) {
}
void FunctionValidator::visitMemoryCopy(MemoryCopy* curr) {
- shouldBeTrue(getModule()->features.hasBulkMemory(),
- curr,
- "Bulk memory operation (bulk memory is disabled)");
+ shouldBeTrue(
+ getModule()->features.hasBulkMemory(),
+ curr,
+ "Bulk memory operations require bulk memory [--enable-bulk-memory]");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::none), curr, "memory.copy must have type none");
auto* destMemory = getModule()->getMemoryOrNull(curr->destMemory);
@@ -1466,9 +1477,10 @@ void FunctionValidator::visitMemoryCopy(MemoryCopy* curr) {
}
void FunctionValidator::visitMemoryFill(MemoryFill* curr) {
- shouldBeTrue(getModule()->features.hasBulkMemory(),
- curr,
- "Bulk memory operation (bulk memory is disabled)");
+ shouldBeTrue(
+ getModule()->features.hasBulkMemory(),
+ curr,
+ "Bulk memory operations require bulk memory [--enable-bulk-memory]");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::none), curr, "memory.fill must have type none");
shouldBeEqualOrFirstIsUnreachable(
@@ -2109,7 +2121,7 @@ void FunctionValidator::visitRefNull(RefNull* curr) {
// features are enabled.
shouldBeTrue(!getFunction() || getModule()->features.hasReferenceTypes(),
curr,
- "ref.null requires reference-types to be enabled");
+ "ref.null requires reference-types [--enable-reference-types]");
if (!shouldBeTrue(
curr->type.isNullable(), curr, "ref.null types must be nullable")) {
return;
@@ -2121,7 +2133,7 @@ void FunctionValidator::visitRefNull(RefNull* curr) {
void FunctionValidator::visitRefIs(RefIs* curr) {
shouldBeTrue(getModule()->features.hasReferenceTypes(),
curr,
- "ref.is_* requires reference-types to be enabled");
+ "ref.is_* requires reference-types [--enable-reference-types]");
shouldBeTrue(curr->value->type == Type::unreachable ||
curr->value->type.isRef(),
curr->value,
@@ -2136,7 +2148,7 @@ void FunctionValidator::visitRefAs(RefAs* curr) {
case ExternInternalize: {
shouldBeTrue(getModule()->features.hasGC(),
curr,
- "extern.internalize requries GC to be enabled");
+ "extern.internalize requries GC [--enable-gc]");
if (curr->type == Type::unreachable) {
return;
}
@@ -2149,7 +2161,7 @@ void FunctionValidator::visitRefAs(RefAs* curr) {
case ExternExternalize: {
shouldBeTrue(getModule()->features.hasGC(),
curr,
- "extern.externalize requries GC to be enabled");
+ "extern.externalize requries GC [--enable-gc]");
if (curr->type == Type::unreachable) {
return;
}
@@ -2168,7 +2180,7 @@ void FunctionValidator::visitRefFunc(RefFunc* curr) {
// features are enabled.
shouldBeTrue(!getFunction() || getModule()->features.hasReferenceTypes(),
curr,
- "ref.func requires reference-types to be enabled");
+ "ref.func requires reference-types [--enable-reference-types]");
if (!info.validateGlobally) {
return;
}
@@ -2192,7 +2204,7 @@ void FunctionValidator::visitRefFunc(RefFunc* curr) {
void FunctionValidator::visitRefEq(RefEq* curr) {
Type eqref = Type(HeapType::eq, Nullable);
shouldBeTrue(
- getModule()->features.hasGC(), curr, "ref.eq requires gc to be enabled");
+ getModule()->features.hasGC(), curr, "ref.eq requires gc [--enable-gc]");
shouldBeSubType(curr->left->type,
eqref,
curr->left,
@@ -2206,7 +2218,7 @@ void FunctionValidator::visitRefEq(RefEq* curr) {
void FunctionValidator::visitTableGet(TableGet* curr) {
shouldBeTrue(getModule()->features.hasReferenceTypes(),
curr,
- "table.get requires reference types to be enabled");
+ "table.get requires reference types [--enable-reference-types]");
shouldBeEqualOrFirstIsUnreachable(
curr->index->type, Type(Type::i32), curr, "table.get index must be an i32");
auto* table = getModule()->getTableOrNull(curr->table);
@@ -2220,7 +2232,7 @@ void FunctionValidator::visitTableGet(TableGet* curr) {
void FunctionValidator::visitTableSet(TableSet* curr) {
shouldBeTrue(getModule()->features.hasReferenceTypes(),
curr,
- "table.set requires reference types to be enabled");
+ "table.set requires reference types [--enable-reference-types]");
shouldBeEqualOrFirstIsUnreachable(
curr->index->type, Type(Type::i32), curr, "table.set index must be an i32");
auto* table = getModule()->getTableOrNull(curr->table);
@@ -2234,17 +2246,19 @@ void FunctionValidator::visitTableSet(TableSet* curr) {
}
void FunctionValidator::visitTableSize(TableSize* curr) {
- shouldBeTrue(getModule()->features.hasReferenceTypes(),
- curr,
- "table.size requires reference types to be enabled");
+ shouldBeTrue(
+ getModule()->features.hasReferenceTypes(),
+ curr,
+ "table.size requires reference types [--enable-reference-types]");
auto* table = getModule()->getTableOrNull(curr->table);
shouldBeTrue(!!table, curr, "table.size table must exist");
}
void FunctionValidator::visitTableGrow(TableGrow* curr) {
- shouldBeTrue(getModule()->features.hasReferenceTypes(),
- curr,
- "table.grow requires reference types to be enabled");
+ shouldBeTrue(
+ getModule()->features.hasReferenceTypes(),
+ curr,
+ "table.grow requires reference types [--enable-reference-types]");
auto* table = getModule()->getTableOrNull(curr->table);
if (shouldBeTrue(!!table, curr, "table.grow table must exist") &&
curr->type != Type::unreachable) {
@@ -2276,7 +2290,7 @@ void FunctionValidator::noteRethrow(Name name, Expression* curr) {
void FunctionValidator::visitTry(Try* curr) {
shouldBeTrue(getModule()->features.hasExceptionHandling(),
curr,
- "try requires exception-handling to be enabled");
+ "try requires exception-handling [--enable-exception-handling]");
if (curr->name.is()) {
noteLabelName(curr->name);
}
@@ -2361,9 +2375,10 @@ void FunctionValidator::visitTry(Try* curr) {
}
void FunctionValidator::visitThrow(Throw* curr) {
- shouldBeTrue(getModule()->features.hasExceptionHandling(),
- curr,
- "throw requires exception-handling to be enabled");
+ shouldBeTrue(
+ getModule()->features.hasExceptionHandling(),
+ curr,
+ "throw requires exception-handling [--enable-exception-handling]");
shouldBeEqual(curr->type,
Type(Type::unreachable),
curr,
@@ -2394,9 +2409,10 @@ void FunctionValidator::visitThrow(Throw* curr) {
}
void FunctionValidator::visitRethrow(Rethrow* curr) {
- shouldBeTrue(getModule()->features.hasExceptionHandling(),
- curr,
- "rethrow requires exception-handling to be enabled");
+ shouldBeTrue(
+ getModule()->features.hasExceptionHandling(),
+ curr,
+ "rethrow requires exception-handling [--enable-exception-handling]");
shouldBeEqual(curr->type,
Type(Type::unreachable),
curr,
@@ -2452,7 +2468,7 @@ void FunctionValidator::visitTupleExtract(TupleExtract* curr) {
void FunctionValidator::visitCallRef(CallRef* curr) {
validateReturnCall(curr);
shouldBeTrue(
- getModule()->features.hasGC(), curr, "call_ref requires gc to be enabled");
+ getModule()->features.hasGC(), curr, "call_ref requires gc [--enable-gc]");
if (curr->target->type == Type::unreachable ||
(curr->target->type.isRef() &&
curr->target->type.getHeapType() == HeapType::nofunc)) {
@@ -2467,7 +2483,7 @@ void FunctionValidator::visitCallRef(CallRef* curr) {
void FunctionValidator::visitI31New(I31New* curr) {
shouldBeTrue(
- getModule()->features.hasGC(), curr, "i31.new requires gc to be enabled");
+ getModule()->features.hasGC(), curr, "i31.new requires gc [--enable-gc]");
shouldBeSubType(curr->value->type,
Type::i32,
curr->value,
@@ -2477,7 +2493,7 @@ void FunctionValidator::visitI31New(I31New* curr) {
void FunctionValidator::visitI31Get(I31Get* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
- "i31.get_s/u requires gc to be enabled");
+ "i31.get_s/u requires gc [--enable-gc]");
shouldBeSubType(curr->i31->type,
Type(HeapType::i31, Nullable),
curr->i31,
@@ -2486,7 +2502,7 @@ void FunctionValidator::visitI31Get(I31Get* curr) {
void FunctionValidator::visitRefTest(RefTest* curr) {
shouldBeTrue(
- getModule()->features.hasGC(), curr, "ref.test requires gc to be enabled");
+ getModule()->features.hasGC(), curr, "ref.test requires gc [--enable-gc]");
if (curr->ref->type != Type::unreachable) {
shouldBeTrue(
curr->ref->type.isRef(), curr, "ref.test ref must have ref type");
@@ -2501,7 +2517,7 @@ void FunctionValidator::visitRefTest(RefTest* curr) {
void FunctionValidator::visitRefCast(RefCast* curr) {
shouldBeTrue(
- getModule()->features.hasGC(), curr, "ref.cast requires gc to be enabled");
+ getModule()->features.hasGC(), curr, "ref.cast requires gc [--enable-gc]");
if (curr->ref->type != Type::unreachable) {
shouldBeTrue(
curr->ref->type.isRef(), curr, "ref.cast ref must have ref type");
@@ -2517,7 +2533,7 @@ void FunctionValidator::visitRefCast(RefCast* curr) {
void FunctionValidator::visitBrOn(BrOn* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
- "br_on_cast requires gc to be enabled");
+ "br_on_cast requires gc [--enable-gc]");
if (curr->ref->type != Type::unreachable) {
shouldBeTrue(
curr->ref->type.isRef(), curr, "br_on_cast ref must have ref type");
@@ -2542,7 +2558,7 @@ void FunctionValidator::visitBrOn(BrOn* curr) {
void FunctionValidator::visitStructNew(StructNew* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
- "struct.new requires gc to be enabled");
+ "struct.new requires gc [--enable-gc]");
if (curr->type == Type::unreachable) {
return;
}
@@ -2581,7 +2597,7 @@ void FunctionValidator::visitStructNew(StructNew* curr) {
void FunctionValidator::visitStructGet(StructGet* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
- "struct.get requires gc to be enabled");
+ "struct.get requires gc [--enable-gc]");
if (curr->type == Type::unreachable || curr->ref->type.isNull()) {
return;
}
@@ -2608,7 +2624,7 @@ void FunctionValidator::visitStructGet(StructGet* curr) {
void FunctionValidator::visitStructSet(StructSet* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
- "struct.set requires gc to be enabled");
+ "struct.set requires gc [--enable-gc]");
if (curr->ref->type == Type::unreachable) {
return;
}
@@ -2638,7 +2654,7 @@ void FunctionValidator::visitStructSet(StructSet* curr) {
void FunctionValidator::visitArrayNew(ArrayNew* curr) {
shouldBeTrue(
- getModule()->features.hasGC(), curr, "array.new requires gc to be enabled");
+ getModule()->features.hasGC(), curr, "array.new requires gc [--enable-gc]");
shouldBeEqualOrFirstIsUnreachable(
curr->size->type, Type(Type::i32), curr, "array.new size must be an i32");
if (curr->type == Type::unreachable) {
@@ -2670,7 +2686,7 @@ void FunctionValidator::visitArrayNew(ArrayNew* curr) {
void FunctionValidator::visitArrayInit(ArrayInit* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
- "array.init requires gc to be enabled");
+ "array.init requires gc [--enable-gc]");
if (curr->type == Type::unreachable) {
return;
}
@@ -2690,7 +2706,7 @@ void FunctionValidator::visitArrayInit(ArrayInit* curr) {
void FunctionValidator::visitArrayGet(ArrayGet* curr) {
shouldBeTrue(
- getModule()->features.hasGC(), curr, "array.get requires gc to be enabled");
+ getModule()->features.hasGC(), curr, "array.get requires gc [--enable-gc]");
shouldBeEqualOrFirstIsUnreachable(
curr->index->type, Type(Type::i32), curr, "array.get index must be an i32");
if (curr->type == Type::unreachable) {
@@ -2723,7 +2739,7 @@ void FunctionValidator::visitArrayGet(ArrayGet* curr) {
void FunctionValidator::visitArraySet(ArraySet* curr) {
shouldBeTrue(
- getModule()->features.hasGC(), curr, "array.set requires gc to be enabled");
+ getModule()->features.hasGC(), curr, "array.set requires gc [--enable-gc]");
shouldBeEqualOrFirstIsUnreachable(
curr->index->type, Type(Type::i32), curr, "array.set index must be an i32");
if (curr->type == Type::unreachable) {
@@ -2754,7 +2770,7 @@ void FunctionValidator::visitArraySet(ArraySet* curr) {
void FunctionValidator::visitArrayLen(ArrayLen* curr) {
shouldBeTrue(
- getModule()->features.hasGC(), curr, "array.len requires gc to be enabled");
+ getModule()->features.hasGC(), curr, "array.len requires gc [--enable-gc]");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::i32), curr, "array.len result must be an i32");
shouldBeSubType(curr->ref->type,
@@ -2766,7 +2782,7 @@ void FunctionValidator::visitArrayLen(ArrayLen* curr) {
void FunctionValidator::visitArrayCopy(ArrayCopy* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
- "array.copy requires gc to be enabled");
+ "array.copy requires gc [--enable-gc]");
shouldBeEqualOrFirstIsUnreachable(curr->srcIndex->type,
Type(Type::i32),
curr,
@@ -3014,8 +3030,8 @@ static void validateImports(Module& module, ValidationInfo& info) {
if (curr->getResults().isTuple()) {
info.shouldBeTrue(module.features.hasMultivalue(),
curr->name,
- "Imported multivalue function "
- "(multivalue is not enabled)");
+ "Imported multivalue function requires multivalue "
+ "[--enable-multivalue]");
}
if (info.validateWeb) {
for (const auto& param : curr->getParams()) {
@@ -3044,8 +3060,10 @@ static void validateImports(Module& module, ValidationInfo& info) {
});
ModuleUtils::iterImportedGlobals(module, [&](Global* curr) {
if (!module.features.hasMutableGlobals()) {
- info.shouldBeFalse(
- curr->mutable_, curr->name, "Imported global cannot be mutable");
+ info.shouldBeFalse(curr->mutable_,
+ curr->name,
+ "Imported mutable global requires mutable-globals "
+ "[--enable-mutable-globals]");
}
info.shouldBeFalse(
curr->type.isTuple(), curr->name, "Imported global cannot be tuple");
@@ -3074,8 +3092,10 @@ static void validateExports(Module& module, ValidationInfo& info) {
} else if (curr->kind == ExternalKind::Global) {
if (Global* g = module.getGlobalOrNull(curr->value)) {
if (!module.features.hasMutableGlobals()) {
- info.shouldBeFalse(
- g->mutable_, g->name, "Exported global cannot be mutable");
+ info.shouldBeFalse(g->mutable_,
+ g->name,
+ "Exported mutable global requires mutable-globals "
+ "[--enable-mutable-globals]");
}
info.shouldBeFalse(
g->type.isTuple(), g->name, "Exported global cannot be tuple");
@@ -3144,7 +3164,7 @@ static void validateMemories(Module& module, ValidationInfo& info) {
info.shouldBeTrue(
module.features.hasMultiMemories(),
"memory",
- "multiple memories present, but multi-memories is disabled");
+ "multiple memories require multi-memories [--enable-multi-memories]");
}
for (auto& memory : module.memories) {
if (memory->hasMax()) {
@@ -3154,7 +3174,7 @@ static void validateMemories(Module& module, ValidationInfo& info) {
if (memory->is64()) {
info.shouldBeTrue(module.features.hasMemory64(),
"memory",
- "memory is 64-bit, but memory64 is disabled");
+ "64-bit memories require memory64 [--enable-memory64]");
} else {
info.shouldBeTrue(memory->initial <= Memory::kMaxSize32,
"memory",
@@ -3169,7 +3189,7 @@ static void validateMemories(Module& module, ValidationInfo& info) {
if (memory->shared) {
info.shouldBeTrue(module.features.hasAtomics(),
"memory",
- "memory is shared, but atomics are disabled");
+ "shared memory requires threads [--enable-threads]");
}
}
}
@@ -3178,9 +3198,10 @@ static void validateDataSegments(Module& module, ValidationInfo& info) {
for (auto& segment : module.dataSegments) {
auto size = segment->data.size();
if (segment->isPassive) {
- info.shouldBeTrue(module.features.hasBulkMemory(),
- segment->offset,
- "nonzero segment flags (bulk memory is disabled)");
+ info.shouldBeTrue(
+ module.features.hasBulkMemory(),
+ segment->offset,
+ "nonzero segment flags require bulk memory [--enable-bulk-memory]");
info.shouldBeEqual(segment->offset,
(Expression*)nullptr,
segment->offset,
@@ -3346,9 +3367,10 @@ static void validateTables(Module& module, ValidationInfo& info) {
static void validateTags(Module& module, ValidationInfo& info) {
if (!module.tags.empty()) {
- info.shouldBeTrue(module.features.hasExceptionHandling(),
- module.tags[0]->name,
- "Module has tags (exception-handling is disabled)");
+ info.shouldBeTrue(
+ module.features.hasExceptionHandling(),
+ module.tags[0]->name,
+ "Tags require exception-handling [--enable-exception-handling]");
}
for (auto& curr : module.tags) {
info.shouldBeEqual(curr->sig.results,
@@ -3356,9 +3378,10 @@ static void validateTags(Module& module, ValidationInfo& info) {
curr->name,
"Tag type's result type should be none");
if (curr->sig.params.isTuple()) {
- info.shouldBeTrue(module.features.hasMultivalue(),
- curr->name,
- "Multivalue tag type (multivalue is not enabled)");
+ info.shouldBeTrue(
+ module.features.hasMultivalue(),
+ curr->name,
+ "Multivalue tag type requires multivalue [--enable-multivalue]");
}
for (const auto& param : curr->sig.params) {
info.shouldBeTrue(param.isConcrete(),