shared string builtins
diff --git a/src/passes/StringLifting.cpp b/src/passes/StringLifting.cpp
index 7b8f456..6858c1b 100644
--- a/src/passes/StringLifting.cpp
+++ b/src/passes/StringLifting.cpp
@@ -50,6 +50,18 @@
   Name charCodeAtImport;
   Name substringImport;
 
+  // Shared imported string functions.
+  Name fromCharCodeArraySharedImport;
+  Name intoCharCodeArraySharedImport;
+  Name fromCodePointSharedImport;
+  Name concatSharedImport;
+  Name equalsSharedImport;
+  Name testSharedImport;
+  Name compareSharedImport;
+  Name lengthSharedImport;
+  Name charCodeAtSharedImport;
+  Name substringSharedImport;
+
   void run(Module* module) override {
     // Whether we found any work to do.
     bool found = false;
@@ -121,79 +133,137 @@
       module->customSections.erase(stringSectionIter);
     }
 
-    auto array16 = Type(Array(Field(Field::i16, Mutable)), Nullable);
+    auto array16 = Type(HeapTypes::getMutI16Array(), Nullable);
     auto refExtern = Type(HeapType::ext, NonNullable);
     auto externref = Type(HeapType::ext, Nullable);
     auto i32 = Type::i32;
 
