summaryrefslogtreecommitdiff
path: root/src/binary-writer.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-writer.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-writer.cc')
-rw-r--r--src/binary-writer.cc54
1 files changed, 37 insertions, 17 deletions
diff --git a/src/binary-writer.cc b/src/binary-writer.cc
index ed2b4f38..ad039677 100644
--- a/src/binary-writer.cc
+++ b/src/binary-writer.cc
@@ -123,6 +123,11 @@ class BinaryWriter {
void WriteU32Leb128WithReloc(Index index,
const char* desc,
RelocType reloc_type);
+ template <typename T>
+ void WriteLoadStoreExpr(const Module* module,
+ const Func* func,
+ const Expr* expr,
+ const char* desc);
void WriteExpr(const Module* module, const Func* func, const Expr* expr);
void WriteExprList(const Module* module,
const Func* func,
@@ -324,10 +329,35 @@ Index BinaryWriter::GetLocalIndex(const Func* func, const Var& var) {
}
}
+template <typename T>
+void BinaryWriter::WriteLoadStoreExpr(const Module* module,
+ const Func* func,
+ const Expr* expr,
+ const char* desc) {
+ auto* typed_expr = cast<T>(expr);
+ WriteOpcode(stream_, typed_expr->opcode);
+ Address align = typed_expr->opcode.GetAlignment(typed_expr->align);
+ stream_->WriteU8(log2_u32(align), "alignment");
+ WriteU32Leb128(stream_, typed_expr->offset, desc);
+}
+
void BinaryWriter::WriteExpr(const Module* module,
const Func* func,
const Expr* expr) {
switch (expr->type()) {
+ case ExprType::AtomicLoad:
+ WriteLoadStoreExpr<AtomicLoadExpr>(module, func, expr, "memory offset");
+ break;
+ case ExprType::AtomicRmw:
+ WriteLoadStoreExpr<AtomicRmwExpr>(module, func, expr, "memory offset");
+ break;
+ case ExprType::AtomicRmwCmpxchg:
+ WriteLoadStoreExpr<AtomicRmwCmpxchgExpr>(module, func, expr,
+ "memory offset");
+ break;
+ case ExprType::AtomicStore:
+ WriteLoadStoreExpr<AtomicStoreExpr>(module, func, expr, "memory offset");
+ break;
case ExprType::Binary:
WriteOpcode(stream_, cast<BinaryExpr>(expr)->opcode);
break;
@@ -348,7 +378,7 @@ void BinaryWriter::WriteExpr(const Module* module,
"break depth");
break;
case ExprType::BrTable: {
- auto br_table_expr = cast<BrTableExpr>(expr);
+ auto* br_table_expr = cast<BrTableExpr>(expr);
WriteOpcode(stream_, Opcode::BrTable);
WriteU32Leb128(stream_, br_table_expr->targets.size(), "num targets");
Index depth;
@@ -429,7 +459,7 @@ void BinaryWriter::WriteExpr(const Module* module,
WriteU32Leb128(stream_, 0, "grow_memory reserved");
break;
case ExprType::If: {
- auto if_expr = cast<IfExpr>(expr);
+ auto* if_expr = cast<IfExpr>(expr);
WriteOpcode(stream_, Opcode::If);
write_inline_signature_type(stream_, if_expr->true_.sig);
WriteExprList(module, func, if_expr->true_.exprs);
@@ -440,14 +470,9 @@ void BinaryWriter::WriteExpr(const Module* module,
WriteOpcode(stream_, Opcode::End);
break;
}
- case ExprType::Load: {
- auto load_expr = cast<LoadExpr>(expr);
- WriteOpcode(stream_, load_expr->opcode);
- Address align = load_expr->opcode.GetAlignment(load_expr->align);
- stream_->WriteU8(log2_u32(align), "alignment");
- WriteU32Leb128(stream_, load_expr->offset, "load offset");
+ case ExprType::Load:
+ WriteLoadStoreExpr<LoadExpr>(module, func, expr, "load offset");
break;
- }
case ExprType::Loop:
WriteOpcode(stream_, Opcode::Loop);
write_inline_signature_type(stream_, cast<LoopExpr>(expr)->block.sig);
@@ -480,14 +505,9 @@ void BinaryWriter::WriteExpr(const Module* module,
WriteU32Leb128(stream_, index, "local index");
break;
}
- case ExprType::Store: {
- auto store_expr = cast<StoreExpr>(expr);
- WriteOpcode(stream_, store_expr->opcode);
- Address align = store_expr->opcode.GetAlignment(store_expr->align);
- stream_->WriteU8(log2_u32(align), "alignment");
- WriteU32Leb128(stream_, store_expr->offset, "store offset");
+ case ExprType::Store:
+ WriteLoadStoreExpr<StoreExpr>(module, func, expr, "store offset");
break;
- }
case ExprType::TeeLocal: {
Index index = GetLocalIndex(func, cast<TeeLocalExpr>(expr)->var);
WriteOpcode(stream_, Opcode::TeeLocal);
@@ -500,7 +520,7 @@ void BinaryWriter::WriteExpr(const Module* module,
"throw exception");
break;
case ExprType::TryBlock: {
- auto try_expr = cast<TryExpr>(expr);
+ auto* try_expr = cast<TryExpr>(expr);
WriteOpcode(stream_, Opcode::Try);
write_inline_signature_type(stream_, try_expr->block.sig);
WriteExprList(module, func, try_expr->block.exprs);