Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/passes/StringLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
};

Expand Down
41 changes: 36 additions & 5 deletions test/lit/passes/string-lowering-instructions.wast
Original file line number Diff line number Diff line change
Expand Up @@ -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))))

Expand Down Expand Up @@ -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
Expand All @@ -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))
Expand Down