summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)