summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-validator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-validator.cpp')
-rw-r--r--src/wasm/wasm-validator.cpp26
1 files changed, 25 insertions, 1 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index c1f44a68b..1b328ec19 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -220,22 +220,46 @@ void WasmValidator::visitSetLocal(SetLocal *curr) {
}
}
void WasmValidator::visitLoad(Load *curr) {
+ if (curr->isAtomic && !getModule()->memory.shared) fail("Atomic operation with non-shared memory", 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");
}
void WasmValidator::visitStore(Store *curr) {
+ if (curr->isAtomic && !getModule()->memory.shared) fail("Atomic operation with non-shared memory", curr);
validateMemBytes(curr->bytes, curr->valueType, curr);
validateAlignment(curr->align, curr->type, 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");
shouldBeEqualOrFirstIsUnreachable(curr->value->type, curr->valueType, curr, "store value type must match");
}
+void WasmValidator::shouldBeIntOrUnreachable(WasmType ty, Expression* curr, const char* text) {
+ switch (ty) {
+ case i32:
+ case i64:
+ case unreachable: {
+ break;
+ }
+ default: fail(text, curr);
+ }
+}
void WasmValidator::visitAtomicRMW(AtomicRMW* curr) {
+ if (!getModule()->memory.shared) fail("Atomic operation with non-shared memory", curr);
validateMemBytes(curr->bytes, curr->type, curr);
+ shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "AtomicRMW pointer type must be i32");
+ shouldBeEqualOrFirstIsUnreachable(curr->value->type, curr->type, curr, "AtomicRMW result type must match operand");
+ shouldBeIntOrUnreachable(curr->type, curr, "Atomic operations are only valid on int types");
}
void WasmValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) {
+ if (!getModule()->memory.shared) fail("Atomic operation with non-shared memory", curr);
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) {
+ shouldBeEqual(curr->expected->type, curr->replacement->type, curr, "cmpxchg operand types must match");
+ }
+ shouldBeEqualOrFirstIsUnreachable(curr->expected->type, curr->type, curr, "Cmpxchg result type must match expected");
+ shouldBeEqualOrFirstIsUnreachable(curr->replacement->type, curr->type, curr, "Cmpxchg result type must match replacement");
+ shouldBeIntOrUnreachable(curr->expected->type, curr, "Atomic operations are only valid on int types");
}
void WasmValidator::validateMemBytes(uint8_t bytes, WasmType ty, Expression* curr) {
switch (bytes) {
@@ -655,7 +679,7 @@ void WasmValidator::validateBinaryenIR(Module& wasm) {
}
template <typename T, typename S>
-std::ostream& WasmValidator::fail(T curr, S text) {
+std::ostream& WasmValidator::fail(S text, T curr) {
valid = false;
auto& ret = printFailureHeader() << text << ", on \n";
return printModuleComponent(curr, ret);