diff options
-rw-r--r-- | src/ir/flat.h | 7 | ||||
-rw-r--r-- | src/ir/module-utils.h | 18 | ||||
-rw-r--r-- | src/ir/properties.h | 5 | ||||
-rw-r--r-- | src/passes/Flatten.cpp | 4 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 13 | ||||
-rw-r--r-- | test/multivalue.wast | 6 | ||||
-rw-r--r-- | test/multivalue.wast.from-wast | 8 | ||||
-rw-r--r-- | test/multivalue.wast.fromBinary | 13 | ||||
-rw-r--r-- | test/multivalue.wast.fromBinary.noDebugInfo | 13 |
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) |