From 2f6df7ef1ca7680d3cbabea8e5bd61db4001a410 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 6 Dec 2019 14:07:25 -0800 Subject: [PATCH 1/8] Add a RoundTrip pass that will help with debug info tests --- src/ir/module-utils.h | 18 +++++++++-- src/passes/CMakeLists.txt | 1 + src/passes/RoundTrip.cpp | 61 ++++++++++++++++++++++++++++++++++++++ src/passes/pass.cpp | 1 + src/passes/passes.h | 1 + test/passes/roundtrip.txt | 7 +++++ test/passes/roundtrip.wast | 11 +++++++ 7 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 src/passes/RoundTrip.cpp create mode 100644 test/passes/roundtrip.txt create mode 100644 test/passes/roundtrip.wast diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h index f2fda908cc9..e212ae8dc45 100644 --- a/src/ir/module-utils.h +++ b/src/ir/module-utils.h @@ -105,8 +105,8 @@ inline Event* copyEvent(Event* event, Module& out) { return ret; } -inline void copyModule(Module& in, Module& out) { - // we use names throughout, not raw points, so simple copying is fine +inline void copyModule(const Module& in, Module& out) { + // we use names throughout, not raw pointers, so simple copying is fine // for everything *but* expressions for (auto& curr : in.functionTypes) { out.addFunctionType(make_unique(*curr)); @@ -136,6 +136,20 @@ inline void copyModule(Module& in, Module& out) { out.debugInfoFileNames = in.debugInfoFileNames; } +inline void clearModule(Module& wasm) { + wasm.functionTypes.clear(); + wasm.exports.clear(); + wasm.functions.clear(); + wasm.globals.clear(); + wasm.events.clear(); + wasm.table.segments.clear(); + wasm.memory.segments.clear(); + wasm.start = Name(); + wasm.userSections.clear(); + wasm.debugInfoFileNames.clear(); + wasm.updateMaps(); +} + // Renaming // Rename functions along with all their uses. diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt index 9ab735efe92..d67f7a48c05 100644 --- a/src/passes/CMakeLists.txt +++ b/src/passes/CMakeLists.txt @@ -47,6 +47,7 @@ set(passes_SOURCES PrintCallGraph.cpp PrintFeatures.cpp PrintFunctionMap.cpp + RoundTrip.cpp StackIR.cpp Strip.cpp StripTargetFeatures.cpp diff --git a/src/passes/RoundTrip.cpp b/src/passes/RoundTrip.cpp new file mode 100644 index 00000000000..f4634ec690d --- /dev/null +++ b/src/passes/RoundTrip.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2019 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// Write the module to binary, and load it from there. This is useful in +// testing to check for the effects of roundtripping in a single wasm-opt +// parameter. +// + +#include +#include + +#include "ir/module-utils.h" +#include "pass.h" +#include "support/file.h" +#include "wasm.h" +#include "wasm-io.h" + +using namespace std; + +namespace wasm { + +struct RoundTrip : public Pass { + void run(PassRunner* runner, Module* module) override { + std::string templateName = "byn_round_trip_XXXXXX"; + std::vector buffer(templateName.begin(), templateName.end()); + mkstemp(buffer.data()); + std::string tempName(buffer.begin(), buffer.end()); + // Write + ModuleWriter writer; + writer.setBinary(true); + writer.setDebugInfo(runner->options.debugInfo); + writer.write(*module, tempName); + // Read + Module newModule; + ModuleReader reader; + reader.read(tempName, newModule); + // Clean up + std::remove(tempName.c_str()); + // Swap in + ModuleUtils::clearModule(*module); + ModuleUtils::copyModule(newModule, *module); + } +}; + +Pass* createRoundTripPass() { return new RoundTrip(); } + +} // namespace wasm diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 906fb85e28b..b139a9414ea 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -276,6 +276,7 @@ void PassRegistry::registerPasses() { createReReloopPass); registerPass( "rse", "remove redundant local.sets", createRedundantSetEliminationPass); + registerPass("roundtrip", "write the module to binary, then read it", createRoundTripPass); registerPass("safe-heap", "instrument loads and stores to check for invalid behavior", createSafeHeapPass); diff --git a/src/passes/passes.h b/src/passes/passes.h index 98c7d374ddd..33a0b26da55 100644 --- a/src/passes/passes.h +++ b/src/passes/passes.h @@ -94,6 +94,7 @@ Pass* createReorderFunctionsPass(); Pass* createReorderLocalsPass(); Pass* createReReloopPass(); Pass* createRedundantSetEliminationPass(); +Pass* createRoundTripPass(); Pass* createSafeHeapPass(); Pass* createSimplifyLocalsPass(); Pass* createSimplifyGlobalsPass(); diff --git a/test/passes/roundtrip.txt b/test/passes/roundtrip.txt new file mode 100644 index 00000000000..ca74a299eb3 --- /dev/null +++ b/test/passes/roundtrip.txt @@ -0,0 +1,7 @@ +(module + (type $0 (func)) + (export "foo" (func $0)) + (func $0 (; 0 ;) + (unreachable) + ) +) diff --git a/test/passes/roundtrip.wast b/test/passes/roundtrip.wast new file mode 100644 index 00000000000..f562ba77912 --- /dev/null +++ b/test/passes/roundtrip.wast @@ -0,0 +1,11 @@ +(module + (func "foo" + ;; binaryen skips unreachable code while reading the binary format + (unreachable) + (nop) + (nop) + (nop) + (nop) + (nop) + ) +) From eb7bcad1d716b50bf3cae33f5624ee465342267e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 6 Dec 2019 14:10:03 -0800 Subject: [PATCH 2/8] format --- src/passes/RoundTrip.cpp | 2 +- src/passes/pass.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/passes/RoundTrip.cpp b/src/passes/RoundTrip.cpp index f4634ec690d..48beb2e7f64 100644 --- a/src/passes/RoundTrip.cpp +++ b/src/passes/RoundTrip.cpp @@ -26,8 +26,8 @@ #include "ir/module-utils.h" #include "pass.h" #include "support/file.h" -#include "wasm.h" #include "wasm-io.h" +#include "wasm.h" using namespace std; diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index b139a9414ea..04b33f34168 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -276,7 +276,9 @@ void PassRegistry::registerPasses() { createReReloopPass); registerPass( "rse", "remove redundant local.sets", createRedundantSetEliminationPass); - registerPass("roundtrip", "write the module to binary, then read it", createRoundTripPass); + registerPass("roundtrip", + "write the module to binary, then read it", + createRoundTripPass); registerPass("safe-heap", "instrument loads and stores to check for invalid behavior", createSafeHeapPass); From 8c20dc319b021f32fd3b082bc17f8da9e352ce95 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 6 Dec 2019 14:53:35 -0800 Subject: [PATCH 3/8] fix warning --- src/passes/RoundTrip.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/passes/RoundTrip.cpp b/src/passes/RoundTrip.cpp index 48beb2e7f64..b857b19716d 100644 --- a/src/passes/RoundTrip.cpp +++ b/src/passes/RoundTrip.cpp @@ -37,7 +37,7 @@ struct RoundTrip : public Pass { void run(PassRunner* runner, Module* module) override { std::string templateName = "byn_round_trip_XXXXXX"; std::vector buffer(templateName.begin(), templateName.end()); - mkstemp(buffer.data()); + (void)mkstemp(buffer.data()); std::string tempName(buffer.begin(), buffer.end()); // Write ModuleWriter writer; From dfa540501ba123454f08d57a64008139f4c6ddfe Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 6 Dec 2019 15:02:47 -0800 Subject: [PATCH 4/8] fix --- src/passes/RoundTrip.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/passes/RoundTrip.cpp b/src/passes/RoundTrip.cpp index b857b19716d..78d2b07caf5 100644 --- a/src/passes/RoundTrip.cpp +++ b/src/passes/RoundTrip.cpp @@ -37,6 +37,7 @@ struct RoundTrip : public Pass { void run(PassRunner* runner, Module* module) override { std::string templateName = "byn_round_trip_XXXXXX"; std::vector buffer(templateName.begin(), templateName.end()); + buffer.push_back(0); (void)mkstemp(buffer.data()); std::string tempName(buffer.begin(), buffer.end()); // Write From 844e3680819a0ba17309ff9bcf7c33a1efc7355b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 6 Dec 2019 15:10:05 -0800 Subject: [PATCH 5/8] windows --- src/passes/RoundTrip.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/passes/RoundTrip.cpp b/src/passes/RoundTrip.cpp index 78d2b07caf5..352e395487c 100644 --- a/src/passes/RoundTrip.cpp +++ b/src/passes/RoundTrip.cpp @@ -20,6 +20,10 @@ // parameter. // +#ifdef _WIN32 +#include +#endif + #include #include @@ -38,8 +42,12 @@ struct RoundTrip : public Pass { std::string templateName = "byn_round_trip_XXXXXX"; std::vector buffer(templateName.begin(), templateName.end()); buffer.push_back(0); +#ifndef _WIN32 (void)mkstemp(buffer.data()); std::string tempName(buffer.begin(), buffer.end()); +#else + std::string tempName = _mktemp(templateName.data()); +#endif // Write ModuleWriter writer; writer.setBinary(true); From a5cb38f507ed6e6ed154870dd6bd7972275d9d82 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 6 Dec 2019 15:16:01 -0800 Subject: [PATCH 6/8] windows fix --- src/passes/RoundTrip.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/passes/RoundTrip.cpp b/src/passes/RoundTrip.cpp index 352e395487c..4541b116f8d 100644 --- a/src/passes/RoundTrip.cpp +++ b/src/passes/RoundTrip.cpp @@ -46,7 +46,7 @@ struct RoundTrip : public Pass { (void)mkstemp(buffer.data()); std::string tempName(buffer.begin(), buffer.end()); #else - std::string tempName = _mktemp(templateName.data()); + std::string tempName = _mktemp(buffer.data()); #endif // Write ModuleWriter writer; From 5b4d1b415bc92fd52c7935b37653b39ddc4dd3d8 Mon Sep 17 00:00:00 2001 From: "Alon Zakai (kripken)" Date: Sat, 7 Dec 2019 13:00:42 -0800 Subject: [PATCH 7/8] fix warning --- src/passes/RoundTrip.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/passes/RoundTrip.cpp b/src/passes/RoundTrip.cpp index 4541b116f8d..626c469d53c 100644 --- a/src/passes/RoundTrip.cpp +++ b/src/passes/RoundTrip.cpp @@ -43,7 +43,8 @@ struct RoundTrip : public Pass { std::vector buffer(templateName.begin(), templateName.end()); buffer.push_back(0); #ifndef _WIN32 - (void)mkstemp(buffer.data()); + auto fd = mkstemp(buffer.data()); + WASM_UNUSED(fd); std::string tempName(buffer.begin(), buffer.end()); #else std::string tempName = _mktemp(buffer.data()); From 3e4a14637ccce8cb93d68accdd6ca47f7af530ce Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 9 Dec 2019 12:52:03 -0800 Subject: [PATCH 8/8] fuzz roundtrip --- scripts/fuzz_opt.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py index a66c599bb50..a0b763aabac 100644 --- a/scripts/fuzz_opt.py +++ b/scripts/fuzz_opt.py @@ -496,6 +496,7 @@ def write_commands(commands, filename): ["--reorder-functions"], ["--reorder-locals"], ["--flatten", "--rereloop"], + ["--roundtrip"], ["--rse"], ["--simplify-locals"], ["--simplify-locals-nonesting"],