+    auto sharedArray16 = Type(HeapTypes::getSharedMutI16Array(), Nullable);
+    auto refSharedExtern =
+      Type(HeapType(HeapType::ext).getBasic(Shared), NonNullable);
+    auto sharedExternref =
+      Type(HeapType(HeapType::ext).getBasic(Shared), Nullable);
+
     // Find imported string functions.
     for (auto& func : module->functions) {
       if (!func->imported() || func->module != WasmStringsModule) {
         continue;
       }
-      // TODO: Check exactness here too.
       auto type = func->type;
       if (func->base == "fromCharCodeArray") {
-        if (type.getHeapType() != Signature({array16, i32, i32}, refExtern)) {
+        if (type.getHeapType() == Signature(Type({array16, i32, i32}), refExtern)) {
+          fromCharCodeArrayImport = func->name;
+          found = true;
+        } else if (type.getHeapType() ==
+                   Signature(Type({sharedArray16, i32, i32}), refSharedExtern)) {
+          fromCharCodeArraySharedImport = func->name;
+          found = true;
+        } else {
           Fatal() << "StringLifting: bad type for fromCharCodeArray: " << type;
         }
-        fromCharCodeArrayImport = func->name;
-        found = true;
       } else if (func->base == "fromCodePoint") {
-        if (type.getHeapType() != Signature(i32, refExtern)) {
+        if (type.getHeapType() == Signature(i32, refExtern)) {
+          fromCodePointImport = func->name;
+          found = true;
+        } else if (type.getHeapType() == Signature(i32, refSharedExtern)) {
+          fromCodePointSharedImport = func->name;
+          found = true;
+        } else {
           Fatal() << "StringLifting: bad type for fromCodePoint: " << type;
         }
-        fromCodePointImport = func->name;
-        found = true;
       } else if (func->base == "concat") {
-        if (type.getHeapType() !=
-            Signature({externref, externref}, refExtern)) {
+        if (type.getHeapType() ==
+            Signature(Type({externref, externref}), refExtern)) {
+          concatImport = func->name;
+          found = true;
+        } else if (type.getHeapType() == Signature(Type({sharedExternref,
+                                                         sharedExternref}),
+                                                   refSharedExtern)) {
+          concatSharedImport = func->name;
+          found = true;
+        } else {
           Fatal() << "StringLifting: bad type for concat: " << type;
         }
-        concatImport = func->name;
-        found = true;
       } else if (func->base == "intoCharCodeArray") {
-        if (type.getHeapType() != Signature({externref, array16, i32}, i32)) {
+        if (type.getHeapType() == Signature(Type({externref, array16, i32}), i32)) {
+          intoCharCodeArrayImport = func->name;
+          found = true;
+        } else if (type.getHeapType() == Signature(Type({sharedExternref,
+                                                         sharedArray16,
+                                                         i32}),
+                                                   i32)) {
+          intoCharCodeArraySharedImport = func->name;
+          found = true;
+        } else {
           Fatal() << "StringLifting: bad type for intoCharCodeArray: " << type;
         }
-        intoCharCodeArrayImport = func->name;
-        found = true;
       } else if (func->base == "equals") {
-        if (type.getHeapType() != Signature({externref, externref}, i32)) {
+        if (type.getHeapType() == Signature(Type({externref, externref}), i32)) {
+          equalsImport = func->name;
+          found = true;
+        } else if (type.getHeapType() == Signature(Type({sharedExternref,
+                                                         sharedExternref}),
+                                                   i32)) {
+          equalsSharedImport = func->name;
+          found = true;
+        } else {
           Fatal() << "StringLifting: bad type for equals: " << type;
         }
-        equalsImport = func->name;
-        found = true;
       } else if (func->base == "test") {
-        if (type.getHeapType() != Signature({externref}, i32)) {
+        if (type.getHeapType() == Signature(Type({externref}), i32)) {
+          testImport = func->name;
+          found = true;
+        } else if (type.getHeapType() == Signature(Type({sharedExternref}), i32)) {
+          testSharedImport = func->name;
+          found = true;
+        } else {
           Fatal() << "StringLifting: bad type for test: " << type;
         }
-        testImport = func->name;
-        found = true;
       } else if (func->base == "compare") {
-        if (type.getHeapType() != Signature({externref, externref}, i32)) {
+        if (type.getHeapType() == Signature(Type({externref, externref}), i32)) {
+          compareImport = func->name;
+          found = true;
+        } else if (type.getHeapType() == Signature(Type({sharedExternref,
+                                                         sharedExternref}),
+                                                   i32)) {
+          compareSharedImport = func->name;
+          found = true;
+        } else {
           Fatal() << "StringLifting: bad type for compare: " << type;
         }
-        compareImport = func->name;
-        found = true;
       } else if (func->base == "length") {
-        if (type.getHeapType() != Signature({externref}, i32)) {
+        if (type.getHeapType() == Signature(Type({externref}), i32)) {
+          lengthImport = func->name;
+          found = true;
+        } else if (type.getHeapType() == Signature(Type({sharedExternref}), i32)) {
+          lengthSharedImport = func->name;
+          found = true;
+        } else {
           Fatal() << "StringLifting: bad type for length: " << type;
         }
-        lengthImport = func->name;
-        found = true;
       } else if (func->base == "charCodeAt") {
-        if (type.getHeapType() != Signature({externref, i32}, i32)) {
+        if (type.getHeapType() == Signature(Type({externref, i32}), i32)) {
+          charCodeAtImport = func->name;
+          found = true;
+        } else if (type.getHeapType() == Signature(Type({sharedExternref, i32}), i32)) {
+          charCodeAtSharedImport = func->name;
+          found = true;
+        } else {
           Fatal() << "StringLifting: bad type for charCodeAt: " << type;
         }
-        charCodeAtImport = func->name;
-        found = true;
       } else if (func->base == "substring") {
-        if (type.getHeapType() != Signature({externref, i32, i32}, refExtern)) {
+        if (type.getHeapType() == Signature(Type({externref, i32, i32}), refExtern)) {
+          substringImport = func->name;
+          found = true;
+        } else if (type.getHeapType() == Signature(Type({sharedExternref,
+                                                         i32,
+                                                         i32}),
+                                                   refSharedExtern)) {
+          substringSharedImport = func->name;
+          found = true;
+        } else {
           Fatal() << "StringLifting: bad type for substring: " << type;
         }
-        substringImport = func->name;
-        found = true;
       } else {
         std::cerr << "warning: unknown strings import: " << func->base << '\n';
       }
@@ -228,53 +298,54 @@
       }
 
       void visitCall(Call* curr) {
+        Builder builder(*getModule());
         // Replace calls of imported string methods with stringref operations.
-        if (curr->target == parent.fromCharCodeArrayImport) {
-          replaceCurrent(Builder(*getModule())
-                           .makeStringNew(StringNewWTF16Array,
-                                          curr->operands[0],
-                                          curr->operands[1],
-                                          curr->operands[2]));
-        } else if (curr->target == parent.fromCodePointImport) {
-          replaceCurrent(
-            Builder(*getModule())
-              .makeStringNew(StringNewFromCodePoint, curr->operands[0]));
-        } else if (curr->target == parent.concatImport) {
-          replaceCurrent(
-            Builder(*getModule())
-              .makeStringConcat(curr->operands[0], curr->operands[1]));
-        } else if (curr->target == parent.intoCharCodeArrayImport) {
-          replaceCurrent(Builder(*getModule())
-                           .makeStringEncode(StringEncodeWTF16Array,
-                                             curr->operands[0],
-                                             curr->operands[1],
-                                             curr->operands[2]));
-        } else if (curr->target == parent.equalsImport) {
-          replaceCurrent(Builder(*getModule())
-                           .makeStringEq(StringEqEqual,
-                                         curr->operands[0],
-                                         curr->operands[1]));
-        } else if (curr->target == parent.testImport) {
-          replaceCurrent(
-            Builder(*getModule()).makeStringTest(curr->operands[0]));
-        } else if (curr->target == parent.compareImport) {
-          replaceCurrent(Builder(*getModule())
-                           .makeStringEq(StringEqCompare,
-                                         curr->operands[0],
-                                         curr->operands[1]));
-        } else if (curr->target == parent.lengthImport) {
-          replaceCurrent(
-            Builder(*getModule())
-              .makeStringMeasure(StringMeasureWTF16, curr->operands[0]));
-        } else if (curr->target == parent.charCodeAtImport) {
-          replaceCurrent(
-            Builder(*getModule())
-              .makeStringWTF16Get(curr->operands[0], curr->operands[1]));
-        } else if (curr->target == parent.substringImport) {
-          replaceCurrent(Builder(*getModule())
-                           .makeStringSliceWTF(curr->operands[0],
+        if (curr->target == parent.fromCharCodeArrayImport ||
+            curr->target == parent.fromCharCodeArraySharedImport) {
+          replaceCurrent(builder.makeStringNew(StringNewWTF16Array,
+                                               curr->operands[0],
                                                curr->operands[1],
                                                curr->operands[2]));
+        } else if (curr->target == parent.fromCodePointImport ||
+                   curr->target == parent.fromCodePointSharedImport) {
+          replaceCurrent(builder.makeStringNew(StringNewFromCodePoint,
+                                               curr->operands[0]));
+        } else if (curr->target == parent.concatImport ||
+                   curr->target == parent.concatSharedImport) {
+          replaceCurrent(builder.makeStringConcat(curr->operands[0],
+                                                  curr->operands[1]));
+        } else if (curr->target == parent.intoCharCodeArrayImport ||
+                   curr->target == parent.intoCharCodeArraySharedImport) {
+          replaceCurrent(builder.makeStringEncode(StringEncodeWTF16Array,
+                                                  curr->operands[0],
+                                                  curr->operands[1],
+                                                  curr->operands[2]));
+        } else if (curr->target == parent.equalsImport ||
+                   curr->target == parent.equalsSharedImport) {
+          replaceCurrent(builder.makeStringEq(StringEqEqual,
+                                              curr->operands[0],
+                                              curr->operands[1]));
+        } else if (curr->target == parent.testImport ||
+                   curr->target == parent.testSharedImport) {
+          replaceCurrent(builder.makeStringTest(curr->operands[0]));
+        } else if (curr->target == parent.compareImport ||
+                   curr->target == parent.compareSharedImport) {
+          replaceCurrent(builder.makeStringEq(StringEqCompare,
+                                              curr->operands[0],
+                                              curr->operands[1]));
+        } else if (curr->target == parent.lengthImport ||
+                   curr->target == parent.lengthSharedImport) {
+          replaceCurrent(builder.makeStringMeasure(StringMeasureWTF16,
+                                                   curr->operands[0]));
+        } else if (curr->target == parent.charCodeAtImport ||
+                   curr->target == parent.charCodeAtSharedImport) {
+          replaceCurrent(builder.makeStringWTF16Get(curr->operands[0],
+                                                    curr->operands[1]));
+        } else if (curr->target == parent.substringImport ||
+                   curr->target == parent.substringSharedImport) {
+          replaceCurrent(builder.makeStringSliceWTF(curr->operands[0],
+                                                    curr->operands[1],
+                                                    curr->operands[2]));
         }
       }
 
diff --git a/src/passes/StringLowering.cpp b/src/passes/StringLowering.cpp
index cf2efad..2e6f842 100644
--- a/src/passes/StringLowering.cpp
+++ b/src/passes/StringLowering.cpp
@@ -106,6 +106,8 @@
   std::unordered_map<Name, Name> stringToGlobalName;
 
   Type nnstringref = Type(HeapType::string, NonNullable);
+  Type nnsharedstringref =
+    Type(HeapType(HeapType::string).getBasic(Shared), NonNullable);
 
   // Existing globals already in the form we emit can be reused. That is, if
   // we see
@@ -208,6 +210,8 @@
     : useMagicImports(useMagicImports), assertUTF8(assertUTF8) {
     // If we are asserting valid UTF-8, we must be using magic imports.
     assert(!assertUTF8 || useMagicImports);
+
+    nullSharedArray16 = Type(HeapTypes::getSharedMutI16Array(), Nullable);
   }
 
   void run(Module* module) override {
@@ -287,6 +291,11 @@
   Type nullExt = Type(HeapType::ext, Nullable);
   Type nnExt = Type(HeapType::ext, NonNullable);
 
+  Type nullSharedArray16;
+  Type nullSharedExt = Type(HeapType(HeapType::ext).getBasic(Shared), Nullable);
+  Type nnSharedExt =
+    Type(HeapType(HeapType::ext).getBasic(Shared), NonNullable);
+
   void updateTypes(Module* module) {
     TypeMapper::TypeUpdates updates;
 
@@ -336,6 +345,8 @@
 
     // Strings turn into externref.
     updates[HeapType::string] = HeapType::ext;
+    updates[HeapType(HeapType::string).getBasic(Shared)] =
+      HeapType(HeapType::ext).getBasic(Shared);
 
     TypeMapper(*module, updates).map();
   }
@@ -352,6 +363,18 @@
   Name charCodeAtImport;
   Name substringImport;
 
+  // Shared imported string functions.
+  Name fromCharCodeArraySharedImport;
+  Name intoCharCodeArraySharedImport;
+  Name fromCodePointSharedImport;
+  Name concatSharedImport;
+  Name equalsSharedImport;
+  Name testSharedImport;
+  Name compareSharedImport;
+  Name lengthSharedImport;
+  Name charCodeAtSharedImport;
+  Name substringSharedImport;
+
   // Creates an imported string function, returning its name (which is equal to
   // the true name of the import, if there is no conflict).
   Name addImport(Module* module, Name trueName, Type params, Type results) {
@@ -396,6 +419,30 @@
     substringImport =
       addImport(module, "substring", {nullExt, Type::i32, Type::i32}, nnExt);
 
+    // Shared imports
+
+    fromCharCodeArraySharedImport = addImport(
+      module, "fromCharCodeArray", {nullSharedArray16, Type::i32, Type::i32}, nnSharedExt);
+    fromCodePointSharedImport =
+      addImport(module, "fromCodePoint", Type::i32, nnSharedExt);
+    concatSharedImport =
+      addImport(module, "concat", {nullSharedExt, nullSharedExt}, nnSharedExt);
+    intoCharCodeArraySharedImport = addImport(module,
+                                              "intoCharCodeArray",
+                                              {nullSharedExt, nullSharedArray16, Type::i32},
+                                              Type::i32);
+    equalsSharedImport =
+      addImport(module, "equals", {nullSharedExt, nullSharedExt}, Type::i32);
+    testSharedImport = addImport(module, "test", {nullSharedExt}, Type::i32);
+    compareSharedImport =
+      addImport(module, "compare", {nullSharedExt, nullSharedExt}, Type::i32);
+    lengthSharedImport =
+      addImport(module, "length", nullSharedExt, Type::i32);
+    charCodeAtSharedImport =
+      addImport(module, "charCodeAt", {nullSharedExt, Type::i32}, Type::i32);
+    substringSharedImport = addImport(
+      module, "substring", {nullSharedExt, Type::i32, Type::i32}, nnSharedExt);
+
     // Replace the string instructions in parallel.
     struct Replacer : public WalkerPass<PostWalker<Replacer>> {
       bool isFunctionParallel() override { return true; }
@@ -410,15 +457,23 @@
 
       void visitStringNew(StringNew* curr) {
         Builder builder(*getModule());
+        bool shared = curr->type.getHeapType().isShared();
+        auto& fromCharCodeArrayImport =
+          shared ? lowering.fromCharCodeArraySharedImport
+                 : lowering.fromCharCodeArrayImport;
+        auto& fromCodePointImport =
+          shared ? lowering.fromCodePointSharedImport : lowering.fromCodePointImport;
+        auto nnExt = shared ? lowering.nnSharedExt : lowering.nnExt;
+
         switch (curr->op) {
           case StringNewWTF16Array:
-            replaceCurrent(builder.makeCall(lowering.fromCharCodeArrayImport,
+            replaceCurrent(builder.makeCall(fromCharCodeArrayImport,
                                             {curr->ref, curr->start, curr->end},
-                                            lowering.nnExt));
+                                            nnExt));
             return;
           case StringNewFromCodePoint:
-            replaceCurrent(builder.makeCall(
-              lowering.fromCodePointImport, {curr->ref}, lowering.nnExt));
+            replaceCurrent(
+              builder.makeCall(fromCodePointImport, {curr->ref}, nnExt));
             return;
           default:
             WASM_UNREACHABLE("TODO: all of string.new*");
@@ -427,18 +482,24 @@
 
       void visitStringConcat(StringConcat* curr) {
         Builder builder(*getModule());
-        replaceCurrent(builder.makeCall(
-          lowering.concatImport, {curr->left, curr->right}, lowering.nnExt));
+        bool shared = curr->type.getHeapType().isShared();
+        auto& concatImport =
+          shared ? lowering.concatSharedImport : lowering.concatImport;
+        auto nnExt = shared ? lowering.nnSharedExt : lowering.nnExt;
+        replaceCurrent(
+          builder.makeCall(concatImport, {curr->left, curr->right}, nnExt));
       }
 
       void visitStringEncode(StringEncode* curr) {
         Builder builder(*getModule());
+        bool shared = curr->str->type.getHeapType().isShared();
+        auto& intoCharCodeArrayImport = shared ? lowering.intoCharCodeArraySharedImport
+                                               : lowering.intoCharCodeArrayImport;
         switch (curr->op) {
           case StringEncodeWTF16Array:
-            replaceCurrent(
-              builder.makeCall(lowering.intoCharCodeArrayImport,
-                               {curr->str, curr->array, curr->start},
-                               Type::i32));
+            replaceCurrent(builder.makeCall(intoCharCodeArrayImport,
+                                            {curr->str, curr->array, curr->start},
+                                            Type::i32));
             return;
           default:
             WASM_UNREACHABLE("TODO: all of string.encode*");
@@ -447,14 +508,19 @@
 
       void visitStringEq(StringEq* curr) {
         Builder builder(*getModule());
+        bool shared = curr->left->type.getHeapType().isShared();
+        auto& equalsImport =
+          shared ? lowering.equalsSharedImport : lowering.equalsImport;
+        auto& compareImport =
+          shared ? lowering.compareSharedImport : lowering.compareImport;
         switch (curr->op) {
           case StringEqEqual:
             replaceCurrent(builder.makeCall(
-              lowering.equalsImport, {curr->left, curr->right}, Type::i32));
+              equalsImport, {curr->left, curr->right}, Type::i32));
             return;
           case StringEqCompare:
             replaceCurrent(builder.makeCall(
-              lowering.compareImport, {curr->left, curr->right}, Type::i32));
+              compareImport, {curr->left, curr->right}, Type::i32));
             return;
           default:
             WASM_UNREACHABLE("invalid string.eq*");
@@ -463,27 +529,39 @@
 
       void visitStringTest(StringTest* curr) {
         Builder builder(*getModule());
+        bool shared = curr->ref->type.getHeapType().isShared();
+        auto& testImport = shared ? lowering.testSharedImport : lowering.testImport;
         replaceCurrent(
-          builder.makeCall(lowering.testImport, {curr->ref}, Type::i32));
+          builder.makeCall(testImport, {curr->ref}, Type::i32));
       }
 
       void visitStringMeasure(StringMeasure* curr) {
         Builder builder(*getModule());
+        bool shared = curr->ref->type.getHeapType().isShared();
+        auto& lengthImport =
+          shared ? lowering.lengthSharedImport : lowering.lengthImport;
         replaceCurrent(
-          builder.makeCall(lowering.lengthImport, {curr->ref}, Type::i32));
+          builder.makeCall(lengthImport, {curr->ref}, Type::i32));
       }
 
       void visitStringWTF16Get(StringWTF16Get* curr) {
         Builder builder(*getModule());
+        bool shared = curr->ref->type.getHeapType().isShared();
+        auto& charCodeAtImport =
+          shared ? lowering.charCodeAtSharedImport : lowering.charCodeAtImport;
         replaceCurrent(builder.makeCall(
-          lowering.charCodeAtImport, {curr->ref, curr->pos}, Type::i32));
+          charCodeAtImport, {curr->ref, curr->pos}, Type::i32));
       }
 
       void visitStringSliceWTF(StringSliceWTF* curr) {
         Builder builder(*getModule());
-        replaceCurrent(builder.makeCall(lowering.substringImport,
+        bool shared = curr->type.getHeapType().isShared();
+        auto& substringImport =
+          shared ? lowering.substringSharedImport : lowering.substringImport;
+        auto nnExt = shared ? lowering.nnSharedExt : lowering.nnExt;
+        replaceCurrent(builder.makeCall(substringImport,
                                         {curr->ref, curr->start, curr->end},
-                                        lowering.nnExt));
+                                        nnExt));
       }
     };
 
diff --git a/src/wasm-type.h b/src/wasm-type.h
index 8361c90..bedfaa8 100644
--- a/src/wasm-type.h
+++ b/src/wasm-type.h
@@ -643,7 +643,9 @@
 // Certain heap types are used by standard operations. Provide central accessors
 // for them to avoid having to build them everywhere they are used.
 HeapType getMutI8Array();
+HeapType getSharedMutI8Array();
 HeapType getMutI16Array();
+HeapType getSharedMutI16Array();
 
 } // namespace HeapTypes
 
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index bfe2df1..67b177c 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -2834,11 +2834,31 @@
   return i8Array;
 }
 
+HeapType getSharedMutI8Array() {
+  static HeapType sharedI8Array = []() {
+    TypeBuilder builder(1);
+    builder[0] = Array{Field(Field::i8, Mutable)};
+    builder[0].setShared(Shared);
+    return (*builder.build())[0];
+  }();
+  return sharedI8Array;
+}
+
 HeapType getMutI16Array() {
-  static HeapType i16Array = Array(Field(Field::i16, Mutable));
+  static HeapType i16Array = Array{Field(Field::i16, Mutable)};
   return i16Array;
 }
 
+HeapType getSharedMutI16Array() {
+  static HeapType sharedI16Array = []() {
+    TypeBuilder builder(1);
+    builder[0] = Array{Field(Field::i16, Mutable)};
+    builder[0].setShared(Shared);
+    return (*builder.build())[0];
+  }();
+  return sharedI16Array;
+}
+
 } // namespace wasm::HeapTypes
 
 namespace std {
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 2b1c6cf..8b1d86d 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -4046,17 +4046,18 @@
             refType.isRef(), curr, "string.new input must have array type")) {
         return;
       }
+      auto ht = refType.getHeapType();
       if (curr->op == StringNewLossyUTF8Array) {
-        shouldBeSubType(
-          refType,
-          Type(HeapTypes::getMutI8Array(), Nullable),
+        shouldBeTrue(
+          HeapType::isSubType(ht, HeapTypes::getMutI8Array()) ||
+            HeapType::isSubType(ht, HeapTypes::getSharedMutI8Array()),
           curr,
           "string.new_lossy_utf8_array input must have proper i8 array type");
       } else {
         assert(curr->op == StringNewWTF16Array);
-        shouldBeSubType(
-          refType,
-          Type(HeapTypes::getMutI16Array(), Nullable),
+        shouldBeTrue(
+          HeapType::isSubType(ht, HeapTypes::getMutI16Array()) ||
+            HeapType::isSubType(ht, HeapTypes::getSharedMutI16Array()),
           curr,
           "string.new_wtf16_array input must have proper i16 array type");
       }
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index c05a23d..9a3d9c0 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -1442,8 +1442,12 @@
       (end && end->type == Type::unreachable)) {
     type = Type::unreachable;
   } else {
-    // TODO: Make this exact.
-    type = Type(HeapType::string, NonNullable);
+    // If our operand is shared, we are shared.
+    auto share = Unshared;
+    if (ref->type.isRef()) {
+      share = ref->type.getHeapType().getShared();
+    }
+    type = Type(HeapType(HeapType::string).getBasic(share), NonNullable);
   }
 }
 
@@ -1473,8 +1477,12 @@
   if (left->type == Type::unreachable || right->type == Type::unreachable) {
     type = Type::unreachable;
   } else {
-    // TODO: Make this exact.
-    type = Type(HeapType::string, NonNullable);
+    // If our operands are shared, we are shared.
+    auto share = Unshared;
+    if (left->type.isRef()) {
+      share = left->type.getHeapType().getShared();
+    }
+    type = Type(HeapType(HeapType::string).getBasic(share), NonNullable);
   }
 }
 
@@ -1507,8 +1515,12 @@
       end->type == Type::unreachable) {
     type = Type::unreachable;
   } else {
-    // TODO: Make this exact.
-    type = Type(HeapType::string, NonNullable);
+    // If our operand is shared, we are shared.
+    auto share = Unshared;
+    if (ref->type.isRef()) {
+      share = ref->type.getHeapType().getShared();
+    }
+    type = Type(HeapType(HeapType::string).getBasic(share), NonNullable);
   }
 }
 
diff --git a/test/lit/passes/shared-string-builtins.wast b/test/lit/passes/shared-string-builtins.wast
new file mode 100644
index 0000000..372439e
--- /dev/null
+++ b/test/lit/passes/shared-string-builtins.wast
@@ -0,0 +1,75 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s -all --string-lowering --no-validation -S -o - | filecheck %s --check-prefix=LOWER
+;; RUN: wasm-opt %s -all --string-lowering --string-lifting --no-validation -S -o - | filecheck %s --check-prefix=LIFT
+
+(module
+  ;; LOWER:      (rec
+  ;; LOWER-NEXT:  (type $shared-array16 (shared (array (mut i16))))
+  ;; LIFT:      (rec
+  ;; LIFT-NEXT:  (type $shared-array16 (shared (array (mut i16))))
+  (type $shared-array16 (shared (array (mut i16))))
+
+  ;; LOWER:      (func $new-shared (type $10) (param $a (ref $shared-array16)) (result (ref (shared extern)))
+  ;; LOWER-NEXT:  (call $fromCharCodeArray_14
+  ;; LOWER-NEXT:   (local.get $a)
+  ;; LOWER-NEXT:   (i32.const 0)
+  ;; LOWER-NEXT:   (i32.const 1)
+  ;; LOWER-NEXT:  )
+  ;; LOWER-NEXT: )
+  ;; LIFT:      (func $new-shared (type $10) (param $a (ref $shared-array16)) (result (ref (shared extern)))
+  ;; LIFT-NEXT:  (string.new_wtf16_array
+  ;; LIFT-NEXT:   (local.get $a)
+  ;; LIFT-NEXT:   (i32.const 0)
+  ;; LIFT-NEXT:   (i32.const 1)
+  ;; LIFT-NEXT:  )
+  ;; LIFT-NEXT: )
+  (func $new-shared (param $a (ref $shared-array16)) (result (ref (shared string)))
+    (string.new_wtf16_array (local.get $a) (i32.const 0) (i32.const 1))
+  )
+
+  ;; LOWER:      (func $concat-shared (type $9) (param $a (ref (shared extern))) (param $b (ref (shared extern))) (result (ref (shared extern)))
+  ;; LOWER-NEXT:  (call $concat_16
+  ;; LOWER-NEXT:   (local.get $a)
+  ;; LOWER-NEXT:   (local.get $b)
+  ;; LOWER-NEXT:  )
+  ;; LOWER-NEXT: )
+  ;; LIFT:      (func $concat-shared (type $9) (param $a (ref (shared extern))) (param $b (ref (shared extern))) (result (ref (shared extern)))
+  ;; LIFT-NEXT:  (string.concat
+  ;; LIFT-NEXT:   (local.get $a)
+  ;; LIFT-NEXT:   (local.get $b)
+  ;; LIFT-NEXT:  )
+  ;; LIFT-NEXT: )
+  (func $concat-shared (param $a (ref (shared string))) (param $b (ref (shared string))) (result (ref (shared string)))
+    (string.concat (local.get $a) (local.get $b))
+  )
+
+  ;; LOWER:      (func $eq-shared (type $8) (param $a (ref (shared extern))) (param $b (ref (shared extern))) (result i32)
+  ;; LOWER-NEXT:  (call $equals_18
+  ;; LOWER-NEXT:   (local.get $a)
+  ;; LOWER-NEXT:   (local.get $b)
+  ;; LOWER-NEXT:  )
+  ;; LOWER-NEXT: )
+  ;; LIFT:      (func $eq-shared (type $8) (param $a (ref (shared extern))) (param $b (ref (shared extern))) (result i32)
+  ;; LIFT-NEXT:  (string.eq
+  ;; LIFT-NEXT:   (local.get $a)
+  ;; LIFT-NEXT:   (local.get $b)
+  ;; LIFT-NEXT:  )
+  ;; LIFT-NEXT: )
+  (func $eq-shared (param $a (ref (shared string))) (param $b (ref (shared string))) (result i32)
+    (string.eq (local.get $a) (local.get $b))
+  )
+
+  ;; LOWER:      (func $length-shared (type $7) (param $a (ref (shared extern))) (result i32)
+  ;; LOWER-NEXT:  (call $length_21
+  ;; LOWER-NEXT:   (local.get $a)
+  ;; LOWER-NEXT:  )
+  ;; LOWER-NEXT: )
+  ;; LIFT:      (func $length-shared (type $7) (param $a (ref (shared extern))) (result i32)
+  ;; LIFT-NEXT:  (string.measure_wtf16
+  ;; LIFT-NEXT:   (local.get $a)
+  ;; LIFT-NEXT:  )
+  ;; LIFT-NEXT: )
+  (func $length-shared (param $a (ref (shared string))) (result i32)
+    (string.measure_wtf16 (local.get $a))
+  )
+)
diff --git a/test/lit/passes/string-gathering.wast b/test/lit/passes/string-gathering.wast
index c8724ab..59da2ee 100644
--- a/test/lit/passes/string-gathering.wast
+++ b/test/lit/passes/string-gathering.wast
@@ -27,23 +27,41 @@
   ;; CHECK:      (global $global2 stringref (global.get $"string.const_\"bar\""))
   ;; LOWER:      (type $0 (array (mut i16)))
 
-  ;; LOWER:      (type $1 (func))
+  ;; LOWER:      (type $1 (shared (array (mut i16))))
 
-  ;; LOWER:      (type $2 (func (param externref externref) (result i32)))
+  ;; LOWER:      (type $2 (func))
 
-  ;; LOWER:      (type $3 (func (param externref) (result i32)))
+  ;; LOWER:      (type $3 (func (param externref externref) (result i32)))
 
-  ;; LOWER:      (type $4 (func (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; LOWER:      (type $4 (func (param externref) (result i32)))
 
-  ;; LOWER:      (type $5 (func (param i32) (result (ref extern))))
+  ;; LOWER:      (type $5 (func (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
 
-  ;; LOWER:      (type $6 (func (param externref externref) (result (ref extern))))
+  ;; LOWER:      (type $6 (func (param (ref null (shared extern))) (result i32)))
 
-  ;; LOWER:      (type $7 (func (param externref (ref null $0) i32) (result i32)))
+  ;; LOWER:      (type $7 (func (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; LOWER:      (type $8 (func (param externref i32) (result i32)))
+  ;; LOWER:      (type $8 (func (param i32) (result (ref extern))))
 
-  ;; LOWER:      (type $9 (func (param externref i32 i32) (result (ref extern))))
+  ;; LOWER:      (type $9 (func (param externref externref) (result (ref extern))))
+
+  ;; LOWER:      (type $10 (func (param externref (ref null $0) i32) (result i32)))
+
+  ;; LOWER:      (type $11 (func (param externref i32) (result i32)))
+
+  ;; LOWER:      (type $12 (func (param externref i32 i32) (result (ref extern))))
+
+  ;; LOWER:      (type $13 (func (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (type $14 (func (param i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (type $15 (func (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; LOWER:      (type $16 (func (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; LOWER:      (type $17 (func (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; LOWER:      (type $18 (func (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; LOWER:      (import "string.const" "0" (global $global (ref extern)))
 
@@ -51,25 +69,45 @@
 
   ;; LOWER:      (import "string.const" "2" (global $"string.const_\"other\"" (ref extern)))
 
-  ;; LOWER:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $4) (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $7) (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; LOWER:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $5) (param i32) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $8) (param i32) (result (ref extern))))
 
-  ;; LOWER:      (import "wasm:js-string" "concat" (func $concat (type $6) (param externref externref) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "concat" (func $concat (type $9) (param externref externref) (result (ref extern))))
 
-  ;; LOWER:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $7) (param externref (ref null $0) i32) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $10) (param externref (ref null $0) i32) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "equals" (func $equals (type $2) (param externref externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "equals" (func $equals (type $3) (param externref externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "test" (func $test (type $3) (param externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "test" (func $test (type $4) (param externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "compare" (func $compare (type $2) (param externref externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "compare" (func $compare (type $3) (param externref externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "length" (func $length (type $3) (param externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "length" (func $length (type $4) (param externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $8) (param externref i32) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $11) (param externref i32) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "substring" (func $substring (type $9) (param externref i32 i32) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "substring" (func $substring (type $12) (param externref i32 i32) (result (ref extern))))
+
+  ;; LOWER:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray_12 (type $13) (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_13 (type $14) (param i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (import "wasm:js-string" "concat" (func $concat_14 (type $15) (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; LOWER:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray_15 (type $16) (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "equals" (func $equals_16 (type $5) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "test" (func $test_17 (type $6) (param (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "compare" (func $compare_18 (type $5) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "length" (func $length_19 (type $6) (param (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt_20 (type $17) (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "substring" (func $substring_21 (type $18) (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; LOWER:      (global $global2 externref (global.get $"string.const_\"bar\""))
   (global $global2 (ref null string) (string.const "bar"))
@@ -82,7 +120,7 @@
   ;; CHECK-NEXT:   (global.get $global)
   ;; CHECK-NEXT:  )
   ;; CHECK-NEXT: )
-  ;; LOWER:      (func $a (type $1)
+  ;; LOWER:      (func $a (type $2)
   ;; LOWER-NEXT:  (drop
   ;; LOWER-NEXT:   (global.get $"string.const_\"bar\"")
   ;; LOWER-NEXT:  )
@@ -113,7 +151,7 @@
   ;; CHECK-NEXT:   (global.get $global2)
   ;; CHECK-NEXT:  )
   ;; CHECK-NEXT: )
-  ;; LOWER:      (func $b (type $1)
+  ;; LOWER:      (func $b (type $2)
   ;; LOWER-NEXT:  (drop
   ;; LOWER-NEXT:   (global.get $"string.const_\"bar\"")
   ;; LOWER-NEXT:  )
@@ -151,21 +189,39 @@
   ;; CHECK:      (import "a" "b" (global $import (ref string)))
   ;; LOWER:      (type $0 (array (mut i16)))
 
-  ;; LOWER:      (type $1 (func (param externref externref) (result i32)))
+  ;; LOWER:      (type $1 (shared (array (mut i16))))
 
-  ;; LOWER:      (type $2 (func (param externref) (result i32)))
+  ;; LOWER:      (type $2 (func (param externref externref) (result i32)))
 
-  ;; LOWER:      (type $3 (func (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; LOWER:      (type $3 (func (param externref) (result i32)))
 
-  ;; LOWER:      (type $4 (func (param i32) (result (ref extern))))
+  ;; LOWER:      (type $4 (func (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
 
-  ;; LOWER:      (type $5 (func (param externref externref) (result (ref extern))))
+  ;; LOWER:      (type $5 (func (param (ref null (shared extern))) (result i32)))
 
-  ;; LOWER:      (type $6 (func (param externref (ref null $0) i32) (result i32)))
+  ;; LOWER:      (type $6 (func (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; LOWER:      (type $7 (func (param externref i32) (result i32)))
+  ;; LOWER:      (type $7 (func (param i32) (result (ref extern))))
 
-  ;; LOWER:      (type $8 (func (param externref i32 i32) (result (ref extern))))
+  ;; LOWER:      (type $8 (func (param externref externref) (result (ref extern))))
+
+  ;; LOWER:      (type $9 (func (param externref (ref null $0) i32) (result i32)))
+
+  ;; LOWER:      (type $10 (func (param externref i32) (result i32)))
+
+  ;; LOWER:      (type $11 (func (param externref i32 i32) (result (ref extern))))
+
+  ;; LOWER:      (type $12 (func (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (type $13 (func (param i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (type $14 (func (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; LOWER:      (type $15 (func (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; LOWER:      (type $16 (func (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; LOWER:      (type $17 (func (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; LOWER:      (import "string.const" "0" (global $global1 (ref extern)))
 
@@ -180,25 +236,45 @@
   ;; CHECK:      (global $global4 (ref string) (string.const "bar"))
 
   ;; CHECK:      (global $global2 (ref string) (global.get $global1))
-  ;; LOWER:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $3) (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $6) (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; LOWER:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $4) (param i32) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $7) (param i32) (result (ref extern))))
 
-  ;; LOWER:      (import "wasm:js-string" "concat" (func $concat (type $5) (param externref externref) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "concat" (func $concat (type $8) (param externref externref) (result (ref extern))))
 
-  ;; LOWER:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $6) (param externref (ref null $0) i32) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $9) (param externref (ref null $0) i32) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "equals" (func $equals (type $1) (param externref externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "equals" (func $equals (type $2) (param externref externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "test" (func $test (type $2) (param externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "test" (func $test (type $3) (param externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "compare" (func $compare (type $1) (param externref externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "compare" (func $compare (type $2) (param externref externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "length" (func $length (type $2) (param externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "length" (func $length (type $3) (param externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $7) (param externref i32) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $10) (param externref i32) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "substring" (func $substring (type $8) (param externref i32 i32) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "substring" (func $substring (type $11) (param externref i32 i32) (result (ref extern))))
+
+  ;; LOWER:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray_10 (type $12) (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_11 (type $13) (param i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (import "wasm:js-string" "concat" (func $concat_12 (type $14) (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; LOWER:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray_13 (type $15) (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "equals" (func $equals_14 (type $4) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "test" (func $test_15 (type $5) (param (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "compare" (func $compare_16 (type $4) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "length" (func $length_17 (type $5) (param (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt_18 (type $16) (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "substring" (func $substring_19 (type $17) (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; LOWER:      (global $global2 (ref extern) (global.get $global1))
   (global $global2 (ref string) (string.const "foo"))
@@ -227,45 +303,83 @@
   ;; CHECK:      (global $global (mut (ref string)) (global.get $"string.const_\"foo\""))
   ;; LOWER:      (type $0 (array (mut i16)))
 
-  ;; LOWER:      (type $1 (func (param externref externref) (result i32)))
+  ;; LOWER:      (type $1 (shared (array (mut i16))))
 
-  ;; LOWER:      (type $2 (func (param externref) (result i32)))
+  ;; LOWER:      (type $2 (func (param externref externref) (result i32)))
 
-  ;; LOWER:      (type $3 (func))
+  ;; LOWER:      (type $3 (func (param externref) (result i32)))
 
-  ;; LOWER:      (type $4 (func (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; LOWER:      (type $4 (func (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
 
-  ;; LOWER:      (type $5 (func (param i32) (result (ref extern))))
+  ;; LOWER:      (type $5 (func (param (ref null (shared extern))) (result i32)))
 
-  ;; LOWER:      (type $6 (func (param externref externref) (result (ref extern))))
+  ;; LOWER:      (type $6 (func))
 
-  ;; LOWER:      (type $7 (func (param externref (ref null $0) i32) (result i32)))
+  ;; LOWER:      (type $7 (func (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; LOWER:      (type $8 (func (param externref i32) (result i32)))
+  ;; LOWER:      (type $8 (func (param i32) (result (ref extern))))
 
-  ;; LOWER:      (type $9 (func (param externref i32 i32) (result (ref extern))))
+  ;; LOWER:      (type $9 (func (param externref externref) (result (ref extern))))
+
+  ;; LOWER:      (type $10 (func (param externref (ref null $0) i32) (result i32)))
+
+  ;; LOWER:      (type $11 (func (param externref i32) (result i32)))
+
+  ;; LOWER:      (type $12 (func (param externref i32 i32) (result (ref extern))))
+
+  ;; LOWER:      (type $13 (func (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (type $14 (func (param i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (type $15 (func (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; LOWER:      (type $16 (func (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; LOWER:      (type $17 (func (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; LOWER:      (type $18 (func (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; LOWER:      (import "string.const" "0" (global $"string.const_\"foo\"" (ref extern)))
 
-  ;; LOWER:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $4) (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $7) (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; LOWER:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $5) (param i32) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $8) (param i32) (result (ref extern))))
 
-  ;; LOWER:      (import "wasm:js-string" "concat" (func $concat (type $6) (param externref externref) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "concat" (func $concat (type $9) (param externref externref) (result (ref extern))))
 
-  ;; LOWER:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $7) (param externref (ref null $0) i32) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $10) (param externref (ref null $0) i32) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "equals" (func $equals (type $1) (param externref externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "equals" (func $equals (type $2) (param externref externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "test" (func $test (type $2) (param externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "test" (func $test (type $3) (param externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "compare" (func $compare (type $1) (param externref externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "compare" (func $compare (type $2) (param externref externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "length" (func $length (type $2) (param externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "length" (func $length (type $3) (param externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $8) (param externref i32) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $11) (param externref i32) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "substring" (func $substring (type $9) (param externref i32 i32) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "substring" (func $substring (type $12) (param externref i32 i32) (result (ref extern))))
+
+  ;; LOWER:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray_11 (type $13) (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_12 (type $14) (param i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (import "wasm:js-string" "concat" (func $concat_13 (type $15) (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; LOWER:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray_14 (type $16) (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "equals" (func $equals_15 (type $4) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "test" (func $test_16 (type $5) (param (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "compare" (func $compare_17 (type $4) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "length" (func $length_18 (type $5) (param (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt_19 (type $17) (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "substring" (func $substring_20 (type $18) (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; LOWER:      (global $global (mut (ref extern)) (global.get $"string.const_\"foo\""))
   (global $global (mut (ref string)) (string.const "foo"))
@@ -275,7 +389,7 @@
   ;; CHECK-NEXT:   (global.get $"string.const_\"foo\"")
   ;; CHECK-NEXT:  )
   ;; CHECK-NEXT: )
-  ;; LOWER:      (func $a (type $3)
+  ;; LOWER:      (func $a (type $6)
   ;; LOWER-NEXT:  (drop
   ;; LOWER-NEXT:   (global.get $"string.const_\"foo\"")
   ;; LOWER-NEXT:  )
@@ -296,6 +410,8 @@
   ;; CHECK:      (type $struct (struct (field stringref)))
   ;; LOWER:      (type $0 (array (mut i16)))
 
+  ;; LOWER:      (type $1 (shared (array (mut i16))))
+
   ;; LOWER:      (type $struct (struct (field externref)))
   (type $struct (struct (field stringref)))
 
@@ -304,43 +420,79 @@
   ;; CHECK:      (global $struct (ref $struct) (struct.new $struct
   ;; CHECK-NEXT:  (global.get $string)
   ;; CHECK-NEXT: ))
-  ;; LOWER:      (type $2 (func (param externref externref) (result i32)))
+  ;; LOWER:      (type $3 (func (param externref externref) (result i32)))
 
-  ;; LOWER:      (type $3 (func (param externref) (result i32)))
+  ;; LOWER:      (type $4 (func (param externref) (result i32)))
 
-  ;; LOWER:      (type $4 (func (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; LOWER:      (type $5 (func (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
 
-  ;; LOWER:      (type $5 (func (param i32) (result (ref extern))))
+  ;; LOWER:      (type $6 (func (param (ref null (shared extern))) (result i32)))
 
-  ;; LOWER:      (type $6 (func (param externref externref) (result (ref extern))))
+  ;; LOWER:      (type $7 (func (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; LOWER:      (type $7 (func (param externref (ref null $0) i32) (result i32)))
+  ;; LOWER:      (type $8 (func (param i32) (result (ref extern))))
 
-  ;; LOWER:      (type $8 (func (param externref i32) (result i32)))
+  ;; LOWER:      (type $9 (func (param externref externref) (result (ref extern))))
 
-  ;; LOWER:      (type $9 (func (param externref i32 i32) (result (ref extern))))
+  ;; LOWER:      (type $10 (func (param externref (ref null $0) i32) (result i32)))
+
+  ;; LOWER:      (type $11 (func (param externref i32) (result i32)))
+
+  ;; LOWER:      (type $12 (func (param externref i32 i32) (result (ref extern))))
+
+  ;; LOWER:      (type $13 (func (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (type $14 (func (param i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (type $15 (func (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; LOWER:      (type $16 (func (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; LOWER:      (type $17 (func (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; LOWER:      (type $18 (func (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; LOWER:      (import "string.const" "0" (global $string (ref extern)))
 
-  ;; LOWER:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $4) (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $7) (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; LOWER:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $5) (param i32) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $8) (param i32) (result (ref extern))))
 
-  ;; LOWER:      (import "wasm:js-string" "concat" (func $concat (type $6) (param externref externref) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "concat" (func $concat (type $9) (param externref externref) (result (ref extern))))
 
-  ;; LOWER:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $7) (param externref (ref null $0) i32) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $10) (param externref (ref null $0) i32) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "equals" (func $equals (type $2) (param externref externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "equals" (func $equals (type $3) (param externref externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "test" (func $test (type $3) (param externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "test" (func $test (type $4) (param externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "compare" (func $compare (type $2) (param externref externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "compare" (func $compare (type $3) (param externref externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "length" (func $length (type $3) (param externref) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "length" (func $length (type $4) (param externref) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $8) (param externref i32) (result i32)))
+  ;; LOWER:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $11) (param externref i32) (result i32)))
 
-  ;; LOWER:      (import "wasm:js-string" "substring" (func $substring (type $9) (param externref i32 i32) (result (ref extern))))
+  ;; LOWER:      (import "wasm:js-string" "substring" (func $substring (type $12) (param externref i32 i32) (result (ref extern))))
+
+  ;; LOWER:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray_10 (type $13) (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_11 (type $14) (param i32) (result (ref (shared extern)))))
+
+  ;; LOWER:      (import "wasm:js-string" "concat" (func $concat_12 (type $15) (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; LOWER:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray_13 (type $16) (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "equals" (func $equals_14 (type $5) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "test" (func $test_15 (type $6) (param (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "compare" (func $compare_16 (type $5) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "length" (func $length_17 (type $6) (param (ref null (shared extern))) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt_18 (type $17) (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; LOWER:      (import "wasm:js-string" "substring" (func $substring_19 (type $18) (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; LOWER:      (global $struct (ref $struct) (struct.new $struct
   ;; LOWER-NEXT:  (global.get $string)
diff --git a/test/lit/passes/string-lifting-section.wast b/test/lit/passes/string-lifting-section.wast
index 5406494..d223139 100644
--- a/test/lit/passes/string-lifting-section.wast
+++ b/test/lit/passes/string-lifting-section.wast
@@ -7,23 +7,41 @@
 (module
   ;; CHECK:      (type $0 (array (mut i16)))
 
-  ;; CHECK:      (type $1 (func))
+  ;; CHECK:      (type $1 (shared (array (mut i16))))
 
-  ;; CHECK:      (type $2 (func (param externref externref) (result i32)))
+  ;; CHECK:      (type $2 (func))
 
-  ;; CHECK:      (type $3 (func (param externref) (result i32)))
+  ;; CHECK:      (type $3 (func (param externref externref) (result i32)))
 
-  ;; CHECK:      (type $4 (func (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; CHECK:      (type $4 (func (param externref) (result i32)))
 
-  ;; CHECK:      (type $5 (func (param i32) (result (ref extern))))
+  ;; CHECK:      (type $5 (func (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
 
-  ;; CHECK:      (type $6 (func (param externref externref) (result (ref extern))))
+  ;; CHECK:      (type $6 (func (param (ref null (shared extern))) (result i32)))
 
-  ;; CHECK:      (type $7 (func (param externref (ref null $0) i32) (result i32)))
+  ;; CHECK:      (type $7 (func (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; CHECK:      (type $8 (func (param externref i32) (result i32)))
+  ;; CHECK:      (type $8 (func (param i32) (result (ref extern))))
 
-  ;; CHECK:      (type $9 (func (param externref i32 i32) (result (ref extern))))
+  ;; CHECK:      (type $9 (func (param externref externref) (result (ref extern))))
+
+  ;; CHECK:      (type $10 (func (param externref (ref null $0) i32) (result i32)))
+
+  ;; CHECK:      (type $11 (func (param externref i32) (result i32)))
+
+  ;; CHECK:      (type $12 (func (param externref i32 i32) (result (ref extern))))
+
+  ;; CHECK:      (type $13 (func (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (type $14 (func (param i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (type $15 (func (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; CHECK:      (type $16 (func (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; CHECK:      (type $17 (func (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; CHECK:      (type $18 (func (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; CHECK:      (import "string.const" "0" (global $"string.const_\"bar\"" (ref extern)))
 
@@ -39,27 +57,47 @@
 
   ;; CHECK:      (import "string.const" "6" (global $"string.const_\"z\\\\\"" (ref extern)))
 
-  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $4) (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $7) (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $5) (param i32) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $8) (param i32) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat (type $6) (param externref externref) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat (type $9) (param externref externref) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $7) (param externref (ref null $0) i32) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $10) (param externref (ref null $0) i32) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals (type $2) (param externref externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals (type $3) (param externref externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "test" (func $test (type $3) (param externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "test" (func $test (type $4) (param externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare (type $2) (param externref externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare (type $3) (param externref externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "length" (func $length (type $3) (param externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "length" (func $length (type $4) (param externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $8) (param externref i32) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $11) (param externref i32) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring (type $9) (param externref i32 i32) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring (type $12) (param externref i32 i32) (result (ref extern))))
 
-  ;; CHECK:      (func $consts (type $1)
+  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray_12 (type $13) (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_13 (type $14) (param i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat_14 (type $15) (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray_15 (type $16) (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals_16 (type $5) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "test" (func $test_17 (type $6) (param (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare_18 (type $5) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "length" (func $length_19 (type $6) (param (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt_20 (type $17) (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring_21 (type $18) (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (func $consts (type $2)
   ;; CHECK-NEXT:  (drop
   ;; CHECK-NEXT:   (string.const "foo")
   ;; CHECK-NEXT:  )
@@ -85,7 +123,7 @@
     )
   )
 
-  ;; CHECK:      (func $tricky-consts (type $1)
+  ;; CHECK:      (func $tricky-consts (type $2)
   ;; CHECK-NEXT:  (drop
   ;; CHECK-NEXT:   (string.const "needs\tescaping\00.\'#%\"- .\r\n\\08\0c\n\r\t.\ea\99\ae")
   ;; CHECK-NEXT:  )
diff --git a/test/lit/passes/string-lowering-imports-custom-module.wast b/test/lit/passes/string-lowering-imports-custom-module.wast
index 2d82bfb..24d87bc 100644
--- a/test/lit/passes/string-lowering-imports-custom-module.wast
+++ b/test/lit/passes/string-lowering-imports-custom-module.wast
@@ -9,49 +9,87 @@
 (module
   ;; CHECK:      (type $0 (array (mut i16)))
 
-  ;; CHECK:      (type $1 (func (param externref externref) (result i32)))
+  ;; CHECK:      (type $1 (shared (array (mut i16))))
 
-  ;; CHECK:      (type $2 (func (param externref) (result i32)))
+  ;; CHECK:      (type $2 (func (param externref externref) (result i32)))
 
-  ;; CHECK:      (type $3 (func))
+  ;; CHECK:      (type $3 (func (param externref) (result i32)))
 
-  ;; CHECK:      (type $4 (func (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; CHECK:      (type $4 (func (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
 
-  ;; CHECK:      (type $5 (func (param i32) (result (ref extern))))
+  ;; CHECK:      (type $5 (func (param (ref null (shared extern))) (result i32)))
 
-  ;; CHECK:      (type $6 (func (param externref externref) (result (ref extern))))
+  ;; CHECK:      (type $6 (func))
 
-  ;; CHECK:      (type $7 (func (param externref (ref null $0) i32) (result i32)))
+  ;; CHECK:      (type $7 (func (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; CHECK:      (type $8 (func (param externref i32) (result i32)))
+  ;; CHECK:      (type $8 (func (param i32) (result (ref extern))))
 
-  ;; CHECK:      (type $9 (func (param externref i32 i32) (result (ref extern))))
+  ;; CHECK:      (type $9 (func (param externref externref) (result (ref extern))))
+
+  ;; CHECK:      (type $10 (func (param externref (ref null $0) i32) (result i32)))
+
+  ;; CHECK:      (type $11 (func (param externref i32) (result i32)))
+
+  ;; CHECK:      (type $12 (func (param externref i32 i32) (result (ref extern))))
+
+  ;; CHECK:      (type $13 (func (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (type $14 (func (param i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (type $15 (func (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; CHECK:      (type $16 (func (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; CHECK:      (type $17 (func (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; CHECK:      (type $18 (func (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; CHECK:      (import "strings" "foo" (global $"string.const_\"foo\"" (ref extern)))
 
-  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $4) (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $7) (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $5) (param i32) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $8) (param i32) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat (type $6) (param externref externref) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat (type $9) (param externref externref) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $7) (param externref (ref null $0) i32) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $10) (param externref (ref null $0) i32) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals (type $1) (param externref externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals (type $2) (param externref externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "test" (func $test (type $2) (param externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "test" (func $test (type $3) (param externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare (type $1) (param externref externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare (type $2) (param externref externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "length" (func $length (type $2) (param externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "length" (func $length (type $3) (param externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $8) (param externref i32) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $11) (param externref i32) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring (type $9) (param externref i32 i32) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring (type $12) (param externref i32 i32) (result (ref extern))))
+
+  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray_11 (type $13) (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_12 (type $14) (param i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat_13 (type $15) (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray_14 (type $16) (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals_15 (type $4) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "test" (func $test_16 (type $5) (param (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare_17 (type $4) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "length" (func $length_18 (type $5) (param (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt_19 (type $17) (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring_20 (type $18) (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; CHECK:      (export "const" (func $const))
 
-  ;; CHECK:      (func $const (type $3)
+  ;; CHECK:      (func $const (type $6)
   ;; CHECK-NEXT:  (drop
   ;; CHECK-NEXT:   (global.get $"string.const_\"foo\"")
   ;; CHECK-NEXT:  )
diff --git a/test/lit/passes/string-lowering-instructions.wast b/test/lit/passes/string-lowering-instructions.wast
index 2330383..750d239 100644
--- a/test/lit/passes/string-lowering-instructions.wast
+++ b/test/lit/passes/string-lowering-instructions.wast
@@ -43,23 +43,41 @@
 
   ;; CHECK:      (type $15 (func (param externref) (result i32)))
 
-  ;; CHECK:      (type $16 (func (result externref)))
+  ;; CHECK:      (type $16 (shared (array (mut i16))))
 
-  ;; CHECK:      (type $17 (func (param externref externref) (result i32)))
+  ;; CHECK:      (type $17 (func (result externref)))
 
-  ;; CHECK:      (type $18 (func (param externref i32 externref)))
+  ;; CHECK:      (type $18 (func (param externref externref) (result i32)))
 
-  ;; CHECK:      (type $19 (func (param (ref null $array16) i32 i32) (result (ref extern))))
+  ;; CHECK:      (type $19 (func (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
 
-  ;; CHECK:      (type $20 (func (param i32) (result (ref extern))))
+  ;; CHECK:      (type $20 (func (param (ref null (shared extern))) (result i32)))
 
-  ;; CHECK:      (type $21 (func (param externref externref) (result (ref extern))))
+  ;; CHECK:      (type $21 (func (param externref i32 externref)))
 
-  ;; CHECK:      (type $22 (func (param externref (ref null $array16) i32) (result i32)))
+  ;; CHECK:      (type $22 (func (param (ref null $array16) i32 i32) (result (ref extern))))
 
-  ;; CHECK:      (type $23 (func (param externref i32) (result i32)))
+  ;; CHECK:      (type $23 (func (param i32) (result (ref extern))))
 
-  ;; CHECK:      (type $24 (func (param externref i32 i32) (result (ref extern))))
+  ;; CHECK:      (type $24 (func (param externref externref) (result (ref extern))))
+
+  ;; CHECK:      (type $25 (func (param externref (ref null $array16) i32) (result i32)))
+
+  ;; CHECK:      (type $26 (func (param externref i32) (result i32)))
+
+  ;; CHECK:      (type $27 (func (param externref i32 i32) (result (ref extern))))
+
+  ;; CHECK:      (type $28 (func (param (ref null $16) i32 i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (type $29 (func (param i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (type $30 (func (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; CHECK:      (type $31 (func (param (ref null (shared extern)) (ref null $16) i32) (result i32)))
+
+  ;; CHECK:      (type $32 (func (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; CHECK:      (type $33 (func (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; CHECK:      (import "string.const" "0" (global $"string.const_\"exported\"" (ref extern)))
 
@@ -69,25 +87,45 @@
   (import "colliding" "name" (func $fromCodePoint))
 
 
-  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $19) (param (ref null $array16) i32 i32) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $22) (param (ref null $array16) i32 i32) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_19 (type $20) (param i32) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_19 (type $23) (param i32) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat (type $21) (param externref externref) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat (type $24) (param externref externref) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $22) (param externref (ref null $array16) i32) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $25) (param externref (ref null $array16) i32) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals (type $17) (param externref externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals (type $18) (param externref externref) (result i32)))
 
   ;; CHECK:      (import "wasm:js-string" "test" (func $test (type $15) (param externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare (type $17) (param externref externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare (type $18) (param externref externref) (result i32)))
 
   ;; CHECK:      (import "wasm:js-string" "length" (func $length (type $15) (param externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $23) (param externref i32) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $26) (param externref i32) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring (type $24) (param externref i32 i32) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring (type $27) (param externref i32 i32) (result (ref extern))))
+
+  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray_28 (type $28) (param (ref null $16) i32 i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_29 (type $29) (param i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat_30 (type $30) (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray_31 (type $31) (param (ref null (shared extern)) (ref null $16) i32) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals_32 (type $19) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "test" (func $test_33 (type $20) (param (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare_34 (type $19) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "length" (func $length_35 (type $20) (param (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt_36 (type $32) (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring_37 (type $33) (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; CHECK:      (global $string externref (ref.null noextern))
   (global $string stringref (ref.null string)) ;; Test we update global nulls.
@@ -115,7 +153,7 @@
     )
   )
 
-  ;; CHECK:      (func $string.from_code_point (type $16) (result externref)
+  ;; CHECK:      (func $string.from_code_point (type $17) (result externref)
   ;; CHECK-NEXT:  (call $fromCodePoint_19
   ;; CHECK-NEXT:   (i32.const 1)
   ;; CHECK-NEXT:  )
@@ -278,7 +316,7 @@
     )
   )
 
-  ;; CHECK:      (func $exported-string-returner (type $16) (result externref)
+  ;; CHECK:      (func $exported-string-returner (type $17) (result externref)
   ;; CHECK-NEXT:  (global.get $"string.const_\"exported\"")
   ;; CHECK-NEXT: )
   (func $exported-string-returner (export "export.1") (result stringref)
@@ -287,7 +325,7 @@
     (string.const "exported")
   )
 
-  ;; CHECK:      (func $exported-string-receiver (type $18) (param $x externref) (param $y i32) (param $z externref)
+  ;; CHECK:      (func $exported-string-receiver (type $21) (param $x externref) (param $y i32) (param $z externref)
   ;; CHECK-NEXT:  (drop
   ;; CHECK-NEXT:   (local.get $x)
   ;; CHECK-NEXT:  )
diff --git a/test/lit/passes/string-lowering_types.wast b/test/lit/passes/string-lowering_types.wast
index 36c92ba..861e8fa 100644
--- a/test/lit/passes/string-lowering_types.wast
+++ b/test/lit/passes/string-lowering_types.wast
@@ -10,62 +10,100 @@
   (rec
     ;; CHECK:      (type $0 (array (mut i16)))
 
-    ;; CHECK:      (type $1 (func (param externref externref) (result i32)))
+    ;; CHECK:      (type $1 (shared (array (mut i16))))
 
-    ;; CHECK:      (type $2 (func (param externref) (result i32)))
+    ;; CHECK:      (type $2 (func (param externref externref) (result i32)))
 
-    ;; CHECK:      (type $3 (func (param externref)))
+    ;; CHECK:      (type $3 (func (param externref) (result i32)))
 
-    ;; CHECK:      (type $4 (func (param (ref extern))))
+    ;; CHECK:      (type $4 (func (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
 
-    ;; CHECK:      (type $5 (func))
+    ;; CHECK:      (type $5 (func (param (ref null (shared extern))) (result i32)))
+
+    ;; CHECK:      (type $6 (func (param externref)))
+
+    ;; CHECK:      (type $7 (func (param (ref extern))))
+
+    ;; CHECK:      (type $8 (func))
 
     ;; CHECK:      (type $private (struct (field externref)))
     (type $private (struct (field stringref)))
   )
   (type $public (func (param stringref)))
 
-  ;; CHECK:      (type $7 (func (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; CHECK:      (type $10 (func (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; CHECK:      (type $8 (func (param i32) (result (ref extern))))
+  ;; CHECK:      (type $11 (func (param i32) (result (ref extern))))
 
-  ;; CHECK:      (type $9 (func (param externref externref) (result (ref extern))))
+  ;; CHECK:      (type $12 (func (param externref externref) (result (ref extern))))
 
-  ;; CHECK:      (type $10 (func (param externref (ref null $0) i32) (result i32)))
+  ;; CHECK:      (type $13 (func (param externref (ref null $0) i32) (result i32)))
 
-  ;; CHECK:      (type $11 (func (param externref i32) (result i32)))
+  ;; CHECK:      (type $14 (func (param externref i32) (result i32)))
 
-  ;; CHECK:      (type $12 (func (param externref i32 i32) (result (ref extern))))
+  ;; CHECK:      (type $15 (func (param externref i32 i32) (result (ref extern))))
 
-  ;; CHECK:      (import "a" "b" (func $import (type $3) (param externref)))
+  ;; CHECK:      (type $16 (func (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (type $17 (func (param i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (type $18 (func (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; CHECK:      (type $19 (func (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; CHECK:      (type $20 (func (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; CHECK:      (type $21 (func (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "a" "b" (func $import (type $6) (param externref)))
   (import "a" "b" (func $import (type $public) (param stringref)))
 
-  ;; CHECK:      (import "a" "b" (func $import-implicit (type $4) (param (ref extern))))
+  ;; CHECK:      (import "a" "b" (func $import-implicit (type $7) (param (ref extern))))
   (import "a" "b" (func $import-implicit (param (ref string))))
 
-  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $7) (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $10) (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $8) (param i32) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $11) (param i32) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat (type $9) (param externref externref) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat (type $12) (param externref externref) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $10) (param externref (ref null $0) i32) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $13) (param externref (ref null $0) i32) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals (type $1) (param externref externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals (type $2) (param externref externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "test" (func $test (type $2) (param externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "test" (func $test (type $3) (param externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare (type $1) (param externref externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare (type $2) (param externref externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "length" (func $length (type $2) (param externref) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "length" (func $length (type $3) (param externref) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $11) (param externref i32) (result i32)))
+  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $14) (param externref i32) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring (type $12) (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:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray_13 (type $16) (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_14 (type $17) (param i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat_15 (type $18) (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray_16 (type $19) (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals_17 (type $4) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "test" (func $test_18 (type $5) (param (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare_19 (type $4) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "length" (func $length_20 (type $5) (param (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt_21 (type $20) (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring_22 (type $21) (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; CHECK:      (export "export" (func $export))
 
-  ;; CHECK:      (func $export (type $5)
+  ;; CHECK:      (func $export (type $8)
   ;; CHECK-NEXT:  (local $0 (ref $private))
   ;; CHECK-NEXT: )
   (func $export (export "export")
@@ -79,43 +117,81 @@
 (module
   ;; CHECK:      (type $0 (array (mut i16)))
 
-  ;; CHECK:      (type $1 (func (param externref externref) (result i32)))
+  ;; CHECK:      (type $1 (shared (array (mut i16))))
 
-  ;; CHECK:      (type $2 (func (param externref) (result i32)))
+  ;; CHECK:      (type $2 (func (param externref externref) (result i32)))
 
-  ;; CHECK:      (type $3 (func (result (ref extern))))
+  ;; CHECK:      (type $3 (func (param externref) (result i32)))
 
-  ;; CHECK:      (type $4 (func (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; CHECK:      (type $4 (func (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
 
-  ;; CHECK:      (type $5 (func (param i32) (result (ref extern))))
+  ;; CHECK:      (type $5 (func (param (ref null (shared extern))) (result i32)))
 
-  ;; CHECK:      (type $6 (func (param externref externref) (result (ref extern))))
+  ;; CHECK:      (type $6 (func (result (ref extern))))
 
-  ;; CHECK:      (type $7 (func (param externref (ref null $0) i32) (result i32)))
+  ;; CHECK:      (type $7 (func (param (ref null $0) i32 i32) (result (ref extern))))
 
-  ;; CHECK:      (type $8 (func (param externref i32) (result i32)))
+  ;; CHECK:      (type $8 (func (param i32) (result (ref extern))))
 
-  ;; CHECK:      (type $9 (func (param externref i32 i32) (result (ref extern))))
+  ;; CHECK:      (type $9 (func (param externref externref) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $4) (param (ref null $0) i32 i32) (result (ref extern))))
+  ;; CHECK:      (type $10 (func (param externref (ref null $0) i32) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $5) (param i32) (result (ref extern))))
+  ;; CHECK:      (type $11 (func (param externref i32) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat (type $6) (param externref externref) (result (ref extern))))
+  ;; CHECK:      (type $12 (func (param externref i32 i32) (result (ref extern))))
 
-  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $7) (param externref (ref null $0) i32) (result i32)))
+  ;; CHECK:      (type $13 (func (param (ref null $1) i32 i32) (result (ref (shared extern)))))
 
-  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals (type $1) (param externref externref) (result i32)))
+  ;; CHECK:      (type $14 (func (param i32) (result (ref (shared extern)))))
 
-  ;; CHECK:      (import "wasm:js-string" "test" (func $test (type $2) (param externref) (result i32)))
+  ;; CHECK:      (type $15 (func (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
 
-  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare (type $1) (param externref externref) (result i32)))
+  ;; CHECK:      (type $16 (func (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "length" (func $length (type $2) (param externref) (result i32)))
+  ;; CHECK:      (type $17 (func (param (ref null (shared extern)) i32) (result i32)))
 
-  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $8) (param externref i32) (result i32)))
+  ;; CHECK:      (type $18 (func (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
-  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring (type $9) (param externref i32 i32) (result (ref extern))))
+  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $7) (param (ref null $0) i32 i32) (result (ref extern))))
+
+  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $8) (param i32) (result (ref extern))))
+
+  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat (type $9) (param externref externref) (result (ref extern))))
+
+  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $10) (param externref (ref null $0) i32) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals (type $2) (param externref externref) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "test" (func $test (type $3) (param externref) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare (type $2) (param externref externref) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "length" (func $length (type $3) (param externref) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $11) (param externref i32) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring (type $12) (param externref i32 i32) (result (ref extern))))
+
+  ;; CHECK:      (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray_11 (type $13) (param (ref null $1) i32 i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_12 (type $14) (param i32) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "concat" (func $concat_13 (type $15) (param (ref null (shared extern)) (ref null (shared extern))) (result (ref (shared extern)))))
+
+  ;; CHECK:      (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray_14 (type $16) (param (ref null (shared extern)) (ref null $1) i32) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "equals" (func $equals_15 (type $4) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "test" (func $test_16 (type $5) (param (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "compare" (func $compare_17 (type $4) (param (ref null (shared extern)) (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "length" (func $length_18 (type $5) (param (ref null (shared extern))) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "charCodeAt" (func $charCodeAt_19 (type $17) (param (ref null (shared extern)) i32) (result i32)))
+
+  ;; CHECK:      (import "wasm:js-string" "substring" (func $substring_20 (type $18) (param (ref null (shared extern)) i32 i32) (result (ref (shared extern)))))
 
   ;; CHECK:      (table $table 31 31 funcref)
   (table $table 31 31 funcref)
@@ -123,7 +199,7 @@
   ;; CHECK:      (elem $elem (i32.const 0) $func)
   (elem $elem (i32.const 0) $func)
 
-  ;; CHECK:      (func $func (type $3) (result (ref extern))
+  ;; CHECK:      (func $func (type $6) (result (ref extern))
   ;; CHECK-NEXT:  (drop
   ;; CHECK-NEXT:   (ref.func $func)
   ;; CHECK-NEXT:  )