Skip to content

Commit b1d65ce

Browse files
committed
Read sentTypes off label types.
1 parent 3bedcb5 commit b1d65ce

File tree

2 files changed

+81
-124
lines changed

2 files changed

+81
-124
lines changed

src/wasm/wasm-binary.cpp

Lines changed: 21 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -7974,77 +7974,47 @@ static void readResumeTable(WasmBinaryReader* reader, ResumeType* curr) {
79747974
std::is_base_of<ResumeThrow, ResumeType>::value);
79757975

79767976
auto numHandlers = reader->getU32LEB();
7977-
7978-
// We *must* bring the handlerTags vector to an appropriate size to ensure
7979-
// that we do not invalidate the pointers we add to tagRefs. They need to stay
7980-
// valid until processNames ran.
79817977
curr->handlerTags.resize(numHandlers);
79827978
curr->handlerBlocks.resize(numHandlers);
7979+
curr->sentTypes.resize(numHandlers);
79837980

79847981
for (size_t i = 0; i < numHandlers; i++) {
79857982
uint8_t code = reader->getInt8();
79867983
auto tagIndex = reader->getU32LEB();
79877984
auto tag = reader->getTagName(tagIndex);
79887985
Name handler;
7986+
Type sentType;
79897987
if (code == BinaryConsts::OnLabel) {
79907988
// expect (on $tag $label)
79917989
auto handlerIndex = reader->getU32LEB();
7992-
handler = reader->getBreakTarget(handlerIndex).name;
7990+
auto target = reader->getBreakTarget(handlerIndex);
7991+
handler = target.name;
7992+
if (target.type.isContinuation()) {
7993+
sentType = target.type;
7994+
} else if (target.type.isTuple() &&
7995+
target.type.getTuple().back().isContinuation()) {
7996+
// The continuation type is expected to be the last element of
7997+
// a multi-valued block.
7998+
sentType = target.type;
7999+
} else {
8000+
if constexpr (std::is_base_of<Resume, ResumeType>::value) {
8001+
reader->throwError("non-continuation type on resume branch target");
8002+
} else {
8003+
reader->throwError(
8004+
"non-continuation type on resume_throw branch target");
8005+
}
8006+
}
79938007
} else if (code == BinaryConsts::OnSwitch) {
79948008
// expect (on $tag switch)
79958009
handler = Name();
8010+
sentType = Type::none;
79968011
} else { // error
79978012
reader->throwError("ON opcode expected");
79988013
}
79998014

80008015
curr->handlerTags[i] = tag;
80018016
curr->handlerBlocks[i] = handler;
8002-
}
8003-
}
8004-
8005-
template<typename ResumeOrResumeThrow>
8006-
static void computeResumeTableSentTypes(Module& wasm,
8007-
ResumeOrResumeThrow* curr) {
8008-
static_assert(std::is_base_of<Resume, ResumeOrResumeThrow>::value ||
8009-
std::is_base_of<ResumeThrow, ResumeOrResumeThrow>::value);
8010-
assert(curr->handlerBlocks.size() == curr->handlerTags.size());
8011-
8012-
// Let $tag be a tag with type [tgp*] -> [tgr*]. Let $ct be a continuation
8013-
// type (cont $ft), where $ft is [ctp*] -> [ctr*]. Then an instruction
8014-
// (resume $ct ... (tag $tag $block) ... ) causes $block to receive values
8015-
// of the following types when suspending to $tag: tgp* (ref $ct') where ct'
8016-
// = (cont $ft') and ft' = [tgr*] -> [ctr*].
8017-
//
8018-
curr->sentTypes.reserve(curr->handlerTags.size());
8019-
auto contSig = curr->contType.getContinuation().type.getSignature();
8020-
auto& ctrs = contSig.params;
8021-
for (Index i = 0; i < curr->handlerTags.size(); i++) {
8022-
Type sentType;
8023-
if (curr->handlerBlocks[i].isNull()) {
8024-
sentType = Type::none;
8025-
} else {
8026-
auto& tag = curr->handlerTags[i];
8027-
auto& tagSig = wasm.getTag(tag)->sig;
8028-
8029-
auto& tgps = tagSig.params;
8030-
auto& tgrs = tagSig.results;
8031-
8032-
HeapType ftPrime{Signature(tgrs, ctrs)};
8033-
HeapType ctPrime{Continuation(ftPrime)};
8034-
Type ctPrimeRef(ctPrime, Nullability::NonNullable);
8035-
8036-
if (tgps.size() > 0) {
8037-
TypeList sentValueTypes;
8038-
sentValueTypes.reserve(tgps.size() + 1);
8039-
8040-
sentValueTypes.insert(sentValueTypes.begin(), tgps.begin(), tgps.end());
8041-
sentValueTypes.push_back(ctPrimeRef);
8042-
sentType = Type(sentValueTypes);
8043-
} else {
8044-
sentType = ctPrimeRef;
8045-
}
8046-
}
8047-
curr->sentTypes.push_back(sentType);
8017+
curr->sentTypes[i] = sentType;
80488018
}
80498019
}
80508020

