summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2023-10-18 20:37:48 +0200
committerGitHub <noreply@github.com>2023-10-18 18:37:48 +0000
commitf50e933f639c24f3a5814980fb20e6f7e1435184 (patch)
treec118bfbfbb54a5c0e1879af650131503ad59bd97
parent89c02aad305474aea1d413e110aadd68278a13d6 (diff)
downloadbinaryen-f50e933f639c24f3a5814980fb20e6f7e1435184.tar.gz
binaryen-f50e933f639c24f3a5814980fb20e6f7e1435184.tar.bz2
binaryen-f50e933f639c24f3a5814980fb20e6f7e1435184.zip
Reuse existing function types for blocks (#6022)
Type annotations on multivalue blocks (and loops, ifs, and trys) are type indices that refer to function types in the type section. For these type annotations, the identities of the function types does not matter. As long as the referenced type has the correct parameters and results, it will be valid to use. Previously, when collecting module types, we always used the "default" function type for multivalue control flow, i.e. we used a final function type with no supertypes in a singleton rec group. However, in cases where the program already contains another function type with the expected signature, using the default type is unnecessary and bloats the type section. Update the type collecting code to reuse existing function types for multivalue control flow where possible rather than unconditionally adding the default function type. Similarly, update the binary writer to use the first heap type with the required signature when emitting annotations on multivalue control flow structures. To make this all testable, update the printer to print the type annotations as well, rather than just the result types. Since the parser was not able to parse those newly emitted type annotations, update the parser as well.
-rw-r--r--src/ir/module-utils.cpp139
-rw-r--r--src/passes/Print.cpp35
-rw-r--r--src/wasm-binary.h2
-rw-r--r--src/wasm-s-parser.h2
-rw-r--r--src/wasm/wasm-binary.cpp16
-rw-r--r--src/wasm/wasm-s-parser.cpp44
-rw-r--r--src/wasm/wasm-stack.cpp2
-rw-r--r--test/lit/blocktype.wast99
-rw-r--r--test/lit/multivalue.wast14
-rw-r--r--test/lit/passes/coalesce-locals-gc.wast10
-rw-r--r--test/lit/passes/optimize-instructions-multivalue.wast2
-rw-r--r--test/lit/passes/poppify.wast2
-rw-r--r--test/lit/passes/remove-unused-brs.wast6
-rw-r--r--test/lit/passes/roundtrip.wast2
-rw-r--r--test/lit/passes/tuple-optimization.wast2
-rw-r--r--test/lit/passes/type-merging.wast6
-rw-r--r--test/lit/types-function-references.wast62
-rw-r--r--test/lit/wat-kitchen-sink.wast14
-rw-r--r--test/passes/remove-unused-brs_enable-multivalue.txt8
19 files changed, 337 insertions, 130 deletions
diff --git a/src/ir/module-utils.cpp b/src/ir/module-utils.cpp
index 0da47e811..cd865a79c 100644
--- a/src/ir/module-utils.cpp
+++ b/src/ir/module-utils.cpp
@@ -230,10 +230,18 @@ void renameFunction(Module& wasm, Name oldName, Name newName) {
namespace {
// Helper for collecting HeapTypes and their frequencies.
-struct Counts : public InsertOrderedMap<HeapType, size_t> {
+struct Counts {
+ InsertOrderedMap<HeapType, size_t> counts;
+
+ // Multivalue control flow structures need a function type, but the identity
+ // of the function type (i.e. what recursion group it is in or whether it is
+ // final) doesn't matter. Save them for the end to see if we can re-use an
+ // existing function type with the necessary signature.
+ InsertOrderedMap<Signature, size_t> controlFlowSignatures;
+
void note(HeapType type) {
if (!type.isBasic()) {
- (*this)[type]++;
+ counts[type]++;
}
}
void note(Type type) {
@@ -244,7 +252,7 @@ struct Counts : public InsertOrderedMap<HeapType, size_t> {
// Ensure a type is included without increasing its count.
void include(HeapType type) {
if (!type.isBasic()) {
- (*this)[type];
+ counts[type];
}
}
void include(Type type) {
@@ -252,6 +260,18 @@ struct Counts : public InsertOrderedMap<HeapType, size_t> {
include(ht);
}
}
+ void noteControlFlow(Signature sig) {
+ // TODO: support control flow input parameters.
+ assert(sig.params.size() == 0);
+ if (sig.results.isTuple()) {
+ // We have to use a function type.
+ controlFlowSignatures[sig]++;
+ } else if (sig.results != Type::none) {
+ // The result type can be emitted directly instead of using a function
+ // type.
+ note(sig.results[0]);
+ }
+ }
};
struct CodeScanner
@@ -319,12 +339,7 @@ struct CodeScanner
} else if (auto* set = curr->dynCast<ArraySet>()) {
counts.note(set->ref->type);
} else if (Properties::isControlFlowStructure(curr)) {
- if (curr->type.isTuple()) {
- // TODO: Allow control flow to have input types as well
- counts.note(Signature(Type::none, curr->type));
- } else {
- counts.note(curr->type);
- }
+ counts.noteControlFlow(Signature(Type::none, curr->type));
}
}
};
@@ -332,7 +347,8 @@ struct CodeScanner
// Count the number of times each heap type that would appear in the binary is
// referenced. If `prune`, exclude types that are never referenced, even though
// a binary would be invalid without them.
-Counts getHeapTypeCounts(Module& wasm, bool prune = false) {
+InsertOrderedMap<HeapType, size_t> getHeapTypeCounts(Module& wasm,
+ bool prune = false) {
// Collect module-level info.
Counts counts;
CodeScanner(wasm, counts).walkModuleCode(&wasm);
@@ -363,18 +379,21 @@ Counts getHeapTypeCounts(Module& wasm, bool prune = false) {
// Combine the function info with the module info.
for (auto& [_, functionCounts] : analysis.map) {
- for (auto& [sig, count] : functionCounts) {
- counts[sig] += count;
+ for (auto& [type, count] : functionCounts.counts) {
+ counts.counts[type] += count;
+ }
+ for (auto& [sig, count] : functionCounts.controlFlowSignatures) {
+ counts.controlFlowSignatures[sig] += count;
}
}
if (prune) {
// Remove types that are not actually used.
- auto it = counts.begin();
- while (it != counts.end()) {
+ auto it = counts.counts.begin();
+ while (it != counts.counts.end()) {
if (it->second == 0) {
auto deleted = it++;
- counts.erase(deleted);
+ counts.counts.erase(deleted);
} else {
++it;
}
@@ -388,50 +407,75 @@ Counts getHeapTypeCounts(Module& wasm, bool prune = false) {
// appear in the type section once, so we just need to visit it once. Also
// track which recursion groups we've already processed to avoid quadratic
// behavior when there is a single large group.
- InsertOrderedSet<HeapType> newTypes;
- for (auto& [type, _] : counts) {
- newTypes.insert(type);
+ UniqueNonrepeatingDeferredQueue<HeapType> newTypes;
+ std::unordered_map<Signature, HeapType> seenSigs;
+ auto noteNewType = [&](HeapType type) {
+ newTypes.push(type);
+ if (type.isSignature()) {
+ seenSigs.insert({type.getSignature(), type});
+ }
+ };
+ for (auto& [type, _] : counts.counts) {
+ noteNewType(type);
}
+ auto controlFlowIt = counts.controlFlowSignatures.begin();
std::unordered_set<RecGroup> includedGroups;
while (!newTypes.empty()) {
- auto iter = newTypes.begin();
- auto ht = *iter;
- newTypes.erase(iter);
- for (HeapType child : ht.getHeapTypeChildren()) {
- if (!child.isBasic()) {
- if (!counts.count(child)) {
- newTypes.insert(child);
+ while (!newTypes.empty()) {
+ auto ht = newTypes.pop();
+ for (HeapType child : ht.getHeapTypeChildren()) {
+ if (!child.isBasic()) {
+ if (!counts.counts.count(child)) {
+ noteNewType(child);
+ }
+ counts.note(child);
}
- counts.note(child);
}
- }
- if (auto super = ht.getDeclaredSuperType()) {
- if (!counts.count(*super)) {
- newTypes.insert(*super);
- // We should unconditionally count supertypes, but while the type system
- // is in flux, skip counting them to keep the type orderings in nominal
- // test outputs more similar to the orderings in the equirecursive
- // outputs. FIXME
- counts.include(*super);
+ if (auto super = ht.getDeclaredSuperType()) {
+ if (!counts.counts.count(*super)) {
+ noteNewType(*super);
+ // We should unconditionally count supertypes, but while the type
+ // system is in flux, skip counting them to keep the type orderings in
+ // nominal test outputs more similar to the orderings in the
+ // equirecursive outputs. FIXME
+ counts.include(*super);
+ }
}
- }
- // Make sure we've noted the complete recursion group of each type as well.
- if (!prune) {
- auto recGroup = ht.getRecGroup();
- if (includedGroups.insert(recGroup).second) {
- for (auto type : recGroup) {
- if (!counts.count(type)) {
- newTypes.insert(type);
- counts.include(type);
+ // Make sure we've noted the complete recursion group of each type as
+ // well.
+ if (!prune) {
+ auto recGroup = ht.getRecGroup();
+ if (includedGroups.insert(recGroup).second) {
+ for (auto type : recGroup) {
+ if (!counts.counts.count(type)) {
+ noteNewType(type);
+ counts.include(type);
+ }
}
}
}
}
+
+ // We've found all the types there are to find without considering more
+ // control flow types. Consider one more control flow type and repeat.
+ for (; controlFlowIt != counts.controlFlowSignatures.end();
+ ++controlFlowIt) {
+ auto& [sig, count] = *controlFlowIt;
+ if (auto it = seenSigs.find(sig); it != seenSigs.end()) {
+ counts.counts[it->second] += count;
+ } else {
+ // We've never seen this signature before, so add a type for it.
+ HeapType type(sig);
+ noteNewType(type);
+ counts.counts[type] += count;
+ break;
+ }
+ }
}
- return counts;
+ return counts.counts;
}
void setIndices(IndexedHeapTypes& indexedTypes) {
@@ -561,12 +605,11 @@ std::vector<HeapType> getPrivateHeapTypes(Module& wasm) {
}
IndexedHeapTypes getOptimizedIndexedHeapTypes(Module& wasm) {
- Counts counts = getHeapTypeCounts(wasm);
+ auto counts = getHeapTypeCounts(wasm);
// Types have to be arranged into topologically ordered recursion groups.
// Under isorecrsive typing, the topological sort has to take all referenced
- // rec groups into account but under nominal typing it only has to take
- // supertypes into account. First, sort the groups by average use count among
+ // rec groups into account. First, sort the groups by average use count among
// their members so that the later topological sort will place frequently used
// types first.
struct GroupInfo {
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index edbb136a3..51d261126 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -169,6 +169,7 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
int controlFlowDepth = 0;
std::vector<HeapType> heapTypes;
+ std::unordered_map<Signature, HeapType> signatureTypes;
// Track the print indent so that we can see when it changes. That affects how
// we print debug annotations. In particular, we don't want to print repeated
@@ -242,6 +243,22 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
return printPrefixedTypes("param", type);
}
+ std::ostream& printBlockType(Signature sig) {
+ assert(sig.params == Type::none);
+ if (sig.results == Type::none) {
+ return o;
+ }
+ if (sig.results.isTuple()) {
+ if (auto it = signatureTypes.find(sig); it != signatureTypes.end()) {
+ o << "(type ";
+ printHeapType(it->second);
+ o << ") ";
+ }
+ }
+ printResultType(sig.results);
+ return o;
+ }
+
void printDebugLocation(const Function::DebugLocation& location);
void printDebugLocation(Expression* curr);
@@ -370,6 +387,10 @@ struct PrintExpressionContents
return parent.printParamType(type);
}
+ std::ostream& printBlockType(Signature sig) {
+ return parent.printBlockType(sig);
+ }
+
void visitBlock(Block* curr) {
printMedium(o, "block");
if (curr->name.is()) {
@@ -378,14 +399,14 @@ struct PrintExpressionContents
}
if (curr->type.isConcrete()) {
o << ' ';
- printResultType(curr->type);
+ printBlockType(Signature(Type::none, curr->type));
}
}
void visitIf(If* curr) {
printMedium(o, "if");
if (curr->type.isConcrete()) {
o << ' ';
- printResultType(curr->type);
+ printBlockType(Signature(Type::none, curr->type));
}
}
void visitLoop(Loop* curr) {
@@ -396,7 +417,7 @@ struct PrintExpressionContents
}
if (curr->type.isConcrete()) {
o << ' ';
- printResultType(curr->type);
+ printBlockType(Signature(Type::none, curr->type));
}
}
void visitBreak(Break* curr) {
@@ -1937,7 +1958,7 @@ struct PrintExpressionContents
}
if (curr->type.isConcrete()) {
o << ' ';
- printResultType(curr->type);
+ printBlockType(Signature(Type::none, curr->type));
}
}
void visitThrow(Throw* curr) {
@@ -2369,8 +2390,14 @@ void PrintSExpression::setModule(Module* module) {
currModule = module;
if (module) {
heapTypes = ModuleUtils::getOptimizedIndexedHeapTypes(*module).types;
+ for (auto type : heapTypes) {
+ if (type.isSignature()) {
+ signatureTypes.insert({type.getSignature(), type});
+ }
+ }
} else {
heapTypes = {};
+ signatureTypes = {};
}
// Reset the type printer for this module's types (or absence thereof).
typePrinter.~TypePrinter();
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 8a4d6969f..ee92fe90e 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1422,6 +1422,7 @@ public:
uint32_t getDataSegmentIndex(Name name) const;
uint32_t getElementSegmentIndex(Name name) const;
uint32_t getTypeIndex(HeapType type) const;
+ uint32_t getSignatureIndex(Signature sig) const;
uint32_t getStringIndex(Name string) const;
void writeTableDeclarations();
@@ -1476,6 +1477,7 @@ private:
BufferWithRandomAccess& o;
BinaryIndexes indexes;
ModuleUtils::IndexedHeapTypes indexedTypes;
+ std::unordered_map<Signature, uint32_t> signatureIndexes;
bool debugInfo = true;
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index a2faea771..6853f2c01 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -327,7 +327,7 @@ private:
Expression* makeStringSliceIter(Element& s);
// Helper functions
- Type parseOptionalResultType(Element& s, Index& i);
+ Type parseBlockType(Element& s, Index& i);
Index parseMemoryLimits(Element& s, Index i, std::unique_ptr<Memory>& memory);
Index parseMemoryIndex(Element& s, Index i, std::unique_ptr<Memory>& memory);
Index parseMemoryForInstruction(const std::string& instrName,
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 2b96e839c..b12cb50c7 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -35,6 +35,11 @@ void WasmBinaryWriter::prepare() {
// Collect function types and their frequencies. Collect information in each
// function in parallel, then merge.
indexedTypes = ModuleUtils::getOptimizedIndexedHeapTypes(*wasm);
+ for (Index i = 0, size = indexedTypes.types.size(); i < size; ++i) {
+ if (indexedTypes.types[i].isSignature()) {
+ signatureIndexes.insert({indexedTypes.types[i].getSignature(), i});
+ }
+ }
importInfo = std::make_unique<ImportInfo>(*wasm);
}
@@ -686,6 +691,17 @@ uint32_t WasmBinaryWriter::getTypeIndex(HeapType type) const {
return it->second;
}
+uint32_t WasmBinaryWriter::getSignatureIndex(Signature sig) const {
+ auto it = signatureIndexes.find(sig);
+#ifndef NDEBUG
+ if (it == signatureIndexes.end()) {
+ std::cout << "Missing signature: " << sig << '\n';
+ assert(0);
+ }
+#endif
+ return it->second;
+}
+
uint32_t WasmBinaryWriter::getStringIndex(Name string) const {
auto it = stringIndexes.find(string);
assert(it != stringIndexes.end());
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 215d349e1..4074e4792 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -1445,7 +1445,7 @@ Expression* SExpressionWasmBuilder::makeUnary(Element& s, UnaryOp op) {
Expression* SExpressionWasmBuilder::makeSelect(Element& s) {
auto ret = allocator.alloc<Select>();
Index i = 1;
- Type type = parseOptionalResultType(s, i);
+ Type type = parseBlockType(s, i);
ret->ifTrue = parseExpression(s[i++]);
ret->ifFalse = parseExpression(s[i++]);
ret->condition = parseExpression(s[i]);
@@ -1603,7 +1603,7 @@ Expression* SExpressionWasmBuilder::makeBlock(Element& s) {
stack.emplace_back(Info{sp, curr, hadName});
curr->name = nameMapper.pushLabelName(sName);
// block signature
- curr->type = parseOptionalResultType(s, i);
+ curr->type = parseBlockType(s, i);
if (i >= s.size()) {
break; // empty block
}
@@ -1630,7 +1630,8 @@ Expression* SExpressionWasmBuilder::makeBlock(Element& s) {
while (i < s.size() && s[i]->isStr()) {
i++;
}
- if (i < s.size() && elementStartsWith(*s[i], RESULT)) {
+ while (i < s.size() && (elementStartsWith(*s[i], RESULT) ||
+ elementStartsWith(*s[i], TYPE))) {
i++;
}
if (t < int(stack.size()) - 1) {
@@ -2370,7 +2371,7 @@ Expression* SExpressionWasmBuilder::makeIf(Element& s) {
}
auto label = nameMapper.pushLabelName(sName);
// if signature
- Type type = parseOptionalResultType(s, i);
+ Type type = parseBlockType(s, i);
ret->condition = parseExpression(s[i++]);
ret->ifTrue = parseExpression(*s[i++]);
if (i < s.size()) {
@@ -2409,7 +2410,7 @@ SExpressionWasmBuilder::makeMaybeBlock(Element& s, size_t i, Type type) {
return ret;
}
-Type SExpressionWasmBuilder::parseOptionalResultType(Element& s, Index& i) {
+Type SExpressionWasmBuilder::parseBlockType(Element& s, Index& i) {
if (s.size() == i) {
return Type::none;
}
@@ -2420,11 +2421,34 @@ Type SExpressionWasmBuilder::parseOptionalResultType(Element& s, Index& i) {
return stringToType(s[i++]->str());
}
- Element& results = *s[i];
- IString id = results[0]->str();
+ Element* results = s[i];
+ IString id = (*results)[0]->str();
+ std::optional<Signature> usedType;
+ if (id == TYPE) {
+ auto type = parseHeapType(*(*results)[1]);
+ if (!type.isSignature()) {
+ throw SParseException("unexpected non-function type", s);
+ }
+ usedType = type.getSignature();
+ if (usedType->params != Type::none) {
+ throw SParseException("block input values are not yet supported", s);
+ }
+ i++;
+ results = s[i];
+ id = (*results)[0]->str();
+ }
+
if (id == RESULT) {
i++;
- return Type(parseResults(results));
+ auto type = Type(parseResults(*results));
+ if (usedType && usedType->results != type) {
+ throw SParseException("results do not match type", s);
+ }
+ return type;
+ }
+
+ if (usedType && usedType->results != Type::none) {
+ throw SParseException("results do not match type", s);
}
return Type::none;
}
@@ -2439,7 +2463,7 @@ Expression* SExpressionWasmBuilder::makeLoop(Element& s) {
sName = "loop-in";
}
ret->name = nameMapper.pushLabelName(sName);
- ret->type = parseOptionalResultType(s, i);
+ ret->type = parseBlockType(s, i);
ret->body = makeMaybeBlock(s, i, ret->type);
nameMapper.popLabelName(ret->name);
ret->finalize(ret->type);
@@ -2690,7 +2714,7 @@ Expression* SExpressionWasmBuilder::makeTry(Element& s) {
sName = "try";
}
ret->name = nameMapper.pushLabelName(sName);
- Type type = parseOptionalResultType(s, i); // signature
+ Type type = parseBlockType(s, i); // signature
if (!elementStartsWith(*s[i], "do")) {
throw SParseException("try body should start with 'do'", s, *s[i]);
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 1f1141821..1d2363be3 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -26,7 +26,7 @@ void BinaryInstWriter::emitResultType(Type type) {
if (type == Type::unreachable) {
parent.writeType(Type::none);
} else if (type.isTuple()) {
- o << S32LEB(parent.getTypeIndex(Signature(Type::none, type)));
+ o << S32LEB(parent.getSignatureIndex(Signature(Type::none, type)));
} else {
parent.writeType(type);
}
diff --git a/test/lit/blocktype.wast b/test/lit/blocktype.wast
new file mode 100644
index 000000000..61eba4868
--- /dev/null
+++ b/test/lit/blocktype.wast
@@ -0,0 +1,99 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+
+;; RUN: wasm-opt %s -all -S -o - | filecheck %s
+;; RUN: wasm-opt %s -all --roundtrip -g -S -o - | filecheck %s --check-prefix=RTRIP
+
+(module
+ (rec
+ ;; CHECK: (rec
+ ;; CHECK-NEXT: (type $f1 (func (result (ref $f1) (ref $f2))))
+ ;; RTRIP: (rec
+ ;; RTRIP-NEXT: (type $f1 (func (result (ref $f1) (ref $f2))))
+ (type $f1 (func (result (ref $f1) (ref $f2))))
+ ;; CHECK: (type $f2 (func (result (ref $f2) (ref $f1))))
+ ;; RTRIP: (type $f2 (func (result (ref $f2) (ref $f1))))
+ (type $f2 (func (result (ref $f2) (ref $f1))))
+ )
+
+ ;; These types will be optimized out.
+ (type $block1 (func (result (ref $f1) (ref $f2))))
+ (type $block2 (func (result (ref $f2) (ref $f1))))
+
+ ;; CHECK: (func $f1 (type $f1) (result (ref $f1) (ref $f2))
+ ;; CHECK-NEXT: (loop $l (type $f1) (result (ref $f1) (ref $f2))
+ ;; CHECK-NEXT: (call $f1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; RTRIP: (func $f1 (type $f1) (result (ref $f1) (ref $f2))
+ ;; RTRIP-NEXT: (local $0 ((ref $f1) (ref $f2)))
+ ;; RTRIP-NEXT: (local $1 ((ref $f1) (ref $f2)))
+ ;; RTRIP-NEXT: (local.set $1
+ ;; RTRIP-NEXT: (loop $label$1 (type $f1) (result (ref $f1) (ref $f2))
+ ;; RTRIP-NEXT: (local.set $0
+ ;; RTRIP-NEXT: (call $f1)
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: (tuple.make
+ ;; RTRIP-NEXT: (tuple.extract 0
+ ;; RTRIP-NEXT: (local.get $0)
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: (tuple.extract 1
+ ;; RTRIP-NEXT: (local.get $0)
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: (tuple.make
+ ;; RTRIP-NEXT: (tuple.extract 0
+ ;; RTRIP-NEXT: (local.get $1)
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: (tuple.extract 1
+ ;; RTRIP-NEXT: (local.get $1)
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: )
+ (func $f1 (type $f1) (result (ref $f1) (ref $f2))
+ ;; This block will be emitted with type $f1
+ (loop $l (type $block1) (result (ref $f1) (ref $f2))
+ (call $f1)
+ )
+ )
+
+ ;; CHECK: (func $f2 (type $f2) (result (ref $f2) (ref $f1))
+ ;; CHECK-NEXT: (loop $l (type $f2) (result (ref $f2) (ref $f1))
+ ;; CHECK-NEXT: (call $f2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; RTRIP: (func $f2 (type $f2) (result (ref $f2) (ref $f1))
+ ;; RTRIP-NEXT: (local $0 ((ref $f2) (ref $f1)))
+ ;; RTRIP-NEXT: (local $1 ((ref $f2) (ref $f1)))
+ ;; RTRIP-NEXT: (local.set $1
+ ;; RTRIP-NEXT: (loop $label$1 (type $f2) (result (ref $f2) (ref $f1))
+ ;; RTRIP-NEXT: (local.set $0
+ ;; RTRIP-NEXT: (call $f2)
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: (tuple.make
+ ;; RTRIP-NEXT: (tuple.extract 0
+ ;; RTRIP-NEXT: (local.get $0)
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: (tuple.extract 1
+ ;; RTRIP-NEXT: (local.get $0)
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: (tuple.make
+ ;; RTRIP-NEXT: (tuple.extract 0
+ ;; RTRIP-NEXT: (local.get $1)
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: (tuple.extract 1
+ ;; RTRIP-NEXT: (local.get $1)
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: )
+ ;; RTRIP-NEXT: )
+ (func $f2 (type $f2) (result (ref $f2) (ref $f1))
+ ;; This block will be emitted with type $f2
+ (loop $l (type $block2) (result (ref $f2) (ref $f1))
+ (call $f2)
+ )
+ )
+)
diff --git a/test/lit/multivalue.wast b/test/lit/multivalue.wast
index 0d52f5382..a4b5c6b7e 100644
--- a/test/lit/multivalue.wast
+++ b/test/lit/multivalue.wast
@@ -320,7 +320,7 @@
;; CHECK-NEXT: (local $0 (i32 i64))
;; CHECK-NEXT: (local $1 i32)
;; CHECK-NEXT: (local.set $0
- ;; CHECK-NEXT: (block $label$1 (result i32 i64)
+ ;; CHECK-NEXT: (block $label$1 (type $0) (result i32 i64)
;; CHECK-NEXT: (tuple.make
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: (i64.const 42)
@@ -394,7 +394,7 @@
;; CHECK: (func $mv-block-break (type $0) (result i32 i64)
;; CHECK-NEXT: (local $0 (i32 i64))
;; CHECK-NEXT: (local.set $0
- ;; CHECK-NEXT: (block $label$1 (result i32 i64)
+ ;; CHECK-NEXT: (block $label$1 (type $0) (result i32 i64)
;; CHECK-NEXT: (br $label$1
;; CHECK-NEXT: (tuple.make
;; CHECK-NEXT: (i32.const 42)
@@ -427,7 +427,7 @@
;; CHECK-NEXT: (local $0 (i32 i64))
;; CHECK-NEXT: (local $1 (i32 i64))
;; CHECK-NEXT: (local.set $1
- ;; CHECK-NEXT: (block $label$1 (result i32 i64)
+ ;; CHECK-NEXT: (block $label$1 (type $0) (result i32 i64)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (br_if $label$1
;; CHECK-NEXT: (tuple.make
@@ -471,7 +471,7 @@
;; CHECK: (func $mv-if (type $2) (result i32 i64 externref)
;; CHECK-NEXT: (local $0 (i32 i64 externref))
;; CHECK-NEXT: (local.set $0
- ;; CHECK-NEXT: (if (result i32 i64 externref)
+ ;; CHECK-NEXT: (if (type $2) (result i32 i64 externref)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (tuple.make
;; CHECK-NEXT: (i32.const 42)
@@ -516,7 +516,7 @@
;; CHECK: (func $mv-loop (type $0) (result i32 i64)
;; CHECK-NEXT: (local $0 (i32 i64))
;; CHECK-NEXT: (local.set $0
- ;; CHECK-NEXT: (loop $label$1 (result i32 i64)
+ ;; CHECK-NEXT: (loop $label$1 (type $0) (result i32 i64)
;; CHECK-NEXT: (tuple.make
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: (i64.const 42)
@@ -545,9 +545,9 @@
;; CHECK-NEXT: (local $0 (i32 i64))
;; CHECK-NEXT: (local $1 (i32 i64))
;; CHECK-NEXT: (local.set $1
- ;; CHECK-NEXT: (block $label$1 (result i32 i64)
+ ;; CHECK-NEXT: (block $label$1 (type $0) (result i32 i64)
;; CHECK-NEXT: (local.set $0
- ;; CHECK-NEXT: (block $label$2 (result i32 i64)
+ ;; CHECK-NEXT: (block $label$2 (type $0) (result i32 i64)
;; CHECK-NEXT: (br_table $label$1 $label$2
;; CHECK-NEXT: (tuple.make
;; CHECK-NEXT: (i32.const 42)
diff --git a/test/lit/passes/coalesce-locals-gc.wast b/test/lit/passes/coalesce-locals-gc.wast
index 3706dc61f..5122fc23b 100644
--- a/test/lit/passes/coalesce-locals-gc.wast
+++ b/test/lit/passes/coalesce-locals-gc.wast
@@ -79,7 +79,7 @@
)
)
- ;; CHECK: (func $nn-dead (type $2)
+ ;; CHECK: (func $nn-dead (type $3)
;; CHECK-NEXT: (local $0 funcref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.func $nn-dead)
@@ -118,7 +118,7 @@
)
)
- ;; CHECK: (func $nn-dead-nameless (type $2)
+ ;; CHECK: (func $nn-dead-nameless (type $3)
;; CHECK-NEXT: (local $0 (ref func))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.func $nn-dead)
@@ -149,7 +149,7 @@
)
)
- ;; CHECK: (func $unreachable-get-null (type $2)
+ ;; CHECK: (func $unreachable-get-null (type $3)
;; CHECK-NEXT: (local $0 anyref)
;; CHECK-NEXT: (local $1 i31ref)
;; CHECK-NEXT: (unreachable)
@@ -307,9 +307,9 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (global.set $nn-tuple-global
- ;; CHECK-NEXT: (block (result (ref any) i32)
+ ;; CHECK-NEXT: (block (type $1) (result (ref any) i32)
;; CHECK-NEXT: (local.set $1
- ;; CHECK-NEXT: (if (result (ref any) i32)
+ ;; CHECK-NEXT: (if (type $1) (result (ref any) i32)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (tuple.make
;; CHECK-NEXT: (ref.as_non_null
diff --git a/test/lit/passes/optimize-instructions-multivalue.wast b/test/lit/passes/optimize-instructions-multivalue.wast
index 0e7938417..1e456f20f 100644
--- a/test/lit/passes/optimize-instructions-multivalue.wast
+++ b/test/lit/passes/optimize-instructions-multivalue.wast
@@ -6,7 +6,7 @@
;; CHECK-NEXT: (local $tuple (i32 i32))
;; CHECK-NEXT: (local $tuple2 (i32 i32))
;; CHECK-NEXT: (tuple.extract 0
- ;; CHECK-NEXT: (if (result i32 i32)
+ ;; CHECK-NEXT: (if (type $2) (result i32 i32)
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (local.get $tuple)
;; CHECK-NEXT: (local.get $tuple2)
diff --git a/test/lit/passes/poppify.wast b/test/lit/passes/poppify.wast
index 9432cbd28..4aa44a3d5 100644
--- a/test/lit/passes/poppify.wast
+++ b/test/lit/passes/poppify.wast
@@ -466,7 +466,7 @@
)
;; CHECK: (func $break-tuple (type $1) (result i32 i64)
- ;; CHECK-NEXT: (block $l (result i32 i64)
+ ;; CHECK-NEXT: (block $l (type $1) (result i32 i64)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (i64.const 1)
;; CHECK-NEXT: (br $l
diff --git a/test/lit/passes/remove-unused-brs.wast b/test/lit/passes/remove-unused-brs.wast
index 93cf4cbd2..8392dfe86 100644
--- a/test/lit/passes/remove-unused-brs.wast
+++ b/test/lit/passes/remove-unused-brs.wast
@@ -5,7 +5,7 @@
(module
;; Regression test in which we need to calculate a proper LUB.
- ;; CHECK: (func $selectify-fresh-lub (type $2) (param $x i32) (result anyref)
+ ;; CHECK: (func $selectify-fresh-lub (type $3) (param $x i32) (result anyref)
;; CHECK-NEXT: (select (result i31ref)
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: (ref.i31
@@ -211,7 +211,7 @@
)
)
- ;; CHECK: (func $get-i32 (type $3) (result i32)
+ ;; CHECK: (func $get-i32 (type $4) (result i32)
;; CHECK-NEXT: (i32.const 400)
;; CHECK-NEXT: )
(func $get-i32 (result i32)
@@ -327,7 +327,7 @@
;; CHECK: (func $restructure-select-no-multivalue (type $1)
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (block $block (result i32 i32)
+ ;; CHECK-NEXT: (block $block (type $2) (result i32 i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (br_if $block
;; CHECK-NEXT: (tuple.make
diff --git a/test/lit/passes/roundtrip.wast b/test/lit/passes/roundtrip.wast
index f41761c2e..2f3fd4009 100644
--- a/test/lit/passes/roundtrip.wast
+++ b/test/lit/passes/roundtrip.wast
@@ -8,7 +8,7 @@
;; CHECK-NEXT: (local $0 (funcref (ref $none)))
;; CHECK-NEXT: (local $1 funcref)
;; CHECK-NEXT: (local.set $0
- ;; CHECK-NEXT: (block $label$1 (result funcref (ref $none))
+ ;; CHECK-NEXT: (block $label$1 (type $1) (result funcref (ref $none))
;; CHECK-NEXT: (tuple.make
;; CHECK-NEXT: (ref.null nofunc)
;; CHECK-NEXT: (ref.func $foo)
diff --git a/test/lit/passes/tuple-optimization.wast b/test/lit/passes/tuple-optimization.wast
index 766f51e81..6884f95c5 100644
--- a/test/lit/passes/tuple-optimization.wast
+++ b/test/lit/passes/tuple-optimization.wast
@@ -546,7 +546,7 @@
;; CHECK: (func $set-of-block (type $0)
;; CHECK-NEXT: (local $tuple (i32 i32))
;; CHECK-NEXT: (local.set $tuple
- ;; CHECK-NEXT: (block (result i32 i32)
+ ;; CHECK-NEXT: (block (type $1) (result i32 i32)
;; CHECK-NEXT: (tuple.make
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: (i32.const 2)
diff --git a/test/lit/passes/type-merging.wast b/test/lit/passes/type-merging.wast
index 7c44fe8e2..34f156a2b 100644
--- a/test/lit/passes/type-merging.wast
+++ b/test/lit/passes/type-merging.wast
@@ -929,8 +929,6 @@
;; CHECK: (rec
;; CHECK-NEXT: (type $B (sub (func)))
- ;; CHECK: (type $1 (func (result (ref any) (ref $B))))
-
;; CHECK: (type $A (sub (func (result (ref any) (ref $B)))))
(type $A (sub (func (result (ref any) (ref $C)))))
(type $B (sub (func)))
@@ -939,10 +937,8 @@
(type $D (sub final $A (func (result (ref any) (ref $C)))))
)
- ;; CHECK: (type $4 (func (result (ref any) (ref $B))))
-
;; CHECK: (func $test (type $D) (result (ref any) (ref $B))
- ;; CHECK-NEXT: (block $l (result (ref any) (ref $B))
+ ;; CHECK-NEXT: (block $l (type $A) (result (ref any) (ref $B))
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
diff --git a/test/lit/types-function-references.wast b/test/lit/types-function-references.wast
index c5f250f34..9479c93b3 100644
--- a/test/lit/types-function-references.wast
+++ b/test/lit/types-function-references.wast
@@ -22,22 +22,26 @@
(type $_=>_eqref (func (result eqref)))
;; CHECK-BINARY: (type $i32-i32 (func (param i32) (result i32)))
- ;; CHECK-BINARY: (type $3 (func (param (ref $i32-i32)) (result i32)))
+ ;; CHECK-BINARY: (type $3 (func (result i32 (ref null $mixed_results) f64)))
- ;; CHECK-BINARY: (type $4 (func (param (ref null $i32-i32)) (result i32)))
+ ;; CHECK-BINARY: (type $4 (func (param (ref $i32-i32)) (result i32)))
- ;; CHECK-BINARY: (type $5 (func (result i32)))
+ ;; CHECK-BINARY: (type $5 (func (param (ref null $i32-i32)) (result i32)))
+
+ ;; CHECK-BINARY: (type $6 (func (result i32)))
;; CHECK-BINARY: (type $=>eqref (func (result eqref)))
;; CHECK-BINARY: (type $f64_=>_ref_null<_->_eqref> (func (param f64) (result (ref null $=>eqref))))
;; CHECK-TEXT: (type $i32-i32 (func (param i32) (result i32)))
- ;; CHECK-TEXT: (type $3 (func (param (ref $i32-i32)) (result i32)))
+ ;; CHECK-TEXT: (type $3 (func (result i32 (ref null $mixed_results) f64)))
+
+ ;; CHECK-TEXT: (type $4 (func (param (ref $i32-i32)) (result i32)))
- ;; CHECK-TEXT: (type $4 (func (param (ref null $i32-i32)) (result i32)))
+ ;; CHECK-TEXT: (type $5 (func (param (ref null $i32-i32)) (result i32)))
- ;; CHECK-TEXT: (type $5 (func (result i32)))
+ ;; CHECK-TEXT: (type $6 (func (result i32)))
;; CHECK-TEXT: (type $=>eqref (func (result eqref)))
@@ -51,8 +55,6 @@
(type $i32-i32 (func (param i32) (result i32)))
- ;; CHECK-BINARY: (type $9 (func (result i32 (ref null $mixed_results) f64)))
-
;; CHECK-BINARY: (type $10 (func (param (ref null $mixed_results))))
;; CHECK-BINARY: (elem declare func $call-ref $call-ref-more)
@@ -62,8 +64,6 @@
;; CHECK-BINARY-NEXT: (ref.func $call-ref)
;; CHECK-BINARY-NEXT: )
;; CHECK-BINARY-NEXT: )
- ;; CHECK-TEXT: (type $9 (func (result i32 (ref null $mixed_results) f64)))
-
;; CHECK-TEXT: (type $10 (func (param (ref null $mixed_results))))
;; CHECK-TEXT: (elem declare func $call-ref $call-ref-more)
@@ -104,13 +104,13 @@
(func $call-ref-more (param i32) (result i32)
(call_ref $i32-i32 (i32.const 42) (ref.func $call-ref-more))
)
- ;; CHECK-BINARY: (func $call_from-param (type $3) (param $f (ref $i32-i32)) (result i32)
+ ;; CHECK-BINARY: (func $call_from-param (type $4) (param $f (ref $i32-i32)) (result i32)
;; CHECK-BINARY-NEXT: (call_ref $i32-i32
;; CHECK-BINARY-NEXT: (i32.const 42)
;; CHECK-BINARY-NEXT: (local.get $f)
;; CHECK-BINARY-NEXT: )
;; CHECK-BINARY-NEXT: )
- ;; CHECK-TEXT: (func $call_from-param (type $3) (param $f (ref $i32-i32)) (result i32)
+ ;; CHECK-TEXT: (func $call_from-param (type $4) (param $f (ref $i32-i32)) (result i32)
;; CHECK-TEXT-NEXT: (call_ref $i32-i32
;; CHECK-TEXT-NEXT: (i32.const 42)
;; CHECK-TEXT-NEXT: (local.get $f)
@@ -119,13 +119,13 @@
(func $call_from-param (param $f (ref $i32-i32)) (result i32)
(call_ref $i32-i32 (i32.const 42) (local.get $f))
)
- ;; CHECK-BINARY: (func $call_from-param-null (type $4) (param $f (ref null $i32-i32)) (result i32)
+ ;; CHECK-BINARY: (func $call_from-param-null (type $5) (param $f (ref null $i32-i32)) (result i32)
;; CHECK-BINARY-NEXT: (call_ref $i32-i32
;; CHECK-BINARY-NEXT: (i32.const 42)
;; CHECK-BINARY-NEXT: (local.get $f)
;; CHECK-BINARY-NEXT: )
;; CHECK-BINARY-NEXT: )
- ;; CHECK-TEXT: (func $call_from-param-null (type $4) (param $f (ref null $i32-i32)) (result i32)
+ ;; CHECK-TEXT: (func $call_from-param-null (type $5) (param $f (ref null $i32-i32)) (result i32)
;; CHECK-TEXT-NEXT: (call_ref $i32-i32
;; CHECK-TEXT-NEXT: (i32.const 42)
;; CHECK-TEXT-NEXT: (local.get $f)
@@ -134,7 +134,7 @@
(func $call_from-param-null (param $f (ref null $i32-i32)) (result i32)
(call_ref $i32-i32 (i32.const 42) (local.get $f))
)
- ;; CHECK-BINARY: (func $call_from-local-null (type $5) (result i32)
+ ;; CHECK-BINARY: (func $call_from-local-null (type $6) (result i32)
;; CHECK-BINARY-NEXT: (local $f (ref null $i32-i32))
;; CHECK-BINARY-NEXT: (local.set $f
;; CHECK-BINARY-NEXT: (ref.func $call-ref-more)
@@ -144,7 +144,7 @@
;; CHECK-BINARY-NEXT: (local.get $f)
;; CHECK-BINARY-NEXT: )
;; CHECK-BINARY-NEXT: )
- ;; CHECK-TEXT: (func $call_from-local-null (type $5) (result i32)
+ ;; CHECK-TEXT: (func $call_from-local-null (type $6) (result i32)
;; CHECK-TEXT-NEXT: (local $f (ref null $i32-i32))
;; CHECK-TEXT-NEXT: (local.set $f
;; CHECK-TEXT-NEXT: (ref.func $call-ref-more)
@@ -188,7 +188,7 @@
;; CHECK-BINARY-NEXT: (local $1 (ref null $mixed_results))
;; CHECK-BINARY-NEXT: (local $2 i32)
;; CHECK-BINARY-NEXT: (local.set $0
- ;; CHECK-BINARY-NEXT: (block $label$1 (result i32 (ref null $mixed_results) f64)
+ ;; CHECK-BINARY-NEXT: (block $label$1 (type $3) (result i32 (ref null $mixed_results) f64)
;; CHECK-BINARY-NEXT: (unreachable)
;; CHECK-BINARY-NEXT: )
;; CHECK-BINARY-NEXT: )
@@ -223,7 +223,7 @@
;; CHECK-TEXT-NEXT: (local $1 (ref null $mixed_results))
;; CHECK-TEXT-NEXT: (local $2 i32)
;; CHECK-TEXT-NEXT: (local.set $0
- ;; CHECK-TEXT-NEXT: (block $label$1 (result i32 (ref null $mixed_results) f64)
+ ;; CHECK-TEXT-NEXT: (block $label$1 (type $3) (result i32 (ref null $mixed_results) f64)
;; CHECK-TEXT-NEXT: (unreachable)
;; CHECK-TEXT-NEXT: )
;; CHECK-TEXT-NEXT: )
@@ -380,19 +380,19 @@
;; CHECK-NODEBUG: (type $2 (func (param i32) (result i32)))
-;; CHECK-NODEBUG: (type $3 (func (param (ref $2)) (result i32)))
+;; CHECK-NODEBUG: (type $3 (func (result i32 (ref null $0) f64)))
-;; CHECK-NODEBUG: (type $4 (func (param (ref null $2)) (result i32)))
+;; CHECK-NODEBUG: (type $4 (func (param (ref $2)) (result i32)))
-;; CHECK-NODEBUG: (type $5 (func (result i32)))
+;; CHECK-NODEBUG: (type $5 (func (param (ref null $2)) (result i32)))
-;; CHECK-NODEBUG: (type $6 (func (result eqref)))
+;; CHECK-NODEBUG: (type $6 (func (result i32)))
-;; CHECK-NODEBUG: (type $7 (func (param f64) (result (ref null $6))))
+;; CHECK-NODEBUG: (type $7 (func (result eqref)))
-;; CHECK-NODEBUG: (type $8 (func (result anyref)))
+;; CHECK-NODEBUG: (type $8 (func (param f64) (result (ref null $7))))
-;; CHECK-NODEBUG: (type $9 (func (result i32 (ref null $0) f64)))
+;; CHECK-NODEBUG: (type $9 (func (result anyref)))
;; CHECK-NODEBUG: (type $10 (func (param (ref null $0))))
@@ -417,21 +417,21 @@
;; CHECK-NODEBUG-NEXT: )
;; CHECK-NODEBUG-NEXT: )
-;; CHECK-NODEBUG: (func $3 (type $3) (param $0 (ref $2)) (result i32)
+;; CHECK-NODEBUG: (func $3 (type $4) (param $0 (ref $2)) (result i32)
;; CHECK-NODEBUG-NEXT: (call_ref $2
;; CHECK-NODEBUG-NEXT: (i32.const 42)
;; CHECK-NODEBUG-NEXT: (local.get $0)
;; CHECK-NODEBUG-NEXT: )
;; CHECK-NODEBUG-NEXT: )
-;; CHECK-NODEBUG: (func $4 (type $4) (param $0 (ref null $2)) (result i32)
+;; CHECK-NODEBUG: (func $4 (type $5) (param $0 (ref null $2)) (result i32)
;; CHECK-NODEBUG-NEXT: (call_ref $2
;; CHECK-NODEBUG-NEXT: (i32.const 42)
;; CHECK-NODEBUG-NEXT: (local.get $0)
;; CHECK-NODEBUG-NEXT: )
;; CHECK-NODEBUG-NEXT: )
-;; CHECK-NODEBUG: (func $5 (type $5) (result i32)
+;; CHECK-NODEBUG: (func $5 (type $6) (result i32)
;; CHECK-NODEBUG-NEXT: (local $0 (ref null $2))
;; CHECK-NODEBUG-NEXT: (local.set $0
;; CHECK-NODEBUG-NEXT: (ref.func $2)
@@ -442,14 +442,14 @@
;; CHECK-NODEBUG-NEXT: )
;; CHECK-NODEBUG-NEXT: )
-;; CHECK-NODEBUG: (func $6 (type $7) (param $0 f64) (result (ref null $6))
+;; CHECK-NODEBUG: (func $6 (type $8) (param $0 f64) (result (ref null $7))
;; CHECK-NODEBUG-NEXT: (ref.null nofunc)
;; CHECK-NODEBUG-NEXT: )
;; CHECK-NODEBUG: (func $7 (type $1)
;; CHECK-NODEBUG-NEXT: (local $0 i32)
;; CHECK-NODEBUG-NEXT: (local $1 f64)
-;; CHECK-NODEBUG-NEXT: (local $2 (ref null $8))
+;; CHECK-NODEBUG-NEXT: (local $2 (ref null $9))
;; CHECK-NODEBUG-NEXT: (nop)
;; CHECK-NODEBUG-NEXT: )
@@ -458,7 +458,7 @@
;; CHECK-NODEBUG-NEXT: (local $1 (ref null $0))
;; CHECK-NODEBUG-NEXT: (local $2 i32)
;; CHECK-NODEBUG-NEXT: (local.set $0
-;; CHECK-NODEBUG-NEXT: (block $label$1 (result i32 (ref null $0) f64)
+;; CHECK-NODEBUG-NEXT: (block $label$1 (type $3) (result i32 (ref null $0) f64)
;; CHECK-NODEBUG-NEXT: (unreachable)
;; CHECK-NODEBUG-NEXT: )
;; CHECK-NODEBUG-NEXT: )
diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast
index 8ef4f8d07..6b86d3e15 100644
--- a/test/lit/wat-kitchen-sink.wast
+++ b/test/lit/wat-kitchen-sink.wast
@@ -738,7 +738,7 @@
;; CHECK: (func $block-folded (type $void)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (block $l (result i32 i32)
+ ;; CHECK-NEXT: (block $l (type $ret2) (result i32 i32)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (unreachable)
@@ -766,7 +766,7 @@
;; CHECK-NEXT: (local.set $scratch_2
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (local.set $scratch_1
- ;; CHECK-NEXT: (block $1 (result i32 i32)
+ ;; CHECK-NEXT: (block $1 (type $ret2) (result i32 i32)
;; CHECK-NEXT: (tuple.make
;; CHECK-NEXT: (block $2 (result i32)
;; CHECK-NEXT: (local.set $scratch
@@ -819,8 +819,8 @@
;; CHECK-NEXT: (local $scratch (i32 i32))
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: (local.set $scratch
- ;; CHECK-NEXT: (block (result i32 i32)
- ;; CHECK-NEXT: (block (result i32 i32)
+ ;; CHECK-NEXT: (block (type $ret2) (result i32 i32)
+ ;; CHECK-NEXT: (block (type $ret2) (result i32 i32)
;; CHECK-NEXT: (tuple.make
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (i32.const 1)
@@ -1566,7 +1566,7 @@
)
;; CHECK: (func $br-multivalue (type $7) (result i32 i64)
- ;; CHECK-NEXT: (block $label (result i32 i64)
+ ;; CHECK-NEXT: (block $label (type $7) (result i32 i64)
;; CHECK-NEXT: (br $label
;; CHECK-NEXT: (tuple.make
;; CHECK-NEXT: (i32.const 0)
@@ -1582,8 +1582,8 @@
)
;; CHECK: (func $br-multivalue-drop (type $7) (result i32 i64)
- ;; CHECK-NEXT: (block $label (result i32 i64)
- ;; CHECK-NEXT: (block (result i32 i64)
+ ;; CHECK-NEXT: (block $label (type $7) (result i32 i64)
+ ;; CHECK-NEXT: (block (type $7) (result i32 i64)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (f32.const 0)
;; CHECK-NEXT: )
diff --git a/test/passes/remove-unused-brs_enable-multivalue.txt b/test/passes/remove-unused-brs_enable-multivalue.txt
index 0a66153e9..b85f1df8c 100644
--- a/test/passes/remove-unused-brs_enable-multivalue.txt
+++ b/test/passes/remove-unused-brs_enable-multivalue.txt
@@ -193,17 +193,17 @@
)
)
(func $b14-tuple (result i32 i64)
- (if (result i32 i64)
+ (if (type $5) (result i32 i64)
(i32.const 1)
- (block $topmost (result i32 i64)
- (block $block1 (result i32 i64)
+ (block $topmost (type $5) (result i32 i64)
+ (block $block1 (type $5) (result i32 i64)
(tuple.make
(i32.const 12)
(i64.const 12)
)
)
)
- (block $block3 (result i32 i64)
+ (block $block3 (type $5) (result i32 i64)
(tuple.make
(i32.const 27)
(i64.const 27)