summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/flat.h7
-rw-r--r--src/ir/module-utils.h18
-rw-r--r--src/ir/properties.h5
-rw-r--r--src/passes/Flatten.cpp4
-rw-r--r--src/wasm/wasm-type.cpp13
-rw-r--r--test/multivalue.wast6
-rw-r--r--test/multivalue.wast.from-wast8
-rw-r--r--test/multivalue.wast.fromBinary13
-rw-r--r--test/multivalue.wast.fromBinary.noDebugInfo13
9 files changed, 62 insertions, 25 deletions
diff --git a/src/ir/flat.h b/src/ir/flat.h
index 01a94a759..d54d4771f 100644
--- a/src/ir/flat.h
+++ b/src/ir/flat.h
@@ -64,17 +64,12 @@ namespace wasm {
namespace Flat {
-inline bool isControlFlowStructure(Expression* curr) {
- return curr->is<Block>() || curr->is<If>() || curr->is<Loop>() ||
- curr->is<Try>();
-}
-
inline void verifyFlatness(Function* func) {
struct VerifyFlatness
: public PostWalker<VerifyFlatness,
UnifiedExpressionVisitor<VerifyFlatness>> {
void visitExpression(Expression* curr) {
- if (isControlFlowStructure(curr)) {
+ if (Properties::isControlFlowStructure(curr)) {
verify(!curr->type.isConcrete(),
"control flow structures must not flow values");
} else if (curr->is<LocalSet>()) {
diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h
index 0e18266e8..be924f742 100644
--- a/src/ir/module-utils.h
+++ b/src/ir/module-utils.h
@@ -19,6 +19,7 @@
#include "ir/find_all.h"
#include "ir/manipulation.h"
+#include "ir/properties.h"
#include "pass.h"
#include "support/unique_deferring_queue.h"
#include "wasm.h"
@@ -435,16 +436,19 @@ collectSignatures(Module& wasm,
if (func->imported()) {
return;
}
- struct TypeCounter : PostWalker<TypeCounter> {
+ struct TypeCounter
+ : PostWalker<TypeCounter, UnifiedExpressionVisitor<TypeCounter>> {
Counts& counts;
TypeCounter(Counts& counts) : counts(counts) {}
-
- void visitCallIndirect(CallIndirect* curr) { counts[curr->sig]++; }
- void visitBlock(Block* curr) {
- // TODO: Allow blocks to have input types as well
- if (curr->type.isMulti()) {
- counts[Signature(Type::none, curr->type)]++;
+ void visitExpression(Expression* curr) {
+ if (auto* call = curr->dynCast<CallIndirect>()) {
+ counts[call->sig]++;
+ } else if (Properties::isControlFlowStructure(curr)) {
+ // TODO: Allow control flow to have input types as well
+ if (curr->type.isMulti()) {
+ counts[Signature(Type::none, curr->type)]++;
+ }
}
}
};
diff --git a/src/ir/properties.h b/src/ir/properties.h
index b4dfbbd5e..094d90bd6 100644
--- a/src/ir/properties.h
+++ b/src/ir/properties.h
@@ -59,6 +59,11 @@ inline bool isSymmetric(Binary* binary) {
}
}
+inline bool isControlFlowStructure(Expression* curr) {
+ return curr->is<Block>() || curr->is<If>() || curr->is<Loop>() ||
+ curr->is<Try>();
+}
+
// Check if an expression is a control flow construct with a name,
// which implies it may have breaks to it.
inline bool isNamedControlFlow(Expression* curr) {
diff --git a/src/passes/Flatten.cpp b/src/passes/Flatten.cpp
index 13aa985aa..0a6a7022a 100644
--- a/src/passes/Flatten.cpp
+++ b/src/passes/Flatten.cpp
@@ -68,7 +68,7 @@ struct Flatten
return;
}
- if (Flat::isControlFlowStructure(curr)) {
+ if (Properties::isControlFlowStructure(curr)) {
// handle control flow explicitly. our children do not have control flow,
// but they do have preludes which we need to set up in the right place
@@ -291,7 +291,7 @@ struct Flatten
// next, finish up: migrate our preludes if we can
if (!ourPreludes.empty()) {
auto* parent = getParent();
- if (parent && !Flat::isControlFlowStructure(parent)) {
+ if (parent && !Properties::isControlFlowStructure(parent)) {
auto& parentPreludes = preludes[parent];
for (auto* prelude : ourPreludes) {
parentPreludes.push_back(prelude);
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index 148b55716..024894dfb 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -237,6 +237,19 @@ bool Type::isSubType(Type left, Type right) {
(right == Type::anyref || left == Type::nullref)) {
return true;
}
+ if (left.isMulti() && right.isMulti()) {
+ const auto& leftElems = left.expand();
+ const auto& rightElems = right.expand();
+ if (leftElems.size() != rightElems.size()) {
+ return false;
+ }
+ for (size_t i = 0; i < leftElems.size(); ++i) {
+ if (!isSubType(leftElems[i], rightElems[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
return false;
}
diff --git a/test/multivalue.wast b/test/multivalue.wast
index d2deaef89..08e23f62a 100644
--- a/test/multivalue.wast
+++ b/test/multivalue.wast
@@ -116,16 +116,18 @@
)
)
)
- (func $mv-if (result i32 i64)
- (if (result i32 i64)
+ (func $mv-if (result i32 i64 anyref)
+ (if (result i32 i64 nullref)
(i32.const 1)
(tuple.make
(i32.const 42)
(i64.const 42)
+ (ref.null)
)
(tuple.make
(i32.const 42)
(i64.const 42)
+ (ref.null)
)
)
)
diff --git a/test/multivalue.wast.from-wast b/test/multivalue.wast.from-wast
index 293ec8cb0..a918979f5 100644
--- a/test/multivalue.wast.from-wast
+++ b/test/multivalue.wast.from-wast
@@ -5,6 +5,8 @@
(type $none_=>_f32_i64_i32 (func (result f32 i64 i32)))
(type $none_=>_i32 (func (result i32)))
(type $none_=>_i32_i64_f32 (func (result i32 i64 f32)))
+ (type $none_=>_i32_i64_anyref (func (result i32 i64 anyref)))
+ (type $none_=>_i32_i64_nullref (func (result i32 i64 nullref)))
(type $none_=>_f32 (func (result f32)))
(import "env" "pair" (func $pair (result i32 i64)))
(func $triple (; 1 ;) (result i32 i64 f32)
@@ -117,16 +119,18 @@
)
)
)
- (func $mv-if (; 14 ;) (result i32 i64)
- (if (result i32 i64)
+ (func $mv-if (; 14 ;) (result i32 i64 anyref)
+ (if (result i32 i64 nullref)
(i32.const 1)
(tuple.make
(i32.const 42)
(i64.const 42)
+ (ref.null)
)
(tuple.make
(i32.const 42)
(i64.const 42)
+ (ref.null)
)
)
)
diff --git a/test/multivalue.wast.fromBinary b/test/multivalue.wast.fromBinary
index 9bd9d5e58..32f744c46 100644
--- a/test/multivalue.wast.fromBinary
+++ b/test/multivalue.wast.fromBinary
@@ -1,10 +1,12 @@
(module
(type $none_=>_i32_i64 (func (result i32 i64)))
(type $none_=>_none (func))
+ (type $none_=>_i32_i64_anyref (func (result i32 i64 anyref)))
(type $none_=>_i64 (func (result i64)))
(type $none_=>_f32_i64_i32 (func (result f32 i64 i32)))
(type $none_=>_i32 (func (result i32)))
(type $none_=>_i32_i64_f32 (func (result i32 i64 f32)))
+ (type $none_=>_i32_i64_nullref (func (result i32 i64 nullref)))
(type $none_=>_f32 (func (result f32)))
(import "env" "pair" (func $pair (result i32 i64)))
(func $triple (; 1 ;) (result i32 i64 f32)
@@ -366,18 +368,20 @@
)
)
)
- (func $mv-if (; 14 ;) (result i32 i64)
- (local $0 (i32 i64))
+ (func $mv-if (; 14 ;) (result i32 i64 anyref)
+ (local $0 (i32 i64 nullref))
(local.set $0
- (if (result i32 i64)
+ (if (result i32 i64 nullref)
(i32.const 1)
(tuple.make
(i32.const 42)
(i64.const 42)
+ (ref.null)
)
(tuple.make
(i32.const 42)
(i64.const 42)
+ (ref.null)
)
)
)
@@ -388,6 +392,9 @@
(tuple.extract 1
(local.get $0)
)
+ (tuple.extract 2
+ (local.get $0)
+ )
)
)
(func $mv-loop (; 15 ;) (result i32 i64)
diff --git a/test/multivalue.wast.fromBinary.noDebugInfo b/test/multivalue.wast.fromBinary.noDebugInfo
index 71d0939ba..c105df989 100644
--- a/test/multivalue.wast.fromBinary.noDebugInfo
+++ b/test/multivalue.wast.fromBinary.noDebugInfo
@@ -1,10 +1,12 @@
(module
(type $none_=>_i32_i64 (func (result i32 i64)))
(type $none_=>_none (func))
+ (type $none_=>_i32_i64_anyref (func (result i32 i64 anyref)))
(type $none_=>_i64 (func (result i64)))
(type $none_=>_f32_i64_i32 (func (result f32 i64 i32)))
(type $none_=>_i32 (func (result i32)))
(type $none_=>_i32_i64_f32 (func (result i32 i64 f32)))
+ (type $none_=>_i32_i64_nullref (func (result i32 i64 nullref)))
(type $none_=>_f32 (func (result f32)))
(import "env" "pair" (func $fimport$0 (result i32 i64)))
(func $0 (; 1 ;) (result i32 i64 f32)
@@ -366,18 +368,20 @@
)
)
)
- (func $13 (; 14 ;) (result i32 i64)
- (local $0 (i32 i64))
+ (func $13 (; 14 ;) (result i32 i64 anyref)
+ (local $0 (i32 i64 nullref))
(local.set $0
- (if (result i32 i64)
+ (if (result i32 i64 nullref)
(i32.const 1)
(tuple.make
(i32.const 42)
(i64.const 42)
+ (ref.null)
)
(tuple.make
(i32.const 42)
(i64.const 42)
+ (ref.null)
)
)
)
@@ -388,6 +392,9 @@
(tuple.extract 1
(local.get $0)
)
+ (tuple.extract 2
+ (local.get $0)
+ )
)
)
(func $14 (; 15 ;) (result i32 i64)