summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/type-updating.cpp7
-rw-r--r--src/ir/type-updating.h13
-rw-r--r--src/passes/StringLowering.cpp16
-rw-r--r--test/lit/passes/string-lowering-instructions.wast104
4 files changed, 104 insertions, 36 deletions
diff --git a/src/ir/type-updating.cpp b/src/ir/type-updating.cpp
index fb701f64a..12a8c7c36 100644
--- a/src/ir/type-updating.cpp
+++ b/src/ir/type-updating.cpp
@@ -30,7 +30,8 @@ GlobalTypeRewriter::GlobalTypeRewriter(Module& wasm) : wasm(wasm) {}
void GlobalTypeRewriter::update() { mapTypes(rebuildTypes()); }
-GlobalTypeRewriter::TypeMap GlobalTypeRewriter::rebuildTypes() {
+GlobalTypeRewriter::TypeMap GlobalTypeRewriter::rebuildTypes(
+ const std::vector<HeapType>& additionalPrivateTypes) {
// Find the heap types that are not publicly observable. Even in a closed
// world scenario, don't modify public types because we assume that they may
// be reflected on or used for linking. Figure out where each private type
@@ -39,6 +40,10 @@ GlobalTypeRewriter::TypeMap GlobalTypeRewriter::rebuildTypes() {
Index i = 0;
auto privateTypes = ModuleUtils::getPrivateHeapTypes(wasm);
+ for (auto t : additionalPrivateTypes) {
+ privateTypes.push_back(t);
+ }
+
// Topological sort to have supertypes first, but we have to account for the
// fact that we may be replacing the supertypes to get the order correct.
struct SupertypesFirst
diff --git a/src/ir/type-updating.h b/src/ir/type-updating.h
index ae247b6c7..1626b40bd 100644
--- a/src/ir/type-updating.h
+++ b/src/ir/type-updating.h
@@ -426,7 +426,12 @@ protected:
// Builds new types after updating their contents using the hooks below and
// returns a map from the old types to the modified types. Used internally in
// update().
- TypeMap rebuildTypes();
+ //
+ // This only operates on private types (so as not to modify the module's
+ // external ABI). It takes as a parameter a list of public types to consider
+ // private, which allows more flexibility.
+ TypeMap
+ rebuildTypes(const std::vector<HeapType>& additionalPrivateTypes = {});
private:
TypeBuilder typeBuilder;
@@ -446,10 +451,12 @@ public:
TypeMapper(Module& wasm, const TypeUpdates& mapping)
: GlobalTypeRewriter(wasm), mapping(mapping) {}
- void map() {
+ // As rebuildTypes, this can take an optional set of additional types to
+ // consider private (and therefore to modify).
+ void map(const std::vector<HeapType>& additionalPrivateTypes = {}) {
// Update the internals of types (struct fields, signatures, etc.) to
// refer to the merged types.
- auto newMapping = rebuildTypes();
+ auto newMapping = rebuildTypes(additionalPrivateTypes);
// Compose the user-provided mapping from old types to other old types with
// the new mapping from old types to new types. `newMapping` will become
diff --git a/src/passes/StringLowering.cpp b/src/passes/StringLowering.cpp
index bdecf648a..f9930d946 100644
--- a/src/passes/StringLowering.cpp
+++ b/src/passes/StringLowering.cpp
@@ -232,13 +232,27 @@ struct StringLowering : public StringGathering {
void updateTypes(Module* module) {
TypeMapper::TypeUpdates updates;
+
// There is no difference between strings and views with imported strings:
// they are all just JS strings, so they all turn into externref.
updates[HeapType::string] = HeapType::ext;
updates[HeapType::stringview_wtf8] = HeapType::ext;
updates[HeapType::stringview_wtf16] = HeapType::ext;
updates[HeapType::stringview_iter] = HeapType::ext;
- TypeMapper(*module, updates).map();
+
+ // We consider all types that use strings as modifiable, which means we
+ // mark them as non-private. That is, we are doing something TypeMapper
+ // normally does not, as we are changing the external interface/ABI of the
+ // module: we are changing that ABI from using strings to externs.
+ auto publicTypes = ModuleUtils::getPublicHeapTypes(*module);
+ std::vector<HeapType> stringUsers;
+ for (auto t : publicTypes) {
+ if (Type(t, Nullable).getFeatures().hasStrings()) {
+ stringUsers.push_back(t);
+ }
+ }
+
+ TypeMapper(*module, updates).map(stringUsers);
}
// Imported string functions.
diff --git a/test/lit/passes/string-lowering-instructions.wast b/test/lit/passes/string-lowering-instructions.wast
index 8d0094231..4ce2dee38 100644
--- a/test/lit/passes/string-lowering-instructions.wast
+++ b/test/lit/passes/string-lowering-instructions.wast
@@ -9,54 +9,62 @@
;; CHECK: (type $1 (func (param externref externref) (result i32)))
;; CHECK: (rec
- ;; CHECK-NEXT: (type $2 (func (param externref) (result externref)))
+ ;; CHECK-NEXT: (type $2 (func (param externref i32 externref)))
- ;; CHECK: (type $3 (func (param externref) (result i32)))
+ ;; CHECK: (type $3 (func (result externref)))
- ;; CHECK: (type $4 (func (param externref externref) (result i32)))
+ ;; CHECK: (type $4 (func (param externref) (result externref)))
- ;; CHECK: (type $5 (func (param externref (ref $array16)) (result i32)))
+ ;; CHECK: (type $5 (func (param externref) (result i32)))
- ;; CHECK: (type $6 (func (result externref)))
+ ;; CHECK: (type $6 (func (param externref externref) (result i32)))
- ;; CHECK: (type $7 (func (param (ref $array16))))
+ ;; CHECK: (type $7 (func (param externref (ref $array16)) (result i32)))
- ;; CHECK: (type $8 (func (param externref externref externref externref)))
+ ;; CHECK: (type $8 (func (param (ref $array16))))
- ;; CHECK: (type $9 (func))
+ ;; CHECK: (type $9 (func (param externref externref externref externref)))
- ;; CHECK: (type $10 (func (param (ref null $array16) i32 i32) (result (ref extern))))
+ ;; CHECK: (type $10 (func))
- ;; CHECK: (type $11 (func (param i32) (result (ref extern))))
+ ;; CHECK: (type $11 (func (param (ref null $array16) i32 i32) (result (ref extern))))
- ;; CHECK: (type $12 (func (param externref (ref null $array16) i32) (result i32)))
+ ;; CHECK: (type $12 (func (param i32) (result (ref extern))))
- ;; CHECK: (type $13 (func (param externref) (result i32)))
+ ;; CHECK: (type $13 (func (param externref (ref null $array16) i32) (result i32)))
- ;; CHECK: (type $14 (func (param externref i32) (result i32)))
+ ;; CHECK: (type $14 (func (param externref) (result i32)))
- ;; CHECK: (type $15 (func (param externref i32 i32) (result (ref extern))))
+ ;; CHECK: (type $15 (func (param externref i32) (result i32)))
- ;; CHECK: (import "colliding" "name" (func $fromCodePoint (type $9)))
+ ;; CHECK: (type $16 (func (param externref i32 i32) (result (ref extern))))
+
+ ;; CHECK: (import "string.const" "0" (global $string.const_exported (ref extern)))
+
+ ;; CHECK: (import "colliding" "name" (func $fromCodePoint (type $10)))
(import "colliding" "name" (func $fromCodePoint))
- ;; CHECK: (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $10) (param (ref null $array16) i32 i32) (result (ref extern))))
+ ;; CHECK: (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $11) (param (ref null $array16) i32 i32) (result (ref extern))))
- ;; CHECK: (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_11 (type $11) (param i32) (result (ref extern))))
+ ;; CHECK: (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_13 (type $12) (param i32) (result (ref extern))))
- ;; CHECK: (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $12) (param externref (ref null $array16) i32) (result i32)))
+ ;; CHECK: (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $13) (param externref (ref null $array16) i32) (result i32)))
;; CHECK: (import "wasm:js-string" "equals" (func $equals (type $1) (param externref externref) (result i32)))
;; CHECK: (import "wasm:js-string" "compare" (func $compare (type $1) (param externref externref) (result i32)))
- ;; CHECK: (import "wasm:js-string" "length" (func $length (type $13) (param externref) (result i32)))
+ ;; CHECK: (import "wasm:js-string" "length" (func $length (type $14) (param externref) (result i32)))
+
+ ;; CHECK: (import "wasm:js-string" "codePointAt" (func $codePointAt (type $15) (param externref i32) (result i32)))
- ;; CHECK: (import "wasm:js-string" "codePointAt" (func $codePointAt (type $14) (param externref i32) (result i32)))
+ ;; CHECK: (import "wasm:js-string" "substring" (func $substring (type $16) (param externref i32 i32) (result (ref extern))))
- ;; CHECK: (import "wasm:js-string" "substring" (func $substring (type $15) (param externref i32 i32) (result (ref extern))))
+ ;; CHECK: (export "export.1" (func $exported-string-returner))
- ;; CHECK: (func $string.as (type $8) (param $a externref) (param $b externref) (param $c externref) (param $d externref)
+ ;; CHECK: (export "export.2" (func $exported-string-receiver))
+
+ ;; CHECK: (func $string.as (type $9) (param $a externref) (param $b externref) (param $c externref) (param $d externref)
;; CHECK-NEXT: (local.set $b
;; CHECK-NEXT: (local.get $a)
;; CHECK-NEXT: )
@@ -91,7 +99,7 @@
)
)
- ;; CHECK: (func $string.new.gc (type $7) (param $array16 (ref $array16))
+ ;; CHECK: (func $string.new.gc (type $8) (param $array16 (ref $array16))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (call $fromCharCodeArray
;; CHECK-NEXT: (local.get $array16)
@@ -110,8 +118,8 @@
)
)
- ;; CHECK: (func $string.from_code_point (type $6) (result externref)
- ;; CHECK-NEXT: (call $fromCodePoint_11
+ ;; CHECK: (func $string.from_code_point (type $3) (result externref)
+ ;; CHECK-NEXT: (call $fromCodePoint_13
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
@@ -121,7 +129,7 @@
)
)
- ;; CHECK: (func $string.encode (type $5) (param $ref externref) (param $array16 (ref $array16)) (result i32)
+ ;; CHECK: (func $string.encode (type $7) (param $ref externref) (param $array16 (ref $array16)) (result i32)
;; CHECK-NEXT: (call $intoCharCodeArray
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: (local.get $array16)
@@ -136,7 +144,7 @@
)
)
- ;; CHECK: (func $string.eq (type $4) (param $a externref) (param $b externref) (result i32)
+ ;; CHECK: (func $string.eq (type $6) (param $a externref) (param $b externref) (result i32)
;; CHECK-NEXT: (call $equals
;; CHECK-NEXT: (local.get $a)
;; CHECK-NEXT: (local.get $b)
@@ -149,7 +157,7 @@
)
)
- ;; CHECK: (func $string.compare (type $4) (param $a externref) (param $b externref) (result i32)
+ ;; CHECK: (func $string.compare (type $6) (param $a externref) (param $b externref) (result i32)
;; CHECK-NEXT: (call $compare
;; CHECK-NEXT: (local.get $a)
;; CHECK-NEXT: (local.get $b)
@@ -162,7 +170,7 @@
)
)
- ;; CHECK: (func $string.length (type $3) (param $ref externref) (result i32)
+ ;; CHECK: (func $string.length (type $5) (param $ref externref) (result i32)
;; CHECK-NEXT: (call $length
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: )
@@ -173,7 +181,7 @@
)
)
- ;; CHECK: (func $string.get_codeunit (type $3) (param $ref externref) (result i32)
+ ;; CHECK: (func $string.get_codeunit (type $5) (param $ref externref) (result i32)
;; CHECK-NEXT: (call $codePointAt
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: (i32.const 2)
@@ -186,7 +194,7 @@
)
)
- ;; CHECK: (func $string.slice (type $2) (param $ref externref) (result externref)
+ ;; CHECK: (func $string.slice (type $4) (param $ref externref) (result externref)
;; CHECK-NEXT: (call $substring
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: (i32.const 2)
@@ -200,4 +208,38 @@
(i32.const 3)
)
)
+
+ ;; CHECK: (func $exported-string-returner (type $3) (result externref)
+ ;; CHECK-NEXT: (global.get $string.const_exported)
+ ;; CHECK-NEXT: )
+ (func $exported-string-returner (export "export.1") (result stringref)
+ ;; We should update the signature of this function even though it is public
+ ;; (exported).
+ (string.const "exported")
+ )
+
+ ;; CHECK: (func $exported-string-receiver (type $2) (param $x externref) (param $y i32) (param $z externref)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $z)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $exported-string-receiver (export "export.2") (param $x stringref) (param $y i32) (param $z stringref)
+ ;; We should update the signature of this function even though it is public
+ ;; (exported).
+ (drop
+ (local.get $x)
+ )
+ (drop
+ (local.get $y)
+ )
+ (drop
+ (local.get $z)
+ )
+ )
)