Skip to content
Draft
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
2 changes: 2 additions & 0 deletions scripts/gen-s-parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@
("i64.extend32_s", "makeUnary(UnaryOp::ExtendS32Int64)"),
# atomic instructions
("memory.atomic.notify", "makeAtomicNotify()"),
("waitqueue.wait", "makeWaitQueueWait()"),
("waitqueue.notify", "makeWaitQueueNotify()"),
("memory.atomic.wait32", "makeAtomicWait(Type::i32)"),
("memory.atomic.wait64", "makeAtomicWait(Type::i64)"),
("atomic.fence", "makeAtomicFence()"),
Expand Down
17 changes: 17 additions & 0 deletions src/gen-s-parser.inc
Original file line number Diff line number Diff line change
Expand Up @@ -5784,6 +5784,23 @@ switch (buf[0]) {
default: goto parse_error;
}
}
case 'w': {
switch (buf[10]) {
case 'n':
if (op == "waitqueue.notify"sv) {
CHECK_ERR(makeWaitQueueNotify(ctx, pos, annotations));
return Ok{};
}
goto parse_error;
case 'w':
if (op == "waitqueue.wait"sv) {
CHECK_ERR(makeWaitQueueWait(ctx, pos, annotations));
return Ok{};
}
goto parse_error;
default: goto parse_error;
}
}
default: goto parse_error;
}
parse_error:
Expand Down
2 changes: 2 additions & 0 deletions src/interpreter/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ struct ExpressionInterpreter : OverriddenVisitor<ExpressionInterpreter, Flow> {
Flow visitResume(Resume* curr) { WASM_UNREACHABLE("TODO"); }
Flow visitResumeThrow(ResumeThrow* curr) { WASM_UNREACHABLE("TODO"); }
Flow visitStackSwitch(StackSwitch* curr) { WASM_UNREACHABLE("TODO"); }
Flow visitWaitQueueWait(WaitQueueWait* curr) { WASM_UNREACHABLE("TODO"); }
Flow visitWaitQueueNotify(WaitQueueNotify* curr) { WASM_UNREACHABLE("TODO"); }
};

} // anonymous namespace
Expand Down
4 changes: 4 additions & 0 deletions src/ir/ReFinalize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,10 @@ void ReFinalize::visitResumeThrow(ResumeThrow* curr) {
}
}
void ReFinalize::visitStackSwitch(StackSwitch* curr) { curr->finalize(); }
void ReFinalize::visitWaitQueueWait(WaitQueueWait* curr) { curr->finalize(); }
void ReFinalize::visitWaitQueueNotify(WaitQueueNotify* curr) {
curr->finalize();
}

void ReFinalize::visitExport(Export* curr) { WASM_UNREACHABLE("unimp"); }
void ReFinalize::visitGlobal(Global* curr) { WASM_UNREACHABLE("unimp"); }
Expand Down
17 changes: 17 additions & 0 deletions src/ir/child-typer.h
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,23 @@ template<typename Subtype> struct ChildTyper : OverriddenVisitor<Subtype> {
}
note(&curr->cont, Type(*ct, Nullable));
}

void visitWaitQueueWait(WaitQueueWait* curr) {
note(&curr->waitqueue,
Type(HeapType(Struct(std::vector{
Field(Field::PackedType::WaitQueue, Mutability::Immutable)})),
NonNullable));
note(&curr->value, Type(Type::BasicType::i32));
note(&curr->timeout, Type(Type::BasicType::i64));
}