@@ -8057,7 +8027,6 @@ void WasmBinaryReader::visitResume(Resume* curr) {
80578027
}
80588028

80598029
readResumeTable<Resume>(this, curr);
8060-
computeResumeTableSentTypes<Resume>(wasm, curr);
80618030

80628031
curr->cont = popNonVoidExpression();
80638032

@@ -8081,7 +8050,6 @@ void WasmBinaryReader::visitResumeThrow(ResumeThrow* curr) {
80818050
curr->tag = getTagName(exnTagIndex);
80828051

80838052
readResumeTable<ResumeThrow>(this, curr);
8084-
computeResumeTableSentTypes<ResumeThrow>(wasm, curr);
80858053

80868054
curr->cont = popNonVoidExpression();
80878055

src/wasm/wasm-ir-builder.cpp

Lines changed: 60 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1963,53 +1963,52 @@ Result<> IRBuilder::makeSuspend(Name tag) {
19631963
return Ok{};
19641964
}
19651965

1966-
static std::vector<Type>
1967-
computeResumeTableSentTypes(Module& wasm,
1968-
const Signature& contSig,
1969-
const std::vector<Name>& handlerTags,
1970-
const std::vector<Name> handlerBlocks) {
1971-
assert(handlerBlocks.size() == handlerTags.size());
1972-
1973-
// Let $tag be a tag with type [tgp*] -> [tgr*]. Let $ct be a continuation
1974-
// type (cont $ft), where $ft is [ctp*] -> [ctr*]. Then an instruction
1975-
// (resume $ct ... (tag $tag $block) ... ) causes $block to receive values
1976-
// of the following types when suspending to $tag: tgp* (ref $ct') where ct'
1977-
// = (cont $ft') and ft' = [tgr*] -> [ctr*].
1978-
//
1966+
struct ResumeTable {
1967+
std::vector<Name> targets;
19791968
std::vector<Type> sentTypes;
1980-
sentTypes.reserve(handlerTags.size());
1981-
auto& ctrs = contSig.params;
1982-
for (Index i = 0; i < handlerTags.size(); i++) {
1983-
Type sentType;
1984-
if (handlerBlocks[i].isNull()) {
1985-
sentType = Type::none;
1986-
} else {
1987-
auto& tag = handlerTags[i];
1988-
auto& tagSig = wasm.getTag(tag)->sig;
1989-
1990-
auto& tgps = tagSig.params;
1991-
auto& tgrs = tagSig.results;
1969+
};
19921970

1993-
HeapType ftPrime{Signature(tgrs, ctrs)};
1994-
HeapType ctPrime{Continuation(ftPrime)};
1995-
Type ctPrimeRef(ctPrime, Nullability::NonNullable);
1971+
static Result<ResumeTable>
1972+
makeResumeTable(const std::vector<std::optional<Index>>& labels,
1973+
std::function<Result<Name>(Index)> getLabelName,
1974+
std::function<Result<Type>(Index)> getLabelType) {
1975+
std::vector<Name> targets;
1976+
targets.reserve(labels.size());
19961977

1997-
if (tgps.size() > 0) {
1998-
TypeList sentValueTypes;
1999-
sentValueTypes.reserve(tgps.size() + 1);
1978+
std::vector<Type> sentTypes;
1979+
sentTypes.reserve(sentTypes.size());
20001980

2001-
sentValueTypes.insert(sentValueTypes.begin(), tgps.begin(), tgps.end());
2002-
sentValueTypes.push_back(ctPrimeRef);
2003-
sentType = Type(sentValueTypes);
1981+
for (Index i = 0; i < labels.size(); i++) {
1982+
Name target;
1983+
Type sentType;
1984+
if (labels[i].has_value()) {
1985+
// (on $tag $label) clause
1986+
Index labelIndex = labels[i].value();
1987+
Result<Name> name = getLabelName(labelIndex);
1988+
CHECK_ERR(name);
1989+
target = *name;
1990+
1991+
Result<Type> targetType = getLabelType(labelIndex);
1992+
CHECK_ERR(targetType);
1993+
if (targetType->isContinuation()) {
1994+
sentType = *targetType;
1995+
} else if (targetType->isTuple() &&
1996+
targetType->getTuple().back().isContinuation()) {
1997+
// The continuation type is expected to be the last element of
1998+
// a multi-valued block.
1999+
sentType = *targetType;
20042000
} else {
2005-
sentType = ctPrimeRef;
2001+
return Err{"expected continuation type"};
20062002
}
2003+
} else {
2004+
// (on $tag switch) clause
2005+
target = Name();
2006+
sentType = Type::none;
20072007
}
2008+
targets.push_back(target);
20082009
sentTypes.push_back(sentType);
20092010
}
2010-
assert(sentTypes.size() == handlerTags.size() &&
2011-
sentTypes.size() == handlerBlocks.size());
2012-
return sentTypes;
2011+
return ResumeTable{std::move(targets), std::move(sentTypes)};
20132012
}
20142013

20152014
Result<>
@@ -2025,24 +2024,18 @@ IRBuilder::makeResume(HeapType ct,
20252024
curr.operands.resize(contSig.params.size());
20262025
CHECK_ERR(visitResume(&curr));
20272026

2028-
std::vector<Name> labelNames;
2029-
labelNames.reserve(labels.size());
2030-
for (size_t i = 0; i < labels.size(); i++) {
2031-
if (labels[i].has_value()) {
2032-
auto name = getLabelName(labels[i].value());
2033-
CHECK_ERR(name);
2034-
labelNames.push_back(*name);
2035-
} else {
2036-
labelNames.push_back(Name());
2037-
}
2038-
}
2039-
std::vector<Type> sentTypes =
2040-
computeResumeTableSentTypes(wasm, contSig, tags, labelNames);
2041-
curr.sentTypes.resize(sentTypes.size());
2042-
assert(sentTypes.size() == labelNames.size());
2027+
Result<ResumeTable> resumetable = std::move(makeResumeTable(
2028+
labels,
2029+
[this](Index i) { return this->getLabelName(i); },
2030+
[this](Index i) { return this->getLabelType(i); }));
2031+
CHECK_ERR(resumetable);
20432032
std::vector<Expression*> operands(curr.operands.begin(), curr.operands.end());
2044-
push(
2045-
builder.makeResume(ct, tags, labelNames, sentTypes, operands, curr.cont));
2033+
push(builder.makeResume(ct,
2034+
tags,
2035+
resumetable->targets,
2036+
resumetable->sentTypes,
2037+
operands,
2038+
curr.cont));
20462039
return Ok{};
20472040
}
20482041

@@ -2058,29 +2051,25 @@ IRBuilder::makeResumeThrow(HeapType ct,
20582051
return Err{"expected continuation type"};
20592052
}
20602053
ResumeThrow curr(wasm.allocator);
2061-
auto contSig = ct.getContinuation().type.getSignature();
20622054
curr.contType = ct;
20632055
curr.tag = tag;
20642056
curr.operands.resize(wasm.getTag(tag)->sig.params.size());
20652057
CHECK_ERR(visitResumeThrow(&curr));
20662058

2067-
std::vector<Name> labelNames;
2068-
labelNames.reserve(labels.size());
2069-
for (size_t i = 0; i < labels.size(); i++) {
2070-
if (labels[i].has_value()) {
2071-
auto name = getLabelName(labels[i].value());
2072-
CHECK_ERR(name);
2073-
labelNames.push_back(*name);
2074-
} else {
2075-
labelNames.push_back(Name());
2076-
}
2077-
}
2078-
std::vector<Type> sentTypes =
2079-
computeResumeTableSentTypes(wasm, contSig, tags, labelNames);
2059+
Result<ResumeTable> resumetable = std::move(makeResumeTable(
2060+
labels,
2061+
[this](Index i) { return this->getLabelName(i); },
2062+
[this](Index i) { return this->getLabelType(i); }));
2063+
CHECK_ERR(resumetable);
20802064

20812065
std::vector<Expression*> operands(curr.operands.begin(), curr.operands.end());
2082-
push(builder.makeResumeThrow(
2083-
ct, tag, tags, labelNames, sentTypes, operands, curr.cont));
2066+
push(builder.makeResumeThrow(ct,
2067+
tag,
2068+
tags,
2069+
resumetable->targets,
2070+
resumetable->sentTypes,
2071+
operands,
2072+
curr.cont));
20842073
return Ok{};
20852074
}
20862075

0 commit comments

Comments
 (0)