Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions scripts/gen-s-parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@
# atomic instructions
("memory.atomic.notify", "makeAtomicNotify()"),
("struct.wait", "makeStructWait()"),
("struct.notify", "makeStructNotify()"),
("memory.atomic.wait32", "makeAtomicWait(Type::i32)"),
("memory.atomic.wait64", "makeAtomicWait(Type::i64)"),
("atomic.fence", "makeAtomicFence()"),
Expand Down
61 changes: 36 additions & 25 deletions src/gen-s-parser.inc
Original file line number Diff line number Diff line change
Expand Up @@ -5356,41 +5356,52 @@ switch (buf[0]) {
}
}
case 'n': {
switch (buf[10]) {
case '\0':
if (op == "struct.new"sv) {
CHECK_ERR(makeStructNew(ctx, pos, annotations, false, false));
return Ok{};
}
goto parse_error;
case '_': {
switch (buf[13]) {
case 'f': {
switch (buf[18]) {
case '\0':
if (op == "struct.new_default"sv) {
CHECK_ERR(makeStructNew(ctx, pos, annotations, true, false));
return Ok{};
switch (buf[8]) {
case 'e': {
switch (buf[10]) {
case '\0':
if (op == "struct.new"sv) {
CHECK_ERR(makeStructNew(ctx, pos, annotations, false, false));
return Ok{};
}
goto parse_error;
case '_': {
switch (buf[13]) {
case 'f': {
switch (buf[18]) {
case '\0':
if (op == "struct.new_default"sv) {
CHECK_ERR(makeStructNew(ctx, pos, annotations, true, false));
return Ok{};
}
goto parse_error;
case '_':
if (op == "struct.new_default_desc"sv) {
CHECK_ERR(makeStructNew(ctx, pos, annotations, true, true));
return Ok{};
}
goto parse_error;
default: goto parse_error;
}
goto parse_error;
case '_':
if (op == "struct.new_default_desc"sv) {
CHECK_ERR(makeStructNew(ctx, pos, annotations, true, true));
}
case 's':
if (op == "struct.new_desc"sv) {
CHECK_ERR(makeStructNew(ctx, pos, annotations, false, true));
return Ok{};
}
goto parse_error;
default: goto parse_error;
}
}
case 's':
if (op == "struct.new_desc"sv) {
CHECK_ERR(makeStructNew(ctx, pos, annotations, false, true));
return Ok{};
}
goto parse_error;
default: goto parse_error;
}
}
case 'o':
if (op == "struct.notify"sv) {
CHECK_ERR(makeStructNotify(ctx, pos, annotations));
return Ok{};
}
goto parse_error;
default: goto parse_error;
}
}
Expand Down
1 change: 1 addition & 0 deletions src/interpreter/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ struct ExpressionInterpreter : OverriddenVisitor<ExpressionInterpreter, Flow> {
Flow visitStructRMW(StructRMW* curr) { WASM_UNREACHABLE("TODO"); }
Flow visitStructCmpxchg(StructCmpxchg* curr) { WASM_UNREACHABLE("TODO"); }
Flow visitStructWait(StructWait* curr) { WASM_UNREACHABLE("TODO"); }
Flow visitStructNotify(StructNotify* curr) { WASM_UNREACHABLE("TODO"); }
Flow visitArrayNew(ArrayNew* curr) { WASM_UNREACHABLE("TODO"); }
Flow visitArrayNewData(ArrayNewData* curr) { WASM_UNREACHABLE("TODO"); }
Flow visitArrayNewElem(ArrayNewElem* curr) { WASM_UNREACHABLE("TODO"); }
Expand Down
1 change: 1 addition & 0 deletions src/ir/ReFinalize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ void ReFinalize::visitStructSet(StructSet* curr) { curr->finalize(); }
void ReFinalize::visitStructRMW(StructRMW* curr) { curr->finalize(); }
void ReFinalize::visitStructCmpxchg(StructCmpxchg* curr) { curr->finalize(); }
void ReFinalize::visitStructWait(StructWait* curr) { curr->finalize(); }
void ReFinalize::visitStructNotify(StructNotify* curr) { curr->finalize(); }
void ReFinalize::visitArrayNew(ArrayNew* curr) { curr->finalize(); }
void ReFinalize::visitArrayNewData(ArrayNewData* curr) { curr->finalize(); }
void ReFinalize::visitArrayNewElem(ArrayNewElem* curr) { curr->finalize(); }
Expand Down
14 changes: 14 additions & 0 deletions src/ir/child-typer.h
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,20 @@ template<typename Subtype> struct ChildTyper : OverriddenVisitor<Subtype> {
note(&curr->timeout, Type(Type::BasicType::i64));
}

void visitStructNotify(StructNotify* curr,
std::optional<HeapType> ht = std::nullopt) {
if (!ht) {
if (!curr->ref->type.isStruct()) {
self().noteUnknown();
return;
}
ht = curr->ref->type.getHeapType();
}

note(&curr->ref, Type(*ht, Nullable));
note(&curr->count, Type(Type::BasicType::i32));
}

void visitArrayNew(ArrayNew* curr) {
if (!curr->isWithDefault()) {
if (!curr->type.isRef()) {
Expand Down
4 changes: 4 additions & 0 deletions src/ir/cost.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> {
return AtomicCost + nullCheckCost(curr->ref) + visit(curr->ref) +
visit(curr->expected) + visit(curr->timeout);
}
CostType visitStructNotify(StructNotify* curr) {
return AtomicCost + nullCheckCost(curr->ref) + visit(curr->ref) +
visit(curr->count);
}
CostType visitAtomicNotify(AtomicNotify* curr) {
return AtomicCost + visit(curr->ptr) + visit(curr->notifyCount);
}
Expand Down
11 changes: 11 additions & 0 deletions src/ir/effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,17 @@ class EffectAnalyzer {
.fields.at(curr->index)
.mutable_ == Mutable;
}
void visitStructNotify(StructNotify* curr) {
parent.isAtomic = true;

// If the ref is null.
parent.implicitTrap = true;

// struct.notify mutates an opaque waiter queue which isn't visible in
// user code. Model this as a struct write which prevents reorderings
// (since isAtomic == true).
parent.writesStruct = true;
}
void visitArrayNew(ArrayNew* curr) {}
void visitArrayNewData(ArrayNewData* curr) {
// Traps on out of bounds access to segments or access to dropped
Expand Down
1 change: 1 addition & 0 deletions src/ir/module-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ struct CodeScanner : PostWalker<CodeScanner> {
void visitStructGet(StructGet* curr) { info.note(curr->ref->type); }
void visitStructSet(StructSet* curr) { info.note(curr->ref->type); }
void visitStructWait(StructWait* curr) { info.note(curr->ref->type); }
void visitStructNotify(StructNotify* curr) { info.note(curr->ref->type); }
void visitArrayGet(ArrayGet* curr) { info.note(curr->ref->type); }
void visitArraySet(ArraySet* curr) { info.note(curr->ref->type); }
void visitContBind(ContBind* curr) {
Expand Down
1 change: 1 addition & 0 deletions src/ir/possible-contents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1086,6 +1086,7 @@ struct InfoCollector
addRoot(curr);
}
void visitStructWait(StructWait* curr) { addRoot(curr); }
void visitStructNotify(StructNotify* curr) { addRoot(curr); }
// Array operations access the array's location, parallel to how structs work.
void visitArrayGet(ArrayGet* curr) {
if (!isRelevant(curr->ref)) {
Expand Down
1 change: 1 addition & 0 deletions src/ir/subtype-exprs.h
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
self()->noteSubtype(curr->replacement, type);
}
void visitStructWait(StructWait* curr) {}
void visitStructNotify(StructNotify* curr) {}
void visitArrayNew(ArrayNew* curr) {
if (!curr->type.isArray() || curr->isWithDefault()) {
return;
Expand Down
14 changes: 14 additions & 0 deletions src/parser/contexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,13 @@ struct NullInstrParserCtx {
return Ok{};
}
template<typename HeapTypeT>
Result<> makeStructNotify(Index,
const std::vector<Annotation>&,
HeapTypeT,
FieldIdxT) {
return Ok{};
}
template<typename HeapTypeT>
Result<> makeArrayNew(Index, const std::vector<Annotation>&, HeapTypeT) {
return Ok{};
}
Expand Down Expand Up @@ -2724,6 +2731,13 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx>, AnnotationParserCtx {
return withLoc(pos, irBuilder.makeStructWait(type, field));
}

Result<> makeStructNotify(Index pos,
const std::vector<Annotation>& annotations,
HeapType type,
Index field) {
return withLoc(pos, irBuilder.makeStructNotify(type, field));
}

Result<> makeArrayNew(Index pos,
const std::vector<Annotation>& annotations,
HeapType type) {
Expand Down
11 changes: 11 additions & 0 deletions src/parser/parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -2493,6 +2493,17 @@ Result<> makeStructWait(Ctx& ctx,
return ctx.makeStructWait(pos, annotations, *type, *field);
}

template<typename Ctx>
Result<> makeStructNotify(Ctx& ctx,
Index pos,
const std::vector<Annotation>& annotations) {
auto type = typeidx(ctx);
CHECK_ERR(type);
auto field = fieldidx(ctx, *type);
CHECK_ERR(field);
return ctx.makeStructNotify(pos, annotations, *type, *field);
}

template<typename Ctx>
Result<> makeArrayNew(Ctx& ctx,
Index pos,
Expand Down
7 changes: 7 additions & 0 deletions src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2412,6 +2412,13 @@ struct PrintExpressionContents
o << ' ';
o << curr->index;
}
void visitStructNotify(StructNotify* curr) {
printMedium(o, "struct.notify");
o << ' ';
printHeapTypeName(curr->ref->type.getHeapType());
o << ' ';
o << curr->index;
}
void visitArrayNew(ArrayNew* curr) {
printMedium(o, "array.new");
if (curr->isWithDefault()) {
Expand Down
2 changes: 2 additions & 0 deletions src/passes/TypeGeneralizing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,8 @@ struct TransferFn : OverriddenVisitor<TransferFn> {

void visitStructWait(StructWait* curr) { WASM_UNREACHABLE("TODO"); }

void visitStructNotify(StructNotify* curr) { WASM_UNREACHABLE("TODO"); }

void visitArrayNew(ArrayNew* curr) {
// We cannot yet generalize allocations. Push a requirement for the
// reference type needed to initialize the array, if any.
Expand Down
1 change: 1 addition & 0 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,7 @@ enum ASTNodes {
AtomicFence = 0x03,
Pause = 0x04,
StructWait = 0x05,
StructNotify = 0x06,

I32AtomicLoad = 0x10,
I64AtomicLoad = 0x11,
Expand Down
10 changes: 10 additions & 0 deletions src/wasm-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1376,6 +1376,16 @@ class Builder {
return ret;
}

StructNotify*
makeStructNotify(Index index, Expression* ref, Expression* count) {
auto* ret = wasm.allocator.alloc<StructNotify>();
ret->index = index;
ret->ref = ref;
ret->count = count;
ret->finalize();
return ret;
}

// Additional helpers

Drop* makeDrop(Expression* value) {
Expand Down
6 changes: 6 additions & 0 deletions src/wasm-delegations-fields.def
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,12 @@ DELEGATE_FIELD_IMMEDIATE_TYPED_CHILD(StructWait, ref)
DELEGATE_FIELD_INT(StructWait, index)
DELEGATE_FIELD_CASE_END(StructWait)

DELEGATE_FIELD_CASE_START(StructNotify)
DELEGATE_FIELD_CHILD(StructNotify, count)
DELEGATE_FIELD_IMMEDIATE_TYPED_CHILD(StructNotify, ref)
DELEGATE_FIELD_INT(StructNotify, index)
DELEGATE_FIELD_CASE_END(StructNotify)


DELEGATE_FIELD_MAIN_END

Expand Down
1 change: 1 addition & 0 deletions src/wasm-delegations.def
Original file line number Diff line number Diff line change
Expand Up @@ -116,5 +116,6 @@ DELEGATE(Resume);
DELEGATE(ResumeThrow);
DELEGATE(StackSwitch);
DELEGATE(StructWait);
DELEGATE(StructNotify);

#undef DELEGATE
6 changes: 6 additions & 0 deletions src/wasm-interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -2248,6 +2248,11 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
return Flow();
}

Flow visitStructNotify(StructNotify* curr) {
WASM_UNREACHABLE("struct.notify not implemented");
return Flow();
}

// Arbitrary deterministic limit on size. If we need to allocate a Literals
// vector that takes around 1-2GB of memory then we are likely to hit memory
// limits on 32-bit machines, and in particular on wasm32 VMs that do not
Expand Down Expand Up @@ -2911,6 +2916,7 @@ class ConstantExpressionRunner : public ExpressionRunner<SubType> {
Flow visitAtomicWait(AtomicWait* curr) { return Flow(NONCONSTANT_FLOW); }
Flow visitAtomicNotify(AtomicNotify* curr) { return Flow(NONCONSTANT_FLOW); }
Flow visitStructWait(StructWait* curr) { return Flow(NONCONSTANT_FLOW); }
Flow visitStructNotify(StructNotify* curr) { return Flow(NONCONSTANT_FLOW); }
Flow visitSIMDLoad(SIMDLoad* curr) { return Flow(NONCONSTANT_FLOW); }
Flow visitSIMDLoadSplat(SIMDLoad* curr) { return Flow(NONCONSTANT_FLOW); }
Flow visitSIMDLoadExtend(SIMDLoad* curr) { return Flow(NONCONSTANT_FLOW); }
Expand Down
1 change: 1 addition & 0 deletions src/wasm-ir-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
makeStructRMW(AtomicRMWOp op, HeapType type, Index field, MemoryOrder order);
Result<> makeStructCmpxchg(HeapType type, Index field, MemoryOrder order);
Result<> makeStructWait(HeapType type, Index index);
Result<> makeStructNotify(HeapType type, Index index);
Result<> makeArrayNew(HeapType type);
Result<> makeArrayNewDefault(HeapType type);
Result<> makeArrayNewData(HeapType type, Name data);
Expand Down
13 changes: 13 additions & 0 deletions src/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,7 @@ class Expression {
ResumeThrowId,
StackSwitchId,
StructWaitId,
StructNotifyId,
NumExpressionIds
};
Id _id;
Expand Down Expand Up @@ -1771,6 +1772,18 @@ class StructWait : public SpecificExpression<Expression::StructWaitId> {
void finalize();
};

class StructNotify : public SpecificExpression<Expression::StructNotifyId> {
public:
StructNotify() = default;
StructNotify(MixedArena& allocator) : StructNotify() {}

Expression* ref;
Expression* count;
Index index;

void finalize();
};

class ArrayNew : public SpecificExpression<Expression::ArrayNewId> {
public:
ArrayNew() = default;
Expand Down
5 changes: 5 additions & 0 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3922,6 +3922,11 @@ Result<> WasmBinaryReader::readInst() {
auto index = getU32LEB();
return builder.makeStructWait(structType, index);
}
case BinaryConsts::StructNotify: {
auto structType = getIndexedHeapType();
auto index = getU32LEB();
return builder.makeStructNotify(structType, index);
}
}
return Err{"unknown atomic operation " + std::to_string(op)};
}
Expand Down
Loading
Loading