summaryrefslogtreecommitdiff
path: root/src/passes/StringLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/StringLowering.cpp')
-rw-r--r--src/passes/StringLowering.cpp64
1 files changed, 60 insertions, 4 deletions
diff --git a/src/passes/StringLowering.cpp b/src/passes/StringLowering.cpp
index f880a50b2..31e41b9e8 100644
--- a/src/passes/StringLowering.cpp
+++ b/src/passes/StringLowering.cpp
@@ -21,17 +21,18 @@
// globals, avoiding them appearing in code that can run more than once (which
// can have overhead in VMs).
//
-// Building on that, an extended version of StringGathering will also replace
-// those new globals with imported globals of type externref, for use with the
-// string imports proposal. String operations will likewise need to be lowered.
-// TODO
+// StringLowering does the same, and also replaces those new globals with
+// imported globals of type externref, for use with the string imports proposal.
+// String operations will likewise need to be lowered. TODO
//
#include <algorithm>
#include "ir/module-utils.h"
#include "ir/names.h"
+#include "ir/type-updating.h"
#include "pass.h"
+#include "support/json.h"
#include "wasm-builder.h"
#include "wasm.h"
@@ -175,6 +176,61 @@ struct StringGathering : public Pass {
}
};
+struct StringLowering : public StringGathering {
+ void run(Module* module) override {
+ if (!module->features.has(FeatureSet::Strings)) {
+ return;
+ }
+
+ // 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);
+
+ // Disable the feature here after we lowered everything away.
+ module->features.disable(FeatureSet::Strings);
+ }
+
+ void makeImports(Module* module) {
+ Index importIndex = 0;
+ json::Value stringArray;
+ stringArray.setArray();
+ std::vector<Name> importedStrings;
+ for (auto& global : module->globals) {
+ if (global->init) {
+ if (auto* c = global->init->dynCast<StringConst>()) {
+ global->module = "string.const";
+ global->base = std::to_string(importIndex);
+ importIndex++;
+ global->init = nullptr;
+
+ auto str = json::Value::make(std::string(c->string.str).c_str());
+ stringArray.push_back(str);
+ }
+ }
+ }
+
+ // Add a custom section with the JSON.
+ std::stringstream stream;
+ stringArray.stringify(stream);
+ auto str = stream.str();
+ auto vec = std::vector<char>(str.begin(), str.end());
+ module->customSections.emplace_back(
+ CustomSection{"string.consts", std::move(vec)});
+ }
+
+ void updateTypes(Module* module) {
+ TypeMapper::TypeUpdates updates;
+ updates[HeapType::string] = HeapType::ext;
+ TypeMapper(*module, updates).map();
+ }
+};
+
Pass* createStringGatheringPass() { return new StringGathering(); }
+Pass* createStringLoweringPass() { return new StringLowering(); }
} // namespace wasm