Skip to content

Commit afae706

Browse files
authored
More unsubtyping for cont.bind (#8506)
We were missing a few type constraints for cont.bind. Add them, and also add more thorough tests for all the stack switching instructions, including the cases where the continuations are null. As a drive-by to get these tests working, fix the parsing of resume and resume_throw* to set the proper type arity when the input is null.
1 parent 737417d commit afae706

File tree

6 files changed

+1439
-238
lines changed

6 files changed

+1439
-238
lines changed

src/ir/subtype-exprs.h

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -494,32 +494,42 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
494494
curr->type.getHeapType().getContinuation().type);
495495
}
496496
void visitContBind(ContBind* curr) {
497-
if (!curr->cont->type.isContinuation()) {
497+
if (!curr->cont->type.isContinuation() || !curr->type.isContinuation()) {
498498
return;
499499
}
500+
auto inType = curr->cont->type.getHeapType();
501+
auto outType = curr->type.getHeapType();
502+
auto sigIn = inType.getContinuation().type.getSignature();
503+
auto sigOut = outType.getContinuation().type.getSignature();
504+
500505
// Each of the bound arguments must remain subtypes of their expected
501506
// parameters.
502-
auto params = curr->cont->type.getHeapType()
503-
.getContinuation()
504-
.type.getSignature()
505-
.params;
506-
assert(curr->operands.size() <= params.size());
507-
for (Index i = 0; i < curr->operands.size(); ++i) {
508-
self()->noteSubtype(curr->operands[i], params[i]);
507+
size_t numBound = curr->operands.size();
508+
for (Index i = 0; i < numBound; ++i) {
509+
self()->noteSubtype(curr->operands[i], sigIn.params[i]);
510+
}
511+
// Each of the unbound output parameters must remain subtypes of their
512+
// corresponding input parameters.
513+
size_t numRemaining = sigIn.params.size() - numBound;
514+
for (Index i = 0; i < numRemaining; ++i) {
515+
self()->noteSubtype(sigOut.params[i], sigIn.params[numBound + i]);
509516
}
517+
// The original input results must remain a subtype of the new output
518+
// results.
519+
self()->noteSubtype(sigIn.results, sigOut.results);
510520
}
511521
void visitSuspend(Suspend* curr) {
522+
auto sig = self()->getModule()->getTag(curr->tag)->type.getSignature();
512523
// The operands must remain subtypes of the parameters given by the tag.
513-
auto params =
514-
self()->getModule()->getTag(curr->tag)->type.getSignature().params;
515-
assert(curr->operands.size() == params.size());
524+
assert(curr->operands.size() == sig.params.size());
516525
for (Index i = 0; i < curr->operands.size(); ++i) {
517-
self()->noteSubtype(curr->operands[i], params[i]);
526+
self()->noteSubtype(curr->operands[i], sig.params[i]);
518527
}
519528
}
520529
void processResumeHandlers(Type contType,
521530
const ArenaVector<Name>& handlerTags,
522531
const ArenaVector<Name>& handlerBlocks) {
532+
assert(contType.isContinuation());
523533
auto contSig = contType.getHeapType().getContinuation().type.getSignature();
524534
assert(handlerTags.size() == handlerBlocks.size());
525535
auto& wasm = *self()->getModule();

src/wasm-builder.h

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,44 +1352,34 @@ class Builder {
13521352
const std::vector<Name>& handlerBlocks,
13531353
const std::vector<Type>& sentTypes,
13541354
ExpressionList&& operands,
1355-
Expression* cont) {
1355+
Expression* cont,
1356+
HeapType contType) {
13561357
auto* ret = wasm.allocator.alloc<Resume>();
13571358
ret->handlerTags.set(handlerTags);
13581359
ret->handlerBlocks.set(handlerBlocks);
13591360
ret->sentTypes.set(sentTypes);
13601361
ret->operands = std::move(operands);
13611362
ret->cont = cont;
1363+
ret->type = contType.getContinuation().type.getSignature().results;
13621364
ret->finalize();
13631365
return ret;
13641366
}
1365-
template<typename T>
1366-
Resume* makeResume(const std::vector<Name>& handlerTags,
1367-
const std::vector<Name>& handlerBlocks,
1368-
const std::vector<Type>& sentTypes,
1369-
ExpressionList& operands,
1370-
Expression* cont) {
1371-
auto* ret = wasm.allocator.alloc<Resume>();
1372-
ret->handlerTags.set(handlerTags);
1373-
ret->handlerBlocks.set(handlerBlocks);
1374-
ret->sentTypes.set(sentTypes);
1375-
ret->operands.set(operands);
1376-
ret->cont = cont;
1377-
ret->finalize();
1378-
return ret;
1379-
}
1367+
13801368
ResumeThrow* makeResumeThrow(Name tag,
13811369
const std::vector<Name>& handlerTags,
13821370
const std::vector<Name>& handlerBlocks,
13831371
const std::vector<Type>& sentTypes,
13841372
ExpressionList&& operands,
1385-
Expression* cont) {
1373+
Expression* cont,
1374+
HeapType contType) {
13861375
auto* ret = wasm.allocator.alloc<ResumeThrow>();
13871376
ret->tag = tag;
13881377
ret->handlerTags.set(handlerTags);
13891378
ret->handlerBlocks.set(handlerBlocks);
13901379
ret->sentTypes.set(sentTypes);
13911380
ret->operands = std::move(operands);
13921381
ret->cont = cont;
1382+
ret->type = contType.getContinuation().type.getSignature().results;
13931383
ret->finalize();
13941384
return ret;
13951385
}

src/wasm/wasm-ir-builder.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2675,7 +2675,8 @@ IRBuilder::makeResume(HeapType ct,
26752675
resumetable->targets,
26762676
resumetable->sentTypes,
26772677
std::move(curr.operands),
2678-
curr.cont));
2678+
curr.cont,
2679+
ct));
26792680

