summaryrefslogtreecommitdiff
path: root/src/tools/wasm-split/wasm-split.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/wasm-split/wasm-split.cpp')
-rw-r--r--src/tools/wasm-split/wasm-split.cpp109
1 files changed, 91 insertions, 18 deletions
diff --git a/src/tools/wasm-split/wasm-split.cpp b/src/tools/wasm-split/wasm-split.cpp
index 871d6bc95..43db1b7d2 100644
--- a/src/tools/wasm-split/wasm-split.cpp
+++ b/src/tools/wasm-split/wasm-split.cpp
@@ -17,6 +17,8 @@
// wasm-split: Split a module in two or instrument a module to inform future
// splitting.
+#include <fstream>
+
#include "ir/module-splitting.h"
#include "ir/names.h"
#include "support/file.h"
@@ -149,6 +151,34 @@ ProfileData readProfile(const std::string& file) {
return {hash, timestamps};
}
+void getFunctionsToKeepAndSplit(Module& wasm,
+ uint64_t wasmHash,
+ const std::string& profileFile,
+ std::set<Name>& keepFuncs,
+ std::set<Name>& splitFuncs) {
+ ProfileData profile = readProfile(profileFile);
+ if (profile.hash != wasmHash) {
+ Fatal() << "error: checksum in profile does not match module checksum. "
+ << "The split module must be the original module that was "
+ << "instrumented to generate the profile.";
+ }
+
+ size_t i = 0;
+ ModuleUtils::iterDefinedFunctions(wasm, [&](Function* func) {
+ if (i >= profile.timestamps.size()) {
+ Fatal() << "Unexpected end of profile data";
+ }
+ if (profile.timestamps[i++] > 0) {
+ keepFuncs.insert(func->name);
+ } else {
+ splitFuncs.insert(func->name);
+ }
+ });
+ if (i != profile.timestamps.size()) {
+ Fatal() << "Unexpected extra profile data";
+ }
+}
+
void writeSymbolMap(Module& wasm, std::string filename) {
PassOptions options;
options.arguments["symbolmap"] = filename;
@@ -175,24 +205,9 @@ void splitModule(const WasmSplitOptions& options) {
if (options.profileFile.size()) {
// Use the profile to set `keepFuncs`.
uint64_t hash = hashFile(options.inputFiles[0]);
- ProfileData profile = readProfile(options.profileFile);
- if (profile.hash != hash) {
- Fatal() << "error: checksum in profile does not match module checksum. "
- << "The split module must be the original module that was "
- << "instrumented to generate the profile.";
- }
- size_t i = 0;
- ModuleUtils::iterDefinedFunctions(wasm, [&](Function* func) {
- if (i >= profile.timestamps.size()) {
- Fatal() << "Unexpected end of profile data";
- }
- if (profile.timestamps[i++] > 0) {
- keepFuncs.insert(func->name);
- }
- });
- if (i != profile.timestamps.size()) {
- Fatal() << "Unexpected extra profile data";
- }
+ std::set<Name> splitFuncs;
+ getFunctionsToKeepAndSplit(
+ wasm, hash, options.profileFile, keepFuncs, splitFuncs);
} else if (options.keepFuncs.size()) {
// Use the explicitly provided `keepFuncs`.
for (auto& func : options.keepFuncs) {
@@ -385,6 +400,61 @@ void mergeProfiles(const WasmSplitOptions& options) {
buffer.writeTo(out.getStream());
}
+std::string unescape(std::string input) {
+ std::string output;
+ for (size_t i = 0; i < input.length(); i++) {
+ if ((input[i] == '\\') && (i + 2 < input.length()) &&
+ isxdigit(input[i + 1]) && isxdigit(input[i + 2])) {
+ std::string byte = input.substr(i + 1, 2);
+ i += 2;
+ char chr = (char)(int)strtol(byte.c_str(), nullptr, 16);
+ output.push_back(chr);
+ } else {
+ output.push_back(input[i]);
+ }
+ }
+ return output;
+}
+
+void checkExists(const std::string& path) {
+ std::ifstream infile(path);
+ if (!infile.is_open()) {
+ Fatal() << "File not found: " << path;
+ }
+}
+
+void printReadableProfile(const WasmSplitOptions& options) {
+ const std::string wasmFile(options.inputFiles[0]);
+ checkExists(options.profileFile);
+ checkExists(wasmFile);
+
+ Module wasm;
+ parseInput(wasm, options);
+
+ std::set<Name> keepFuncs;
+ std::set<Name> splitFuncs;
+
+ uint64_t hash = hashFile(wasmFile);
+ getFunctionsToKeepAndSplit(
+ wasm, hash, options.profileFile, keepFuncs, splitFuncs);
+
+ auto printFnSet = [&](auto funcs, std::string prefix) {
+ for (auto it = funcs.begin(); it != funcs.end(); ++it) {
+ std::cout << prefix << " "
+ << (options.unescape ? unescape(it->c_str()) : it->c_str())
+ << std::endl;
+ }
+ };
+
+ std::cout << "Keeping functions: " << std::endl;
+ printFnSet(keepFuncs, "+");
+ std::cout << std::endl;
+
+ std::cout << "Splitting out functions: " << std::endl;
+ printFnSet(splitFuncs, "-");
+ std::cout << std::endl;
+}
+
} // anonymous namespace
int main(int argc, const char* argv[]) {
@@ -405,5 +475,8 @@ int main(int argc, const char* argv[]) {
case WasmSplitOptions::Mode::MergeProfiles:
mergeProfiles(options);
break;
+ case WasmSplitOptions::Mode::PrintProfile:
+ printReadableProfile(options);
+ break;
}
}