void visitWaitQueueNotify(WaitQueueNotify* curr) {
note(&curr->waitqueue,
Type(HeapType(Struct(std::vector{
Field(Field::PackedType::WaitQueue, Mutability::Immutable)})),
NonNullable));
note(&curr->count, Type(Type::BasicType::i32));
}
};

} // namespace wasm
Expand Down
7 changes: 7 additions & 0 deletions src/ir/cost.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> {
return AtomicCost + visit(curr->ptr) + visit(curr->expected) +
visit(curr->timeout);
}
CostType visitWaitQueueWait(WaitQueueWait* curr) {
return AtomicCost + visit(curr->waitqueue) + visit(curr->value) +
visit(curr->timeout);
}
CostType visitWaitQueueNotify(WaitQueueNotify* curr) {
return AtomicCost + visit(curr->waitqueue) + visit(curr->count);
}
CostType visitAtomicNotify(AtomicNotify* curr) {
return AtomicCost + visit(curr->ptr) + visit(curr->notifyCount);
}
Expand Down
25 changes: 25 additions & 0 deletions src/ir/effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,31 @@ class EffectAnalyzer {
parent.throws_ = true;
}
}

void visitWaitQueueWait(WaitQueueWait* curr) {
parent.isAtomic = true;
parent.mayNotReturn = true;

// field 0 must exist and be a packed waitqueue if this is valid Wasm.
if (curr->waitqueue->type.getHeapType()
.getStruct()
.fields.at(0)
.mutable_ == Mutable) {
parent.readsMutableStruct = true;
}
}

void visitWaitQueueNotify(WaitQueueNotify* curr) {
parent.isAtomic = true;

// field 0 must exist and be a packed waitqueue if this is valid Wasm.
if (curr->waitqueue->type.getHeapType()
.getStruct()
.fields.at(0)
.mutable_ == Mutable) {
parent.readsMutableStruct = true;
}
}
};

public:
Expand Down
6 changes: 6 additions & 0 deletions src/ir/module-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,12 @@ struct CodeScanner : PostWalker<CodeScanner> {
info.note(curr->cont->type);
info.note(curr->type);
}
void visitWaitQueueWait(WaitQueueWait* curr) {
info.note(curr->waitqueue->type);
}
void visitWaitQueueNotify(WaitQueueNotify* curr) {
info.note(curr->waitqueue->type);
}
void visitBlock(Block* curr) {
info.noteControlFlow(Signature(Type::none, curr->type));
}
Expand Down
2 changes: 2 additions & 0 deletions src/ir/possible-contents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1401,6 +1401,8 @@ struct InfoCollector
// TODO: optimize when possible
addRoot(curr);
}
void visitWaitQueueWait(WaitQueueWait* curr) { addRoot(curr); }
void visitWaitQueueNotify(WaitQueueNotify* curr) { addRoot(curr); }

void visitFunction(Function* func) {
// Functions with a result can flow a value out from their body.
Expand Down
12 changes: 12 additions & 0 deletions src/ir/subtype-exprs.h
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,18 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
.type.getSignature();
self()->noteSubtype(currResult, retSig.results);
}
void visitWaitQueueWait(WaitQueueWait* curr) {
self()->noteSubtype(curr->waitqueue,
Type(HeapType(Struct(std::vector{Field(
Field::PackedType::WaitQueue, Immutable)})),
NonNullable));
}
void visitWaitQueueNotify(WaitQueueNotify* curr) {
self()->noteSubtype(curr->waitqueue,
Type(HeapType(Struct(std::vector{Field(
Field::PackedType::WaitQueue, Immutable)})),
NonNullable));
}
};

} // namespace wasm
Expand Down
17 changes: 17 additions & 0 deletions src/parser/contexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,13 @@ struct NullInstrParserCtx {
makeStackSwitch(Index, const std::vector<Annotation>&, HeapTypeT, TagIdxT) {
return Ok{};
}

Result<> makeWaitQueueWait(Index, const std::vector<Annotation>&) {
return Ok{};
}
Result<> makeWaitQueueNotify(Index, const std::vector<Annotation>&) {
return Ok{};
}
};

