diff options
author | Alon Zakai <azakai@google.com> | 2024-02-13 17:09:30 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-13 17:09:30 -0800 |
commit | 9784f012848a7eb321c2037bdb363dfe0eab8bc9 (patch) | |
tree | 413f22ba04b2c4f8191e2d399cb6e4e6461d74ac /src | |
parent | 78516ae1febad02ebf3162f5db9debc8904e8e74 (diff) | |
download | binaryen-9784f012848a7eb321c2037bdb363dfe0eab8bc9.tar.gz binaryen-9784f012848a7eb321c2037bdb363dfe0eab8bc9.tar.bz2 binaryen-9784f012848a7eb321c2037bdb363dfe0eab8bc9.zip |
StringLowering: Use an array16 type in its own rec group (#6302)
The input module might use an array of 16-bit elements type that is somewhere in a
giant rec group, but that is not valid for imported strings: that array type is now on an
import and must match the expected ABI, which is to be in its own personal rec group.
The old array16 type remains in the module after this transformation, but all uses of it
are replaced with uses of the new array16 type.
Also move makeImports to after updateTypes: there are no types to update in the new
imports. That does not matter but it can make debugging less pleasant, so improve it.
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/StringLowering.cpp | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/src/passes/StringLowering.cpp b/src/passes/StringLowering.cpp index 1a5610608..d0487f602 100644 --- a/src/passes/StringLowering.cpp +++ b/src/passes/StringLowering.cpp @@ -189,12 +189,12 @@ struct StringLowering : public StringGathering { // First, run the gathering operation so all string.consts are in one place. StringGathering::run(module); - // Lower the string.const globals into imports. - makeImports(module); - // Remove all HeapType::string etc. in favor of externref. updateTypes(module); + // Lower the string.const globals into imports. + makeImports(module); + // Replace string.* etc. operations with imported ones. replaceInstructions(module); @@ -230,6 +230,11 @@ struct StringLowering : public StringGathering { CustomSection{"string.consts", std::move(vec)}); } + // Common types used in imports. + Type nullArray16 = Type(Array(Field(Field::i16, Mutable)), Nullable); + Type nullExt = Type(HeapType::ext, Nullable); + Type nnExt = Type(HeapType::ext, NonNullable); + void updateTypes(Module* module) { TypeMapper::TypeUpdates updates; @@ -240,8 +245,24 @@ struct StringLowering : public StringGathering { updates[HeapType::stringview_wtf16] = HeapType::ext; updates[HeapType::stringview_iter] = HeapType::ext; + // The module may have its own array16 type inside a big rec group, but + // imported strings expects that type in its own rec group as part of the + // ABI. Fix that up here. (This is valid to do as this type has no sub- or + // super-types anyhow; it is "plain old data" for communicating with the + // outside.) + auto allTypes = ModuleUtils::collectHeapTypes(*module); + auto array16 = nullArray16.getHeapType(); + auto array16Element = array16.getArray().element; + for (auto type : allTypes) { + // Match an array type with no super and that is closed. + if (type.isArray() && !type.getDeclaredSuperType() && !type.isOpen() && + type.getArray().element == array16Element) { + updates[type] = array16; + } + } + // We consider all types that use strings as modifiable, which means we - // mark them as non-private. That is, we are doing something TypeMapper + // mark them as non-public. That is, we are doing something TypeMapper // normally does not, as we are changing the external interface/ABI of the // module: we are changing that ABI from using strings to externs. auto publicTypes = ModuleUtils::getPublicHeapTypes(*module); @@ -268,11 +289,6 @@ struct StringLowering : public StringGathering { // The name of the module to import string functions from. Name WasmStringsModule = "wasm:js-string"; - // Common types used in imports. - Type nullArray16 = Type(Array(Field(Field::i16, Mutable)), Nullable); - Type nullExt = Type(HeapType::ext, Nullable); - Type nnExt = Type(HeapType::ext, NonNullable); - // 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) { |