diff options
-rw-r--r-- | src/passes/StringLowering.cpp | 12 | ||||
-rw-r--r-- | test/lit/passes/string-lowering-instructions.wast | 41 |
2 files changed, 47 insertions, 6 deletions
diff --git a/src/passes/StringLowering.cpp b/src/passes/StringLowering.cpp index a0002fcf6..85e75f705 100644 --- a/src/passes/StringLowering.cpp +++ b/src/passes/StringLowering.cpp @@ -35,6 +35,7 @@ #include "ir/module-utils.h" #include "ir/names.h" #include "ir/type-updating.h" +#include "ir/utils.h" #include "pass.h" #include "support/json.h" #include "wasm-builder.h" @@ -360,7 +361,13 @@ struct StringLowering : public StringGathering { void visitStringAs(StringAs* curr) { // There is no difference between strings and views with imported // strings: they are all just JS strings, so no conversion is needed. - replaceCurrent(curr->ref); + // However, we must keep the same nullability: the output of StringAs + // must be non-nullable. + auto* ref = curr->ref; + if (ref->type.isNullable()) { + ref = Builder(*getModule()).makeRefAs(RefAsNonNull, ref); + } + replaceCurrent(ref); } void visitStringEncode(StringEncode* curr) { @@ -468,6 +475,9 @@ struct StringLowering : public StringGathering { Replacer replacer(*this); replacer.run(getPassRunner(), module); replacer.walkModuleCode(module); + + // ReFinalize to apply changes to parents. + ReFinalize().run(getPassRunner(), module); } }; diff --git a/test/lit/passes/string-lowering-instructions.wast b/test/lit/passes/string-lowering-instructions.wast index 458cf4f91..6764f7a4c 100644 --- a/test/lit/passes/string-lowering-instructions.wast +++ b/test/lit/passes/string-lowering-instructions.wast @@ -49,7 +49,7 @@ ;; CHECK: (type $17 (func (param (ref $0)))) - ;; CHECK: (type $18 (func (param externref externref externref externref))) + ;; CHECK: (type $18 (func (param externref (ref extern) externref externref externref (ref extern)))) ;; CHECK: (type $19 (func (param (ref null $0) i32 i32) (result (ref extern)))) @@ -90,22 +90,38 @@ ;; CHECK: (export "export.2" (func $exported-string-receiver)) - ;; CHECK: (func $string.as (type $18) (param $a externref) (param $b externref) (param $c externref) (param $d externref) + ;; CHECK: (func $string.as (type $18) (param $a externref) (param $a_nn (ref extern)) (param $b externref) (param $c externref) (param $d externref) (param $nn_view (ref extern)) ;; CHECK-NEXT: (local.set $b - ;; CHECK-NEXT: (local.get $a) + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $a) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $c - ;; CHECK-NEXT: (local.get $a) + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $a) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $d - ;; CHECK-NEXT: (local.get $a) + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $a) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $nn_view + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (local.get $a) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $nn_view + ;; CHECK-NEXT: (local.get $a_nn) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $string.as (param $a stringref) + (param $a_nn (ref string)) (param $b stringview_wtf8) (param $c stringview_wtf16) (param $d stringview_iter) + (param $nn_view (ref stringview_wtf16)) ;; These operations all vanish in the lowering, as they all become extref ;; (JS strings). (local.set $b @@ -123,6 +139,21 @@ (local.get $a) ) ) + ;; The input is nullable, and string.as casts to non-null, so we will need + ;; to keep a cast here in order to validate. (We also add a cast in all the + ;; above as the inputs are nullable, but this is the only one that will + ;; fail to validate. Other opts can remove the above ones.) + (local.set $nn_view + (string.as_wtf16 + (local.get $a) + ) + ) + ;; The input is already non-nullable here, so no cast is needed. + (local.set $nn_view + (string.as_wtf16 + (local.get $a_nn) + ) + ) ) ;; CHECK: (func $string.new.gc (type $17) (param $array16 (ref $0)) |