struct NullCtx : NullTypeParserCtx, NullInstrParserCtx {
Expand Down Expand Up @@ -2947,6 +2954,16 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx>, AnnotationParserCtx {
Name tag) {
return withLoc(pos, irBuilder.makeStackSwitch(type, tag));
}

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

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

} // namespace wasm::WATParser
Expand Down
14 changes: 14 additions & 0 deletions src/parser/parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -2840,6 +2840,20 @@ Result<> makeStackSwitch(Ctx& ctx,
return ctx.makeStackSwitch(pos, annotations, *type, *tag);
}

template<typename Ctx>
Result<> makeWaitQueueWait(Ctx& ctx,
Index pos,
const std::vector<Annotation>& annotations) {
return ctx.makeWaitQueueWait(pos, annotations);
}

template<typename Ctx>
Result<> makeWaitQueueNotify(Ctx& ctx,
Index pos,
const std::vector<Annotation>& annotations) {
return ctx.makeWaitQueueNotify(pos, annotations);
}

// =======
// Modules
// =======
Expand Down
18 changes: 18 additions & 0 deletions src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,16 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
visitExpression(curr);
}
}
void visitWaitQueueWait(WaitQueueWait* curr) {
if (!maybePrintUnreachableReplacement(curr, curr->type)) {
visitExpression(curr);
}
}
void visitWaitQueueNotify(WaitQueueNotify* curr) {
if (!maybePrintUnreachableReplacement(curr, curr->type)) {
visitExpression(curr);
}
}

// Module-level visitors
void handleSignature(Function* curr, bool printImplicitNames = false);
Expand Down Expand Up @@ -2658,6 +2668,14 @@ struct PrintExpressionContents
o << ' ';
curr->tag.print(o);
}

void visitWaitQueueWait(WaitQueueWait* curr) {
printMedium(o, "waitqueue.wait");
}

void visitWaitQueueNotify(WaitQueueNotify* curr) {
printMedium(o, "waitqueue.notify");
}
};

