@@ -220,22 +220,46 @@ void WasmValidator::visitSetLocal(SetLocal *curr) {
220220 }
221221}
222222void WasmValidator::visitLoad (Load *curr) {
223+ if (curr->isAtomic && !getModule ()->memory .shared ) fail (" Atomic operation with non-shared memory" , curr);
223224 validateMemBytes (curr->bytes , curr->type , curr);
224225 validateAlignment (curr->align , curr->type , curr->bytes , curr->isAtomic , curr);
225226 shouldBeEqualOrFirstIsUnreachable (curr->ptr ->type , i32 , curr, " load pointer type must be i32" );
226227}
227228void WasmValidator::visitStore (Store *curr) {
229+ if (curr->isAtomic && !getModule ()->memory .shared ) fail (" Atomic operation with non-shared memory" , curr);
228230 validateMemBytes (curr->bytes , curr->valueType , curr);
229231 validateAlignment (curr->align , curr->type , curr->bytes , curr->isAtomic , curr);
230232 shouldBeEqualOrFirstIsUnreachable (curr->ptr ->type , i32 , curr, " store pointer type must be i32" );
231233 shouldBeUnequal (curr->value ->type , none, curr, " store value type must not be none" );
232234 shouldBeEqualOrFirstIsUnreachable (curr->value ->type , curr->valueType , curr, " store value type must match" );
233235}
236+ void WasmValidator::shouldBeIntOrUnreachable (WasmType ty, Expression* curr, const char * text) {
237+ switch (ty) {
238+ case i32 :
239+ case i64 :
240+ case unreachable: {
241+ break ;
242+ }
243+ default : fail (text, curr);
244+ }
245+ }
234246void WasmValidator::visitAtomicRMW (AtomicRMW* curr) {
247+ if (!getModule ()->memory .shared ) fail (" Atomic operation with non-shared memory" , curr);
235248 validateMemBytes (curr->bytes , curr->type , curr);
249+ shouldBeEqualOrFirstIsUnreachable (curr->ptr ->type , i32 , curr, " AtomicRMW pointer type must be i32" );
250+ shouldBeEqualOrFirstIsUnreachable (curr->value ->type , curr->type , curr, " AtomicRMW result type must match operand" );
251+ shouldBeIntOrUnreachable (curr->type , curr, " Atomic operations are only valid on int types" );
236252}
237253void WasmValidator::visitAtomicCmpxchg (AtomicCmpxchg* curr) {
254+ if (!getModule ()->memory .shared ) fail (" Atomic operation with non-shared memory" , curr);
238255 validateMemBytes (curr->bytes , curr->type , curr);
256+ shouldBeEqualOrFirstIsUnreachable (curr->ptr ->type , i32 , curr, " cmpxchg pointer type must be i32" );
257+ if (curr->expected ->type != unreachable && curr->replacement ->type != unreachable) {
258+ shouldBeEqual (curr->expected ->type , curr->replacement ->type , curr, " cmpxchg operand types must match" );
259+ }
260+ shouldBeEqualOrFirstIsUnreachable (curr->expected ->type , curr->type , curr, " Cmpxchg result type must match expected" );
261+ shouldBeEqualOrFirstIsUnreachable (curr->replacement ->type , curr->type , curr, " Cmpxchg result type must match replacement" );
262+ shouldBeIntOrUnreachable (curr->expected ->type , curr, " Atomic operations are only valid on int types" );
239263}
240264void WasmValidator::validateMemBytes (uint8_t bytes, WasmType ty, Expression* curr) {
241265 switch (bytes) {
@@ -655,7 +679,7 @@ void WasmValidator::validateBinaryenIR(Module& wasm) {
655679}
656680
657681template <typename T, typename S>
658- std::ostream& WasmValidator::fail (T curr, S text ) {
682+ std::ostream& WasmValidator::fail (S text, T curr ) {
659683 valid = false ;
660684 auto & ret = printFailureHeader () << text << " , on \n " ;
661685 return printModuleComponent (curr, ret);
0 commit comments