summaryrefslogtreecommitdiff
path: root/src/binary-reader-interpreter.cc
diff options
context:
space:
mode:
authorBen Smith <binjimin@gmail.com>2017-09-20 09:49:58 -0700
committerGitHub <noreply@github.com>2017-09-20 09:49:58 -0700
commit447e6f752b157d0a9951525a045d862e62d9b88c (patch)
tree2484ab5841f35fa50127f6dd83460f943a202fb6 /src/binary-reader-interpreter.cc
parentc71918746e06d2afffc46b3da5e3f2c024cc4b92 (diff)
downloadwabt-447e6f752b157d0a9951525a045d862e62d9b88c.tar.gz
wabt-447e6f752b157d0a9951525a045d862e62d9b88c.tar.bz2
wabt-447e6f752b157d0a9951525a045d862e62d9b88c.zip
Add Atomic instructions (#633)
This adds support for all atomic instructions, enabled via the `--enable-threads` flag. It supports all tools: parsing text, decoding binary, validation, and interpreting. It does not currently ensure that the memory is marked as shared; that flag is not supported in wabt yet.
Diffstat (limited to 'src/binary-reader-interpreter.cc')
-rw-r--r--src/binary-reader-interpreter.cc74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/binary-reader-interpreter.cc b/src/binary-reader-interpreter.cc
index 19969c4e..258ffc5f 100644
--- a/src/binary-reader-interpreter.cc
+++ b/src/binary-reader-interpreter.cc
@@ -136,6 +136,18 @@ class BinaryReaderInterpreter : public BinaryReaderNop {
wabt::Result OnLocalDeclCount(Index count) override;
wabt::Result OnLocalDecl(Index decl_index, Index count, Type type) override;
+ wabt::Result OnAtomicLoadExpr(Opcode opcode,
+ uint32_t alignment_log2,
+ Address offset) override;
+ wabt::Result OnAtomicStoreExpr(Opcode opcode,
+ uint32_t alignment_log2,
+ Address offset) override;
+ wabt::Result OnAtomicRmwExpr(Opcode opcode,
+ uint32_t alignment_log2,
+ Address offset) override;
+ wabt::Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
+ uint32_t alignment_log2,
+ Address offset) override;
wabt::Result OnBinaryExpr(wabt::Opcode opcode) override;
wabt::Result OnBlockExpr(Index num_types, Type* sig_types) override;
wabt::Result OnBrExpr(Index depth) override;
@@ -243,6 +255,8 @@ class BinaryReaderInterpreter : public BinaryReaderNop {
const Limits* actual_limits);
wabt::Result CheckHasMemory(wabt::Opcode opcode);
wabt::Result CheckAlign(uint32_t alignment_log2, Address natural_alignment);
+ wabt::Result CheckAtomicAlign(uint32_t alignment_log2,
+ Address natural_alignment);
wabt::Result AppendExport(Module* module,
ExternalKind kind,
@@ -1121,12 +1135,72 @@ wabt::Result BinaryReaderInterpreter::CheckAlign(uint32_t alignment_log2,
return wabt::Result::Ok;
}
+wabt::Result BinaryReaderInterpreter::CheckAtomicAlign(
+ uint32_t alignment_log2,
+ Address natural_alignment) {
+ if (alignment_log2 >= 32 || (1U << alignment_log2) != natural_alignment) {
+ PrintError("alignment must be equal to natural alignment (%u)",
+ natural_alignment);
+ return wabt::Result::Error;
+ }
+ return wabt::Result::Ok;
+}
+
wabt::Result BinaryReaderInterpreter::OnUnaryExpr(wabt::Opcode opcode) {
CHECK_RESULT(typechecker_.OnUnary(opcode));
CHECK_RESULT(EmitOpcode(opcode));
return wabt::Result::Ok;
}
+wabt::Result BinaryReaderInterpreter::OnAtomicLoadExpr(Opcode opcode,
+ uint32_t alignment_log2,
+ Address offset) {
+ CHECK_RESULT(CheckHasMemory(opcode));
+ CHECK_RESULT(CheckAtomicAlign(alignment_log2, opcode.GetMemorySize()));
+ CHECK_RESULT(typechecker_.OnAtomicLoad(opcode));
+ CHECK_RESULT(EmitOpcode(opcode));
+ CHECK_RESULT(EmitI32(module_->memory_index));
+ CHECK_RESULT(EmitI32(offset));
+ return wabt::Result::Ok;
+}
+
+wabt::Result BinaryReaderInterpreter::OnAtomicStoreExpr(Opcode opcode,
+ uint32_t alignment_log2,
+ Address offset) {
+ CHECK_RESULT(CheckHasMemory(opcode));
+ CHECK_RESULT(CheckAtomicAlign(alignment_log2, opcode.GetMemorySize()));
+ CHECK_RESULT(typechecker_.OnAtomicStore(opcode));
+ CHECK_RESULT(EmitOpcode(opcode));
+ CHECK_RESULT(EmitI32(module_->memory_index));
+ CHECK_RESULT(EmitI32(offset));
+ return wabt::Result::Ok;
+}
+
+wabt::Result BinaryReaderInterpreter::OnAtomicRmwExpr(Opcode opcode,
+ uint32_t alignment_log2,
+ Address offset) {
+ CHECK_RESULT(CheckHasMemory(opcode));
+ CHECK_RESULT(CheckAtomicAlign(alignment_log2, opcode.GetMemorySize()));
+ CHECK_RESULT(typechecker_.OnAtomicRmw(opcode));
+ CHECK_RESULT(EmitOpcode(opcode));
+ CHECK_RESULT(EmitI32(module_->memory_index));
+ CHECK_RESULT(EmitI32(offset));
+ return wabt::Result::Ok;
+}
+
+wabt::Result BinaryReaderInterpreter::OnAtomicRmwCmpxchgExpr(
+ Opcode opcode,
+ uint32_t alignment_log2,
+ Address offset) {
+ CHECK_RESULT(CheckHasMemory(opcode));
+ CHECK_RESULT(CheckAtomicAlign(alignment_log2, opcode.GetMemorySize()));
+ CHECK_RESULT(typechecker_.OnAtomicRmwCmpxchg(opcode));
+ CHECK_RESULT(EmitOpcode(opcode));
+ CHECK_RESULT(EmitI32(module_->memory_index));
+ CHECK_RESULT(EmitI32(offset));
+ return wabt::Result::Ok;
+}
+
wabt::Result BinaryReaderInterpreter::OnBinaryExpr(wabt::Opcode opcode) {
CHECK_RESULT(typechecker_.OnBinary(opcode));
CHECK_RESULT(EmitOpcode(opcode));