diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 40 | ||||
-rw-r--r-- | src/wasm/wasm-ir-builder.cpp | 13 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 21 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 10 |
4 files changed, 75 insertions, 9 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 791dc53d7..b0c5a54ac 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1737,6 +1737,20 @@ void WasmBinaryWriter::writeField(const Field& field) { o << U32LEB(field.mutable_); } +void WasmBinaryWriter::writeMemoryOrder(MemoryOrder order) { + switch (order) { + case MemoryOrder::Unordered: + break; + case MemoryOrder::SeqCst: + o << uint8_t(BinaryConsts::OrderSeqCst); + return; + case MemoryOrder::AcqRel: + o << uint8_t(BinaryConsts::OrderAcqRel); + return; + } + WASM_UNREACHABLE("unexpected memory order"); +} + // reader WasmBinaryReader::WasmBinaryReader(Module& wasm, @@ -3406,6 +3420,21 @@ Result<> WasmBinaryReader::readInst() { return Err{"expected 0x00 byte immediate on atomic.fence"}; } return builder.makeAtomicFence(); + case BinaryConsts::StructAtomicGet: + case BinaryConsts::StructAtomicGetS: + case BinaryConsts::StructAtomicGetU: { + auto order = getMemoryOrder(); + auto type = getIndexedHeapType(); + auto field = getU32LEB(); + bool signed_ = op == BinaryConsts::StructAtomicGetS; + return builder.makeStructGet(type, field, signed_, order); + } + case BinaryConsts::StructAtomicSet: { + auto order = getMemoryOrder(); + auto type = getIndexedHeapType(); + auto field = getU32LEB(); + return builder.makeStructSet(type, field, order); + } } return Err{"unknown atomic operation"}; } @@ -4952,4 +4981,15 @@ std::tuple<Name, Address, Address> WasmBinaryReader::getMemarg() { return {getMemoryName(memIdx), alignment, offset}; } +MemoryOrder WasmBinaryReader::getMemoryOrder() { + auto code = getInt8(); + switch (code) { + case BinaryConsts::OrderSeqCst: + return MemoryOrder::SeqCst; + case BinaryConsts::OrderAcqRel: + return MemoryOrder::AcqRel; + } + throwError("Unrecognized memory order code " + std::to_string(code)); +} + } // namespace wasm diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp index 6cd62e439..4b0342410 100644 --- a/src/wasm/wasm-ir-builder.cpp +++ b/src/wasm/wasm-ir-builder.cpp @@ -1792,21 +1792,26 @@ Result<> IRBuilder::makeStructNewDefault(HeapType type) { return Ok{}; } -Result<> IRBuilder::makeStructGet(HeapType type, Index field, bool signed_) { +Result<> IRBuilder::makeStructGet(HeapType type, + Index field, + bool signed_, + MemoryOrder order) { const auto& fields = type.getStruct().fields; StructGet curr; CHECK_ERR(ChildPopper{*this}.visitStructGet(&curr, type)); CHECK_ERR(validateTypeAnnotation(type, curr.ref)); - push(builder.makeStructGet(field, curr.ref, fields[field].type, signed_)); + push( + builder.makeStructGet(field, curr.ref, fields[field].type, signed_, order)); return Ok{}; } -Result<> IRBuilder::makeStructSet(HeapType type, Index field) { +Result<> +IRBuilder::makeStructSet(HeapType type, Index field, MemoryOrder order) { StructSet curr; curr.index = field; CHECK_ERR(ChildPopper{*this}.visitStructSet(&curr, type)); CHECK_ERR(validateTypeAnnotation(type, curr.ref)); - push(builder.makeStructSet(field, curr.ref, curr.value)); + push(builder.makeStructSet(field, curr.ref, curr.value, order)); return Ok{}; } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 61f59c76a..08043b27f 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2327,15 +2327,20 @@ void BinaryInstWriter::visitStructGet(StructGet* curr) { } const auto& heapType = curr->ref->type.getHeapType(); const auto& field = heapType.getStruct().fields[curr->index]; + bool atomic = curr->order != MemoryOrder::Unordered; int8_t op; if (field.type != Type::i32 || field.packedType == Field::not_packed) { - op = BinaryConsts::StructGet; + op = atomic ? BinaryConsts::StructAtomicGet : BinaryConsts::StructGet; } else if (curr->signed_) { - op = BinaryConsts::StructGetS; + op = atomic ? BinaryConsts::StructAtomicGetS : BinaryConsts::StructGetS; } else { - op = BinaryConsts::StructGetU; + op = atomic ? BinaryConsts::StructAtomicGetU : BinaryConsts::StructGetU; + } + auto prefix = atomic ? BinaryConsts::AtomicPrefix : BinaryConsts::GCPrefix; + o << int8_t(prefix) << U32LEB(op); + if (atomic) { + parent.writeMemoryOrder(curr->order); } - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(op); parent.writeIndexedHeapType(heapType); o << U32LEB(curr->index); } @@ -2345,7 +2350,13 @@ void BinaryInstWriter::visitStructSet(StructSet* curr) { emitUnreachable(); return; } - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StructSet); + if (curr->order == MemoryOrder::Unordered) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StructSet); + } else { + o << int8_t(BinaryConsts::AtomicPrefix) + << U32LEB(BinaryConsts::StructAtomicSet); + parent.writeMemoryOrder(curr->order); + } parent.writeIndexedHeapType(curr->ref->type.getHeapType()); o << U32LEB(curr->index); } diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 242e07c43..7de69a1ff 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -2989,6 +2989,11 @@ void FunctionValidator::visitStructGet(StructGet* curr) { shouldBeTrue(getModule()->features.hasGC(), curr, "struct.get requires gc [--enable-gc]"); + shouldBeTrue(curr->order == MemoryOrder::Unordered || + getModule()->features.hasSharedEverything(), + curr, + "struct.atomic.get requires shared-everything " + "[--enable-shared-everything]"); if (curr->type == Type::unreachable || curr->ref->type.isNull()) { return; } @@ -3016,6 +3021,11 @@ void FunctionValidator::visitStructSet(StructSet* curr) { shouldBeTrue(getModule()->features.hasGC(), curr, "struct.set requires gc [--enable-gc]"); + shouldBeTrue(curr->order == MemoryOrder::Unordered || + getModule()->features.hasSharedEverything(), + curr, + "struct.atomic.set requires shared-everything " + "[--enable-shared-everything]"); if (curr->ref->type == Type::unreachable) { return; } |