summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/parser/contexts.h45
-rw-r--r--src/wasm-binary.h4
-rw-r--r--src/wasm-ir-builder.h95
-rw-r--r--src/wasm/wasm-binary.cpp40
-rw-r--r--src/wasm/wasm-ir-builder.cpp129
5 files changed, 201 insertions, 112 deletions
diff --git a/src/parser/contexts.h b/src/parser/contexts.h
index 807b6c003..3e0bc7c40 100644
--- a/src/parser/contexts.h
+++ b/src/parser/contexts.h
@@ -1447,11 +1447,7 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
Result<HeapType> getBlockTypeFromTypeUse(Index pos, HeapType type) {
assert(type.isSignature());
- if (type.getSignature().params != Type::none) {
- return in.err(pos, "block parameters not yet supported");
- }
- // TODO: Once we support block parameters, return an error here if any of
- // them are named.
+ // TODO: Error if block parameters are named
return type;
}
@@ -1822,9 +1818,11 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
HeapType type) {
// TODO: validate labels?
// TODO: Move error on input types to here?
- return withLoc(pos,
- irBuilder.makeBlock(label ? *label : Name{},
- type.getSignature().results));
+ if (!type.isSignature()) {
+ return in.err(pos, "expected function type");
+ }
+ return withLoc(
+ pos, irBuilder.makeBlock(label ? *label : Name{}, type.getSignature()));
}
Result<> makeIf(Index pos,
@@ -1832,10 +1830,11 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
std::optional<Name> label,
HeapType type) {
// TODO: validate labels?
- // TODO: Move error on input types to here?
+ if (!type.isSignature()) {
+ return in.err(pos, "expected function type");
+ }
return withLoc(
- pos,
- irBuilder.makeIf(label ? *label : Name{}, type.getSignature().results));
+ pos, irBuilder.makeIf(label ? *label : Name{}, type.getSignature()));
}
Result<> visitElse() { return withLoc(irBuilder.visitElse()); }
@@ -1845,10 +1844,11 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
std::optional<Name> label,
HeapType type) {
// TODO: validate labels?
- // TODO: Move error on input types to here?
+ if (!type.isSignature()) {
+ return in.err(pos, "expected function type");
+ }
return withLoc(
- pos,
- irBuilder.makeLoop(label ? *label : Name{}, type.getSignature().results));
+ pos, irBuilder.makeLoop(label ? *label : Name{}, type.getSignature()));
}
Result<> makeTry(Index pos,
@@ -1856,10 +1856,11 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
std::optional<Name> label,
HeapType type) {
// TODO: validate labels?
- // TODO: Move error on input types to here?
+ if (!type.isSignature()) {
+ return in.err(pos, "expected function type");
+ }
return withLoc(
- pos,
- irBuilder.makeTry(label ? *label : Name{}, type.getSignature().results));
+ pos, irBuilder.makeTry(label ? *label : Name{}, type.getSignature()));
}
Result<> makeTryTable(Index pos,
@@ -1875,12 +1876,10 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
labels.push_back(info.label);
isRefs.push_back(info.isRef);
}
- return withLoc(pos,
- irBuilder.makeTryTable(label ? *label : Name{},
- type.getSignature().results,
- tags,
- labels,
- isRefs));
+ return withLoc(
+ pos,
+ irBuilder.makeTryTable(
+ label ? *label : Name{}, type.getSignature(), tags, labels, isRefs));
}
Result<> visitCatch(Index pos, Name tag) {
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 163a62b1e..61f4faf69 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1467,10 +1467,12 @@ public:
bool getBasicType(int32_t code, Type& out);
bool getBasicHeapType(int64_t code, HeapType& out);
+ // Get the signature of control flow structure.
+ Signature getBlockType();
// Read a value and get a type for it.
Type getType();
// Get a type given the initial S32LEB has already been read, and is provided.
- Type getType(int initial);
+ Type getType(int code);
HeapType getHeapType();
HeapType getIndexedHeapType();
diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h
index 84ac26979..250d5d17c 100644
--- a/src/wasm-ir-builder.h
+++ b/src/wasm-ir-builder.h
@@ -80,15 +80,18 @@ public:
// the corresponding `makeXYZ` function below instead of `visitXYZStart`, but
// either way must call `visitEnd` and friends at the appropriate times.
Result<> visitFunctionStart(Function* func);
- Result<> visitBlockStart(Block* block);
- Result<> visitIfStart(If* iff, Name label = {});
+ Result<> visitBlockStart(Block* block, Type inputType = Type::none);
+ Result<> visitIfStart(If* iff, Name label = {}, Type inputType = Type::none);
Result<> visitElse();
- Result<> visitLoopStart(Loop* iff);
- Result<> visitTryStart(Try* tryy, Name label = {});
+ Result<> visitLoopStart(Loop* iff, Type inputType = Type::none);
+ Result<>
+ visitTryStart(Try* tryy, Name label = {}, Type inputType = Type::none);
Result<> visitCatch(Name tag);
Result<> visitCatchAll();
Result<> visitDelegate(Index label);
- Result<> visitTryTableStart(TryTable* trytable, Name label = {});
+ Result<> visitTryTableStart(TryTable* trytable,
+ Name label = {},
+ Type inputType = Type::none);
Result<> visitEnd();
// Used to visit break nodes when traversing a single block without its
@@ -113,9 +116,9 @@ public:
// nodes. This is generally safer than calling `visit` because the function
// signatures ensure that there are no missing fields.
Result<> makeNop();
- Result<> makeBlock(Name label, Type type);
- Result<> makeIf(Name label, Type type);
- Result<> makeLoop(Name label, Type type);
+ Result<> makeBlock(Name label, Signature sig);
+ Result<> makeIf(Name label, Signature sig);
+ Result<> makeLoop(Name label, Signature sig);
Result<> makeBreak(Index label, bool isConditional);
Result<> makeSwitch(const std::vector<Index>& labels, Index defaultLabel);
// Unlike Builder::makeCall, this assumes the function already exists.
@@ -180,9 +183,9 @@ public:
Result<> makeTableFill(Name table);
Result<> makeTableCopy(Name destTable, Name srcTable);
Result<> makeTableInit(Name elem, Name table);
- Result<> makeTry(Name label, Type type);
+ Result<> makeTry(Name label, Signature sig);
Result<> makeTryTable(Name label,
- Type type,
+ Signature sig,
const std::vector<Name>& tags,
const std::vector<Index>& labels,
const std::vector<bool>& isRefs);
@@ -323,13 +326,21 @@ private:
// The branch label name for this scope. Always fresh, never shadowed.
Name label;
+
// For Try/Catch/CatchAll scopes, we need to separately track a label used
// for branches, since the normal label is only used for delegates.
Name branchLabel;
bool labelUsed = false;
+ // If the control flow scope has an input type, we need to lower it using a
+ // scratch local because we cannot represent control flow input in the IR.
+ Type inputType;
+ Index inputLocal = -1;
+
+ // The stack of instructions being built in this scope.
std::vector<Expression*> exprStack;
+
// Whether we have seen an unreachable instruction and are in
// stack-polymorphic unreachable mode.
bool unreachable = false;
@@ -338,29 +349,39 @@ private:
size_t startPos = 0;
ScopeCtx() : scope(NoScope{}) {}
- ScopeCtx(Scope scope) : scope(scope) {}
- ScopeCtx(Scope scope, Name label, bool labelUsed)
- : scope(scope), label(label), labelUsed(labelUsed) {}
+ ScopeCtx(Scope scope, Type inputType)
+ : scope(scope), inputType(inputType) {}
+ ScopeCtx(
+ Scope scope, Name label, bool labelUsed, Type inputType, Index inputLocal)
+ : scope(scope), label(label), labelUsed(labelUsed), inputType(inputType),
+ inputLocal(inputLocal) {}
ScopeCtx(Scope scope, Name label, bool labelUsed, Name branchLabel)
: scope(scope), label(label), branchLabel(branchLabel),
labelUsed(labelUsed) {}
static ScopeCtx makeFunc(Function* func) {
- return ScopeCtx(FuncScope{func});
+ return ScopeCtx(FuncScope{func}, Type::none);
}
- static ScopeCtx makeBlock(Block* block) {
- return ScopeCtx(BlockScope{block});
+ static ScopeCtx makeBlock(Block* block, Type inputType) {
+ return ScopeCtx(BlockScope{block}, inputType);
}
- static ScopeCtx makeIf(If* iff, Name originalLabel = {}) {
- return ScopeCtx(IfScope{iff, originalLabel});
+ static ScopeCtx makeIf(If* iff, Name originalLabel, Type inputType) {
+ return ScopeCtx(IfScope{iff, originalLabel}, inputType);
}
- static ScopeCtx
- makeElse(If* iff, Name originalLabel, Name label, bool labelUsed) {
- return ScopeCtx(ElseScope{iff, originalLabel}, label, labelUsed);
+ static ScopeCtx makeElse(If* iff,
+ Name originalLabel,
+ Name label,
+ bool labelUsed,
+ Type inputType,
+ Index inputLocal) {
+ return ScopeCtx(
+ ElseScope{iff, originalLabel}, label, labelUsed, inputType, inputLocal);
}
- static ScopeCtx makeLoop(Loop* loop) { return ScopeCtx(LoopScope{loop}); }
- static ScopeCtx makeTry(Try* tryy, Name originalLabel = {}) {
- return ScopeCtx(TryScope{tryy, originalLabel});
+ static ScopeCtx makeLoop(Loop* loop, Type inputType) {
+ return ScopeCtx(LoopScope{loop}, inputType);
+ }
+ static ScopeCtx makeTry(Try* tryy, Name originalLabel, Type inputType) {
+ return ScopeCtx(TryScope{tryy, originalLabel}, inputType);
}
static ScopeCtx makeCatch(Try* tryy,
Name originalLabel,
@@ -378,8 +399,9 @@ private:
return ScopeCtx(
CatchAllScope{tryy, originalLabel}, label, labelUsed, branchLabel);
}
- static ScopeCtx makeTryTable(TryTable* trytable, Name originalLabel = {}) {
- return ScopeCtx(TryTableScope{trytable, originalLabel});
+ static ScopeCtx
+ makeTryTable(TryTable* trytable, Name originalLabel, Type inputType) {
+ return ScopeCtx(TryTableScope{trytable, originalLabel}, inputType);
}
bool isNone() { return std::get_if<NoScope>(&scope); }
@@ -518,6 +540,7 @@ private:
}
WASM_UNREACHABLE("unexpected scope kind");
}
+ bool isDelimiter() { return getElse() || getCatch() || getCatchAll(); }
};
// The stack of block contexts currently being parsed.
@@ -541,7 +564,7 @@ private:
Index blockHint = 0;
Index labelHint = 0;
- void pushScope(ScopeCtx scope) {
+ Result<> pushScope(ScopeCtx&& scope) {
if (auto label = scope.getOriginalLabel()) {
// Assign a fresh label to the scope, if necessary.
if (!scope.label) {
@@ -554,7 +577,21 @@ private:
scope.startPos = lastBinaryPos;
lastBinaryPos = *binaryPos;
}
- scopeStack.push_back(scope);
+ bool hasInput = scope.inputType != Type::none;
+ Index inputLocal = scope.inputLocal;
+ if (hasInput && !scope.isDelimiter()) {
+ if (inputLocal == Index(-1)) {
+ auto scratch = addScratchLocal(scope.inputType);
+ CHECK_ERR(scratch);
+ inputLocal = scope.inputLocal = *scratch;
+ }
+ CHECK_ERR(makeLocalSet(inputLocal));
+ }
+ scopeStack.emplace_back(std::move(scope));
+ if (hasInput) {
+ CHECK_ERR(makeLocalGet(inputLocal));
+ }
+ return Ok{};
}
ScopeCtx& getScope() {
@@ -610,6 +647,8 @@ private:
Result<Type> getLabelType(Index label);
Result<Type> getLabelType(Name labelName);
+ void fixLoopWithInput(Loop* loop, Type inputType, Index scratch);
+
void dump();
};
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 0c931f518..791dc53d7 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -2121,30 +2121,30 @@ bool WasmBinaryReader::getBasicHeapType(int64_t code, HeapType& out) {
}
}
-Type WasmBinaryReader::getType(int initial) {
- // Single value types are negative; signature indices are non-negative
- if (initial >= 0) {
- // TODO: Handle block input types properly.
- auto sig = getSignatureByTypeIndex(initial);
- if (sig.params != Type::none) {
- throwError("control flow inputs are not supported yet");
- }
- return sig.results;
+Signature WasmBinaryReader::getBlockType() {
+ // Single value types are negative; signature indices are non-negative.
+ auto code = getS32LEB();
+ if (code >= 0) {
+ return getSignatureByTypeIndex(code);
+ }
+ if (code == BinaryConsts::EncodedType::Empty) {
+ return Signature();
}
+ return Signature(Type::none, getType(code));
+}
+
+Type WasmBinaryReader::getType(int code) {
Type type;
- if (getBasicType(initial, type)) {
+ if (getBasicType(code, type)) {
return type;
}
- switch (initial) {
- // None only used for block signatures. TODO: Separate out?
- case BinaryConsts::EncodedType::Empty:
- return Type::none;
+ switch (code) {
case BinaryConsts::EncodedType::nullable:
return Type(getHeapType(), Nullable);
case BinaryConsts::EncodedType::nonnullable:
return Type(getHeapType(), NonNullable);
default:
- throwError("invalid wasm type: " + std::to_string(initial));
+ throwError("invalid wasm type: " + std::to_string(code));
}
WASM_UNREACHABLE("unexpected type");
}
@@ -2885,11 +2885,11 @@ Result<> WasmBinaryReader::readInst() {
uint8_t code = getInt8();
switch (code) {
case BinaryConsts::Block:
- return builder.makeBlock(Name(), getType());
+ return builder.makeBlock(Name(), getBlockType());
case BinaryConsts::If:
- return builder.makeIf(Name(), getType());
+ return builder.makeIf(Name(), getBlockType());
case BinaryConsts::Loop:
- return builder.makeLoop(Name(), getType());
+ return builder.makeLoop(Name(), getBlockType());
case BinaryConsts::Br:
return builder.makeBreak(getU32LEB(), false);
case BinaryConsts::BrIf:
@@ -2974,9 +2974,9 @@ Result<> WasmBinaryReader::readInst() {
case BinaryConsts::TableSet:
return builder.makeTableSet(getTableName(getU32LEB()));
case BinaryConsts::Try:
- return builder.makeTry(Name(), getType());
+ return builder.makeTry(Name(), getBlockType());
case BinaryConsts::TryTable: {
- auto type = getType();
+ auto type = getBlockType();
std::vector<Name> tags;
std::vector<Index> labels;
std::vector<bool> isRefs;
diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp
index 96212ccd7..6cd62e439 100644
--- a/src/wasm/wasm-ir-builder.cpp
+++ b/src/wasm/wasm-ir-builder.cpp
@@ -679,9 +679,8 @@ Result<> IRBuilder::visitExpression(Expression* curr) {
Result<Type> IRBuilder::getLabelType(Index label) {
auto scope = getScope(label);
CHECK_ERR(scope);
- // Loops would receive their input type rather than their output type, if we
- // supported that.
- return (*scope)->getLoop() ? Type::none : (*scope)->getResultType();
+ // Loops receive their input type rather than their output type.
+ return (*scope)->getLoop() ? (*scope)->inputType : (*scope)->getResultType();
}
Result<Type> IRBuilder::getLabelType(Name labelName) {
@@ -722,35 +721,31 @@ Result<> IRBuilder::visitFunctionStart(Function* func) {
return Ok{};
}
-Result<> IRBuilder::visitBlockStart(Block* curr) {
+Result<> IRBuilder::visitBlockStart(Block* curr, Type inputType) {
applyDebugLoc(curr);
- pushScope(ScopeCtx::makeBlock(curr));
- return Ok{};
+ return pushScope(ScopeCtx::makeBlock(curr, inputType));
}
-Result<> IRBuilder::visitIfStart(If* iff, Name label) {
+Result<> IRBuilder::visitIfStart(If* iff, Name label, Type inputType) {
applyDebugLoc(iff);
CHECK_ERR(visitIf(iff));
- pushScope(ScopeCtx::makeIf(iff, label));
- return Ok{};
+ return pushScope(ScopeCtx::makeIf(iff, label, inputType));
}
-Result<> IRBuilder::visitLoopStart(Loop* loop) {
+Result<> IRBuilder::visitLoopStart(Loop* loop, Type inputType) {
applyDebugLoc(loop);
- pushScope(ScopeCtx::makeLoop(loop));
- return Ok{};
+ return pushScope(ScopeCtx::makeLoop(loop, inputType));
}
-Result<> IRBuilder::visitTryStart(Try* tryy, Name label) {
+Result<> IRBuilder::visitTryStart(Try* tryy, Name label, Type inputType) {
applyDebugLoc(tryy);
- pushScope(ScopeCtx::makeTry(tryy, label));
- return Ok{};
+ return pushScope(ScopeCtx::makeTry(tryy, label, inputType));
}
-Result<> IRBuilder::visitTryTableStart(TryTable* trytable, Name label) {
+Result<>
+IRBuilder::visitTryTableStart(TryTable* trytable, Name label, Type inputType) {
applyDebugLoc(trytable);
- pushScope(ScopeCtx::makeTryTable(trytable, label));
- return Ok{};
+ return pushScope(ScopeCtx::makeTryTable(trytable, label, inputType));
}
Result<Expression*> IRBuilder::finishScope(Block* block) {
@@ -849,6 +844,8 @@ Result<> IRBuilder::visitElse() {
auto originalLabel = scope.getOriginalLabel();
auto label = scope.label;
auto labelUsed = scope.labelUsed;
+ auto inputType = scope.inputType;
+ auto inputLocal = scope.inputLocal;
auto expr = finishScope();
CHECK_ERR(expr);
iff->ifTrue = *expr;
@@ -858,8 +855,8 @@ Result<> IRBuilder::visitElse() {
lastBinaryPos - codeSectionOffset;
}
- pushScope(ScopeCtx::makeElse(iff, originalLabel, label, labelUsed));
- return Ok{};
+ return pushScope(ScopeCtx::makeElse(
+ iff, originalLabel, label, labelUsed, inputType, inputLocal));
}
Result<> IRBuilder::visitCatch(Name tag) {
@@ -891,8 +888,8 @@ Result<> IRBuilder::visitCatch(Name tag) {
delimiterLocs[delimiterLocs.size()] = lastBinaryPos - codeSectionOffset;
}
- pushScope(
- ScopeCtx::makeCatch(tryy, originalLabel, label, labelUsed, branchLabel));
+ CHECK_ERR(pushScope(
+ ScopeCtx::makeCatch(tryy, originalLabel, label, labelUsed, branchLabel)));
// Push a pop for the exception payload if necessary.
auto params = wasm.getTag(tag)->sig.params;
if (params != Type::none) {
@@ -933,9 +930,8 @@ Result<> IRBuilder::visitCatchAll() {
delimiterLocs[delimiterLocs.size()] = lastBinaryPos - codeSectionOffset;
}
- pushScope(
+ return pushScope(
ScopeCtx::makeCatchAll(tryy, originalLabel, label, labelUsed, branchLabel));
- return Ok{};
}
Result<> IRBuilder::visitDelegate(Index label) {
@@ -1035,11 +1031,24 @@ Result<> IRBuilder::visitEnd() {
} else if (auto* loop = scope.getLoop()) {
loop->body = *expr;
loop->name = scope.label;
+ if (scope.inputType != Type::none && scope.labelUsed) {
+ // Branches to this loop carry values, but Binaryen IR does not support
+ // that. Fix this by trampolining the branches through new code that sets
+ // the branch value to the appropriate scratch local.
+ fixLoopWithInput(loop, scope.inputType, scope.inputLocal);
+ }
loop->finalize(loop->type);
push(loop);
} else if (auto* iff = scope.getIf()) {
iff->ifTrue = *expr;
- iff->ifFalse = nullptr;
+ if (scope.inputType != Type::none) {
+ // Normally an if without an else must have type none, but if there is an
+ // input parameter, the empty else arm must propagate its value.
+ // Synthesize an else arm that loads the value from the scratch local.
+ iff->ifFalse = builder.makeLocalGet(scope.inputLocal, scope.inputType);
+ } else {
+ iff->ifFalse = nullptr;
+ }
iff->finalize(iff->type);
push(maybeWrapForLabel(iff));
} else if (auto* iff = scope.getElse()) {
@@ -1067,6 +1076,46 @@ Result<> IRBuilder::visitEnd() {
return Ok{};
}
+// Branches to this loop need to be trampolined through code that sets the value
+// carried by the branch to the appropriate scratch local before branching to
+// the loop. Transform this:
+//
+// (loop $l (param t1) (result t2) ...)
+//
+// to this:
+//
+// (loop $l0 (result t2)
+// (block $l1 (result t2)
+// (local.set $scratch ;; set the branch values to the scratch local
+// (block $l (result t1)
+// (br $l1 ;; exit the loop with the fallthrough value, if any.
+// ... ;; contains branches to $l
+// )
+// )
+// )
+// (br $l0) ;; continue the loop
+// )
+// )
+void IRBuilder::fixLoopWithInput(Loop* loop, Type inputType, Index scratch) {
+ auto l = loop->name;
+ auto l0 = makeFresh(l, 0);
+ auto l1 = makeFresh(l, 1);
+
+ Block* inner =
+ loop->type == Type::none
+ ? builder.blockifyWithName(
+ loop->body, l, builder.makeBreak(l1), inputType)
+ : builder.makeBlock(l, {builder.makeBreak(l1, loop->body)}, inputType);
+
+ Block* outer = builder.makeBlock(
+ l1,
+ {builder.makeLocalSet(scratch, inner), builder.makeBreak(l0)},
+ loop->type);
+
+ loop->body = outer;
+ loop->name = l0;
+}
+
Result<Index> IRBuilder::getLabelIndex(Name label, bool inDelegate) {
auto it = labelDepths.find(label);
if (it == labelDepths.end() || it->second.empty()) {
@@ -1128,24 +1177,24 @@ Result<> IRBuilder::makeNop() {
return Ok{};
}
-Result<> IRBuilder::makeBlock(Name label, Type type) {
+Result<> IRBuilder::makeBlock(Name label, Signature sig) {
auto* block = wasm.allocator.alloc<Block>();
block->name = label;
- block->type = type;
- return visitBlockStart(block);
+ block->type = sig.results;
+ return visitBlockStart(block, sig.params);
}
-Result<> IRBuilder::makeIf(Name label, Type type) {
+Result<> IRBuilder::makeIf(Name label, Signature sig) {
auto* iff = wasm.allocator.alloc<If>();
- iff->type = type;
- return visitIfStart(iff, label);
+ iff->type = sig.results;
+ return visitIfStart(iff, label, sig.params);
}
-Result<> IRBuilder::makeLoop(Name label, Type type) {
+Result<> IRBuilder::makeLoop(Name label, Signature sig) {
auto* loop = wasm.allocator.alloc<Loop>();
loop->name = label;
- loop->type = type;
- return visitLoopStart(loop);
+ loop->type = sig.results;
+ return visitLoopStart(loop, sig.params);
}
Result<> IRBuilder::makeBreak(Index label, bool isConditional) {
@@ -1584,19 +1633,19 @@ Result<> IRBuilder::makeTableInit(Name elem, Name table) {
return Ok{};
}
-Result<> IRBuilder::makeTry(Name label, Type type) {
+Result<> IRBuilder::makeTry(Name label, Signature sig) {
auto* tryy = wasm.allocator.alloc<Try>();
- tryy->type = type;
- return visitTryStart(tryy, label);
+ tryy->type = sig.results;
+ return visitTryStart(tryy, label, sig.params);
}
Result<> IRBuilder::makeTryTable(Name label,
- Type type,
+ Signature sig,
const std::vector<Name>& tags,
const std::vector<Index>& labels,
const std::vector<bool>& isRefs) {
auto* trytable = wasm.allocator.alloc<TryTable>();
- trytable->type = type;
+ trytable->type = sig.results;
trytable->catchTags.set(tags);
trytable->catchRefs.set(isRefs);
trytable->catchDests.reserve(labels.size());
@@ -1605,7 +1654,7 @@ Result<> IRBuilder::makeTryTable(Name label,
CHECK_ERR(name);
trytable->catchDests.push_back(*name);
}
- return visitTryTableStart(trytable, label);
+ return visitTryTableStart(trytable, label, sig.params);
}
Result<> IRBuilder::makeThrow(Name tag) {