Skip to content
Open
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
34 changes: 22 additions & 12 deletions src/ir/subtype-exprs.h
Original file line number Diff line number Diff line change
Expand Up @@ -494,32 +494,42 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
curr->type.getHeapType().getContinuation().type);
}
void visitContBind(ContBind* curr) {
if (!curr->cont->type.isContinuation()) {
if (!curr->cont->type.isContinuation() || !curr->type.isContinuation()) {
return;
}
auto inType = curr->cont->type.getHeapType();
auto outType = curr->type.getHeapType();
auto sigIn = inType.getContinuation().type.getSignature();
auto sigOut = outType.getContinuation().type.getSignature();

// Each of the bound arguments must remain subtypes of their expected
// parameters.
auto params = curr->cont->type.getHeapType()
.getContinuation()
.type.getSignature()
.params;
assert(curr->operands.size() <= params.size());
for (Index i = 0; i < curr->operands.size(); ++i) {
self()->noteSubtype(curr->operands[i], params[i]);
size_t numBound = curr->operands.size();
for (Index i = 0; i < numBound; ++i) {
self()->noteSubtype(curr->operands[i], sigIn.params[i]);
}
// Each of the unbound output parameters must remain subtypes of their
// corresponding input parameters.
size_t numRemaining = sigIn.params.size() - numBound;
for (Index i = 0; i < numRemaining; ++i) {
self()->noteSubtype(sigOut.params[i], sigIn.params[numBound + i]);
}
// The original input results must remain a subtype of the new output
// results.
self()->noteSubtype(sigIn.results, sigOut.results);
}
void visitSuspend(Suspend* curr) {
auto sig = self()->getModule()->getTag(curr->tag)->type.getSignature();
// The operands must remain subtypes of the parameters given by the tag.
auto params =
self()->getModule()->getTag(curr->tag)->type.getSignature().params;
assert(curr->operands.size() == params.size());
assert(curr->operands.size() == sig.params.size());
for (Index i = 0; i < curr->operands.size(); ++i) {
self()->noteSubtype(curr->operands[i], params[i]);
self()->noteSubtype(curr->operands[i], sig.params[i]);
}
}
void processResumeHandlers(Type contType,
const ArenaVector<Name>& handlerTags,
const ArenaVector<Name>& handlerBlocks) {
assert(contType.isContinuation());
auto contSig = contType.getHeapType().getContinuation().type.getSignature();
assert(handlerTags.size() == handlerBlocks.size());
auto& wasm = *self()->getModule();
Expand Down
26 changes: 9 additions & 17 deletions src/wasm-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1352,44 +1352,36 @@ class Builder {
const std::vector<Name>& handlerBlocks,
const std::vector<Type>& sentTypes,
ExpressionList&& operands,
Expression* cont) {
Expression* cont,
HeapType contType) {
auto* ret = wasm.allocator.alloc<Resume>();
ret->handlerTags.set(handlerTags);
ret->handlerBlocks.set(handlerBlocks);
ret->sentTypes.set(sentTypes);
ret->operands = std::move(operands);
ret->cont = cont;
assert(contType.isContinuation());
ret->type = contType.getContinuation().type.getSignature().results;
ret->finalize();
return ret;
}
template<typename T>
Resume* makeResume(const std::vector<Name>& handlerTags,
const std::vector<Name>& handlerBlocks,
const std::vector<Type>& sentTypes,
ExpressionList& operands,
Expression* cont) {
auto* ret = wasm.allocator.alloc<Resume>();
ret->handlerTags.set(handlerTags);
ret->handlerBlocks.set(handlerBlocks);
ret->sentTypes.set(sentTypes);
ret->operands.set(operands);
ret->cont = cont;
ret->finalize();
return ret;
}

ResumeThrow* makeResumeThrow(Name tag,
const std::vector<Name>& handlerTags,
const std::vector<Name>& handlerBlocks,
const std::vector<Type>& sentTypes,
ExpressionList&& operands,
Expression* cont) {
Expression* cont,
HeapType contType) {
auto* ret = wasm.allocator.alloc<ResumeThrow>();
ret->tag = tag;
ret->handlerTags.set(handlerTags);
ret->handlerBlocks.set(handlerBlocks);
ret->sentTypes.set(sentTypes);
ret->operands = std::move(operands);
ret->cont = cont;
assert(contType.isContinuation());
ret->type = contType.getContinuation().type.getSignature().results;
ret->finalize();
return ret;
}
Expand Down
6 changes: 4 additions & 2 deletions src/wasm/wasm-ir-builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2675,7 +2675,8 @@ IRBuilder::makeResume(HeapType ct,
resumetable->targets,
resumetable->sentTypes,
std::move(curr.operands),
curr.cont));
curr.cont,
ct));

return Ok{};
}
Expand Down Expand Up @@ -2715,7 +2716,8 @@ IRBuilder::makeResumeThrow(HeapType ct,
resumetable->targets,
resumetable->sentTypes,
std::move(curr.operands),
curr.cont));
curr.cont,
ct));
return Ok{};
}

Expand Down
44 changes: 22 additions & 22 deletions src/wasm/wasm-validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4510,6 +4510,28 @@ void FunctionValidator::visitResumeThrow(ResumeThrow* curr) {
return;
}

if (curr->cont->type == Type::unreachable) {
return;
}

if (!shouldBeTrue(curr->cont->type.isRef(),
curr,
"resume_throw continuation must be a reference")) {
return;
}

auto type = curr->cont->type.getHeapType();
if (type.isMaybeShared(HeapType::nocont)) {
return;
}

if (!shouldBeTrue(
type.isContinuation(),
curr,
"resume_throw continuation must have a defined continuation type")) {
return;
}

if (curr->tag) {
// Normal resume_throw
auto* tag = getModule()->getTagOrNull(curr->tag);
Expand Down Expand Up @@ -4551,28 +4573,6 @@ void FunctionValidator::visitResumeThrow(ResumeThrow* curr) {
}
}

if (curr->cont->type == Type::unreachable) {
return;
}

if (!shouldBeTrue(curr->cont->type.isRef(),
curr,
"resume_throw continuation must be a reference")) {
return;
}

auto type = curr->cont->type.getHeapType();
if (type.isMaybeShared(HeapType::nocont)) {
return;
}

if (!shouldBeTrue(
type.isContinuation(),
curr,
"resume_throw continuation must have a defined continuation type")) {
return;
}

auto sig = type.getContinuation().type.getSignature();

shouldBeEqualOrFirstIsUnreachable(
Expand Down
Loading
Loading