summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/StringLowering.cpp12
-rw-r--r--test/lit/passes/string-lowering-instructions.wast41
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))