diff options
-rw-r--r-- | src/passes/TypeMerging.cpp | 29 | ||||
-rw-r--r-- | test/lit/passes/type-merging.wast | 41 |
2 files changed, 55 insertions, 15 deletions
diff --git a/src/passes/TypeMerging.cpp b/src/passes/TypeMerging.cpp index 94a198adf..0fc766f4e 100644 --- a/src/passes/TypeMerging.cpp +++ b/src/passes/TypeMerging.cpp @@ -149,22 +149,21 @@ struct TypeMerging : public Pass { continue; } - // TODO: arrays - if (!type.isStruct()) { - continue; - } - - auto& fields = type.getStruct().fields; - auto& superFields = super->getStruct().fields; - if (fields != superFields) { - // This adds a field, or refines one, so it differs from the super, and - // we cannot merge it with the super. - continue; + if (type.isStruct()) { + auto& fields = type.getStruct().fields; + auto& superFields = super->getStruct().fields; + if (fields == superFields) { + // We can merge! This is identical structurally to the super, and also + // not distinguishable nominally. + merges[type] = *super; + } + } else if (type.isArray()) { + auto element = type.getArray().element; + auto superElement = super->getArray().element; + if (element == superElement) { + merges[type] = *super; + } } - - // We can merge! This is identical structurally to the super, and also not - // distinguishable nominally. - merges[type] = *super; } if (merges.empty()) { diff --git a/test/lit/passes/type-merging.wast b/test/lit/passes/type-merging.wast index 4df8d7e88..f28cf0e1d 100644 --- a/test/lit/passes/type-merging.wast +++ b/test/lit/passes/type-merging.wast @@ -235,3 +235,44 @@ ) ) ) + +;; Arrays +(module + ;; CHECK: (type $none_=>_none (func)) + + ;; CHECK: (type $intarray (array (mut i32))) + (type $intarray (array (mut i32))) + (type $sub-intarray (array_subtype (mut i32) $intarray)) + + ;; CHECK: (type $refarray (array anyref)) + (type $refarray (array (ref null any))) + (type $sub-refarray (array_subtype (ref null any) $refarray)) + ;; CHECK: (type $sub-refarray-nn (array_subtype (ref any) $refarray)) + (type $sub-refarray-nn (array_subtype (ref any) $refarray)) + + ;; CHECK: (func $foo (type $none_=>_none) + ;; CHECK-NEXT: (local $a (ref null $intarray)) + ;; CHECK-NEXT: (local $b (ref null $intarray)) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $foo + ;; $A will remain the same. + (local $a (ref null $intarray)) + ;; $B can be merged into $A. + (local $b (ref null $sub-intarray)) + ) + + ;; CHECK: (func $bar (type $none_=>_none) + ;; CHECK-NEXT: (local $a (ref null $refarray)) + ;; CHECK-NEXT: (local $b (ref null $refarray)) + ;; CHECK-NEXT: (local $c (ref null $sub-refarray-nn)) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $bar + (local $a (ref null $refarray)) + ;; $B can be merged into $A. + (local $b (ref null $sub-refarray)) + ;; $C cannot be merged as the element type is more refined. + (local $c (ref null $sub-refarray-nn)) + ) +) |