26802681
return Ok{};
26812682
}
@@ -2715,7 +2716,8 @@ IRBuilder::makeResumeThrow(HeapType ct,
27152716
resumetable->targets,
27162717
resumetable->sentTypes,
27172718
std::move(curr.operands),
2718-
curr.cont));
2719+
curr.cont,
2720+
ct));
27192721
return Ok{};
27202722
}
27212723

src/wasm/wasm-validator.cpp

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4510,6 +4510,28 @@ void FunctionValidator::visitResumeThrow(ResumeThrow* curr) {
45104510
return;
45114511
}
45124512

4513+
if (curr->cont->type == Type::unreachable) {
4514+
return;
4515+
}
4516+
4517+
if (!shouldBeTrue(curr->cont->type.isRef(),
4518+
curr,
4519+
"resume_throw continuation must be a reference")) {
4520+
return;
4521+
}
4522+
4523+
auto type = curr->cont->type.getHeapType();
4524+
if (type.isMaybeShared(HeapType::nocont)) {
4525+
return;
4526+
}
4527+
4528+
if (!shouldBeTrue(
4529+
type.isContinuation(),
4530+
curr,
4531+
"resume_throw continuation must have a defined continuation type")) {
4532+
return;
4533+
}
4534+
45134535
if (curr->tag) {
45144536
// Normal resume_throw
45154537
auto* tag = getModule()->getTagOrNull(curr->tag);
@@ -4551,28 +4573,6 @@ void FunctionValidator::visitResumeThrow(ResumeThrow* curr) {
45514573
}
45524574
}
45534575

4554-
if (curr->cont->type == Type::unreachable) {
4555-
return;
4556-
}
4557-
4558-
if (!shouldBeTrue(curr->cont->type.isRef(),
4559-
curr,
4560-
"resume_throw continuation must be a reference")) {
4561-
return;
4562-
}
4563-
4564-
auto type = curr->cont->type.getHeapType();
4565-
if (type.isMaybeShared(HeapType::nocont)) {
4566-
return;
4567-
}
4568-
4569-
if (!shouldBeTrue(
4570-
type.isContinuation(),
4571-
curr,
4572-
"resume_throw continuation must have a defined continuation type")) {
4573-
return;
4574-
}
4575-
45764576
auto sig = type.getContinuation().type.getSignature();
45774577

45784578
shouldBeEqualOrFirstIsUnreachable(

0 commit comments

Comments
 (0)