summaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2024-12-17 20:01:23 -0800
committerGitHub <noreply@github.com>2024-12-18 04:01:23 +0000
commit7c8cd2f4a51213964f6f1ec11e54d2b6e721cdaf (patch)
tree6440ab4fb4a1c572a5a82f3fcb9766fc8d505c5e /src/parser
parent9f5f8dd2ffe0b89ea071aea3d2b3efad42dada4f (diff)
downloadbinaryen-7c8cd2f4a51213964f6f1ec11e54d2b6e721cdaf.tar.gz
binaryen-7c8cd2f4a51213964f6f1ec11e54d2b6e721cdaf.tar.bz2
binaryen-7c8cd2f4a51213964f6f1ec11e54d2b6e721cdaf.zip
Support atomic struct accessors (#7155)
Implement support for both sequentially consistent and acquire-release variants of `struct.atomic.get` and `struct.atomic.set`, as proposed by shared-everything-threads. Introduce a new `MemoryOrdering` enum for describing different levels of atomicity (or the lack thereof). This new enum should eventually be adopted by linear memory atomic accessors as well to support acquire-release semantics, but for now just use it in `StructGet` and `StructSet`. In addition to implementing parsing and emitting for the instructions, validate that shared-everything is enabled to use them, mark them as having synchronization side effects, and lightly optimize them by relaxing acquire-release accesses to non-shared structs to normal, unordered accesses. This is valid because such accesses cannot possibly synchronize with other threads. Also update Precompute to avoid optimizing out synchronization points. There are probably other passes that need to be updated to avoid incorrectly optimizing synchronizing accesses, but identifying and fixing them is left as future work.
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/contexts.h25
-rw-r--r--src/parser/parsers.h46
2 files changed, 63 insertions, 8 deletions
diff --git a/src/parser/contexts.h b/src/parser/contexts.h
index 3e0bc7c40..a65299eac 100644
--- a/src/parser/contexts.h
+++ b/src/parser/contexts.h
@@ -735,13 +735,20 @@ struct NullInstrParserCtx {
return Ok{};
}
template<typename HeapTypeT>
- Result<> makeStructGet(
- Index, const std::vector<Annotation>&, HeapTypeT, FieldIdxT, bool) {
+ Result<> makeStructGet(Index,
+ const std::vector<Annotation>&,
+ HeapTypeT,
+ FieldIdxT,
+ bool,
+ MemoryOrder = MemoryOrder::Unordered) {
return Ok{};
}
template<typename HeapTypeT>
- Result<>
- makeStructSet(Index, const std::vector<Annotation>&, HeapTypeT, FieldIdxT) {
+ Result<> makeStructSet(Index,
+ const std::vector<Annotation>&,
+ HeapTypeT,
+ FieldIdxT,
+ MemoryOrder = MemoryOrder::Unordered) {
return Ok{};
}
template<typename HeapTypeT>
@@ -2448,15 +2455,17 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
const std::vector<Annotation>& annotations,
HeapType type,
Index field,
- bool signed_) {
- return withLoc(pos, irBuilder.makeStructGet(type, field, signed_));
+ bool signed_,
+ MemoryOrder order = MemoryOrder::Unordered) {
+ return withLoc(pos, irBuilder.makeStructGet(type, field, signed_, order));
}
Result<> makeStructSet(Index pos,
const std::vector<Annotation>& annotations,
HeapType type,
- Index field) {
- return withLoc(pos, irBuilder.makeStructSet(type, field));
+ Index field,
+ MemoryOrder order = MemoryOrder::Unordered) {
+ return withLoc(pos, irBuilder.makeStructSet(type, field, order));
}
Result<> makeArrayNew(Index pos,
diff --git a/src/parser/parsers.h b/src/parser/parsers.h
index 2d3321dcd..1f7236403 100644
--- a/src/parser/parsers.h
+++ b/src/parser/parsers.h
@@ -48,6 +48,7 @@ template<typename Ctx> Result<typename Ctx::LimitsT> limits64(Ctx&);
template<typename Ctx> Result<typename Ctx::MemTypeT> memtype(Ctx&);
template<typename Ctx>
Result<typename Ctx::MemTypeT> memtypeContinued(Ctx&, Type addressType);
+template<typename Ctx> Result<MemoryOrder> memorder(Ctx&);
template<typename Ctx> Result<typename Ctx::TableTypeT> tabletype(Ctx&);
template<typename Ctx>
Result<typename Ctx::TableTypeT> tabletypeContinued(Ctx&, Type addressType);
@@ -246,8 +247,15 @@ Result<> makeStructGet(Ctx&,
const std::vector<Annotation>&,
bool signed_ = false);
template<typename Ctx>
+Result<> makeAtomicStructGet(Ctx&,
+ Index,
+ const std::vector<Annotation>&,
+ bool signed_ = false);
+template<typename Ctx>
Result<> makeStructSet(Ctx&, Index, const std::vector<Annotation>&);
template<typename Ctx>
+Result<> makeAtomicStructSet(Ctx&, Index, const std::vector<Annotation>&);
+template<typename Ctx>
Result<>
makeArrayNew(Ctx&, Index, const std::vector<Annotation>&, bool default_);
template<typename Ctx>
@@ -801,6 +809,17 @@ Result<typename Ctx::MemTypeT> memtypeContinued(Ctx& ctx, Type addressType) {
return ctx.makeMemType(addressType, *limits, shared);
}
+// memorder ::= '' | 'seqcst' | 'acqrel'
+template<typename Ctx> Result<MemoryOrder> memorder(Ctx& ctx) {
+ if (ctx.in.takeKeyword("seqcst"sv)) {
+ return MemoryOrder::SeqCst;
+ }
+ if (ctx.in.takeKeyword("acqrel"sv)) {
+ return MemoryOrder::AcqRel;
+ }
+ return MemoryOrder::SeqCst;
+}
+
// tabletype ::= (limits32 | 'i32' limits32 | 'i64' limit64) reftype
template<typename Ctx> Result<typename Ctx::TableTypeT> tabletype(Ctx& ctx) {
Type addressType = Type::i32;
@@ -2225,6 +2244,20 @@ Result<> makeStructGet(Ctx& ctx,
}
template<typename Ctx>
+Result<> makeAtomicStructGet(Ctx& ctx,
+ Index pos,
+ const std::vector<Annotation>& annotations,
+ bool signed_) {
+ auto order = memorder(ctx);
+ CHECK_ERR(order);
+ auto type = typeidx(ctx);
+ CHECK_ERR(type);
+ auto field = fieldidx(ctx, *type);
+ CHECK_ERR(field);
+ return ctx.makeStructGet(pos, annotations, *type, *field, signed_, *order);
+}
+
+template<typename Ctx>
Result<>
makeStructSet(Ctx& ctx, Index pos, const std::vector<Annotation>& annotations) {
auto type = typeidx(ctx);
@@ -2235,6 +2268,19 @@ makeStructSet(Ctx& ctx, Index pos, const std::vector<Annotation>& annotations) {
}
template<typename Ctx>
+Result<> makeAtomicStructSet(Ctx& ctx,
+ Index pos,
+ const std::vector<Annotation>& annotations) {
+ auto order = memorder(ctx);
+ CHECK_ERR(order);
+ auto type = typeidx(ctx);
+ CHECK_ERR(type);
+ auto field = fieldidx(ctx, *type);
+ CHECK_ERR(field);
+ return ctx.makeStructSet(pos, annotations, *type, *field, *order);
+}
+
+template<typename Ctx>
Result<> makeArrayNew(Ctx& ctx,
Index pos,
const std::vector<Annotation>& annotations,