void PrintSExpression::setModule(Module* module) {
Expand Down
2 changes: 2 additions & 0 deletions src/passes/TypeGeneralizing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,8 @@ struct TransferFn : OverriddenVisitor<TransferFn> {
void visitResume(Resume* curr) { WASM_UNREACHABLE("TODO"); }
void visitResumeThrow(ResumeThrow* curr) { WASM_UNREACHABLE("TODO"); }
void visitStackSwitch(StackSwitch* curr) { WASM_UNREACHABLE("TODO"); }
void visitWaitQueueWait(WaitQueueWait* curr) { WASM_UNREACHABLE("TODO"); }
void visitWaitQueueNotify(WaitQueueNotify* curr) { WASM_UNREACHABLE("TODO"); }
};

struct TypeGeneralizing : WalkerPass<PostWalker<TypeGeneralizing>> {
Expand Down
9 changes: 6 additions & 3 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,8 @@ enum ASTNodes {
I64AtomicWait = 0x02,
AtomicFence = 0x03,
Pause = 0x04,
WaitQueueWait = 0x05,
WaitQueueNotify = 0x06,

I32AtomicLoad = 0x10,
I64AtomicLoad = 0x11,
Expand Down Expand Up @@ -1252,9 +1254,10 @@ enum ASTNodes {
Resume = 0xe3,
ResumeThrow = 0xe4,
ResumeThrowRef = 0xe5,
Switch = 0xe6, // NOTE(dhil): the internal class is known as
// StackSwitch to avoid conflict with the existing
// 'switch table'.
Switch = 0xe6, // NOTE(dhil): the internal class is known as
// StackSwitch to avoid conflict with the existing
// 'switch table'.

OnLabel = 0x00, // (on $tag $label)
OnSwitch = 0x01 // (on $tag switch)
};
Expand Down
20 changes: 20 additions & 0 deletions src/wasm-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1363,6 +1363,26 @@ class Builder {
return ret;
}

WaitQueueWait* makeWaitQueueWait(Expression* waitqueue,
Expression* value,
Expression* timeout) {
auto* ret = wasm.allocator.alloc<WaitQueueWait>();
ret->waitqueue = waitqueue;
ret->value = value;
ret->timeout = timeout;
ret->finalize();
return ret;
}

WaitQueueNotify* makeWaitQueueNotify(Expression* waitqueue,
Expression* count) {
auto* ret = wasm.allocator.alloc<WaitQueueNotify>();
ret->waitqueue = waitqueue;
ret->count = count;
ret->finalize();
return ret;
}

// Additional helpers

Drop* makeDrop(Expression* value) {
Expand Down
11 changes: 11 additions & 0 deletions src/wasm-delegations-fields.def
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,17 @@ DELEGATE_FIELD_CHILD_VECTOR(StackSwitch, operands)
DELEGATE_FIELD_NAME_KIND(StackSwitch, tag, ModuleItemKind::Tag)
DELEGATE_FIELD_CASE_END(StackSwitch)

DELEGATE_FIELD_CASE_START(WaitQueueWait)
DELEGATE_FIELD_CHILD(WaitQueueWait, timeout)
DELEGATE_FIELD_CHILD(WaitQueueWait, value)
DELEGATE_FIELD_CHILD(WaitQueueWait, waitqueue)
DELEGATE_FIELD_CASE_END(WaitQueueWait)

DELEGATE_FIELD_CASE_START(WaitQueueNotify)
DELEGATE_FIELD_CHILD(WaitQueueNotify, count)
DELEGATE_FIELD_CHILD(WaitQueueNotify, waitqueue)
DELEGATE_FIELD_CASE_END(WaitQueueNotify)


DELEGATE_FIELD_MAIN_END

Expand Down
2 changes: 2 additions & 0 deletions src/wasm-delegations.def
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,7 @@ DELEGATE(Suspend);
DELEGATE(Resume);
DELEGATE(ResumeThrow);
DELEGATE(StackSwitch);
DELEGATE(WaitQueueWait);
DELEGATE(WaitQueueNotify);

#undef DELEGATE
12 changes: 12 additions & 0 deletions src/wasm-interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -2932,6 +2932,12 @@ class ConstantExpressionRunner : public ExpressionRunner<SubType> {
Flow visitResume(Resume* curr) { return Flow(NONCONSTANT_FLOW); }
Flow visitResumeThrow(ResumeThrow* curr) { return Flow(NONCONSTANT_FLOW); }
Flow visitStackSwitch(StackSwitch* curr) { return Flow(NONCONSTANT_FLOW); }
Flow visitWaitQueueWait(WaitQueueWait* curr) {
return Flow(NONCONSTANT_FLOW);
}
Flow visitWaitQueueNotify(WaitQueueNotify* curr) {
return Flow(NONCONSTANT_FLOW);
}

void trap(std::string_view why) override { throw NonconstantException(); }

Expand Down Expand Up @@ -4918,6 +4924,12 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
Flow visitResume(Resume* curr) { return doResume(curr); }
Flow visitResumeThrow(ResumeThrow* curr) { return doResume(curr); }
Flow visitStackSwitch(StackSwitch* curr) { return Flow(NONCONSTANT_FLOW); }
Flow visitWaitQueueWait(WaitQueueWait* curr) {
WASM_UNREACHABLE("waitqueue not implemented");
}
Flow visitWaitQueueNotify(WaitQueueNotify* curr) {
WASM_UNREACHABLE("waitqueue not implemented");
}

void trap(std::string_view why) override {
// Traps break all current continuations - they will never be resumable.
Expand Down
2 changes: 2 additions & 0 deletions src/wasm-ir-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
return makeResumeThrow(ct, Name(), tags, labels);
}
Result<> makeStackSwitch(HeapType ct, Name tag);
Result<> makeWaitQueueWait();
Result<> makeWaitQueueNotify();

// Private functions that must be public for technical reasons.
Result<> visitExpression(Expression*);
Expand Down
Loading
Loading