From c93009422574e54797736ce4b346804943a14d32 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 16 Dec 2024 16:13:17 -0800 Subject: [PATCH] [wasm-reduce] Add an option to save all interim working files as we reduce (#7154) With this option, each time we reduce we save a file w.wasm.17 or such, incrementing that counter. This is useful when debugging the reducer, but might have more uses. --- src/tools/wasm-reduce.cpp | 31 +++++++++++++++++++++++++++++-- test/lit/help/wasm-reduce.test | 3 +++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index 026825118f3..3b922946232 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -83,6 +83,9 @@ static size_t timeout = 2; // default of enabling all features should work in most cases. static std::string extraFlags = "-all"; +// Whether to save all intermediate working files as we go. +static bool saveAllWorkingFiles = false; + struct ProgramResult { int code; std::string output; @@ -231,6 +234,11 @@ ProgramResult expected; // case we may try again but much later. static std::unordered_set functionsWeTriedToRemove; +// The index of the working file we save, when saveAllWorkingFiles. We must +// store this globally so that the difference instances of Reducer do not +// overlap. +static size_t workingFileIndex = 0; + struct Reducer : public WalkerPass>> { std::string command, test, working; @@ -322,7 +330,7 @@ struct Reducer if (ProgramResult(command) == expected) { std::cerr << "| command \"" << currCommand << "\" succeeded, reduced size to " << newSize << '\n'; - copy_file(test, working); + applyTestToWorking(); more = true; oldSize = newSize; } @@ -335,6 +343,16 @@ struct Reducer } } + // Apply the test file to the working file, after we saw that it successfully + // reduced the testcase. + void applyTestToWorking() { + copy_file(test, working); + + if (saveAllWorkingFiles) { + copy_file(working, working + '.' + std::to_string(workingFileIndex++)); + } + } + // does one pass of slow and destructive reduction. returns whether it // succeeded or not // the criterion here is a logical change in the program. this may actually @@ -471,7 +489,7 @@ struct Reducer void noteReduction(size_t amount = 1) { reduced += amount; - copy_file(test, working); + applyTestToWorking(); } // tests a reduction on an arbitrary child @@ -1302,6 +1320,15 @@ int main(int argc, const char* argv[]) { extraFlags = argument; std::cout << "|applying extraFlags: " << extraFlags << "\n"; }) + .add("--save-all-working", + "-saw", + "Save all intermediate working files, as $WORKING.0, .1, .2 etc", + WasmReduceOption, + Options::Arguments::Zero, + [&](Options* o, const std::string& argument) { + saveAllWorkingFiles = true; + std::cout << "|saving all intermediate working files\n"; + }) .add_positional( "INFILE", Options::Arguments::One, diff --git a/test/lit/help/wasm-reduce.test b/test/lit/help/wasm-reduce.test index d02d46fd7a7..5116b7bea12 100644 --- a/test/lit/help/wasm-reduce.test +++ b/test/lit/help/wasm-reduce.test @@ -51,6 +51,9 @@ ;; CHECK-NEXT: wasm-opt while reducing. (default: ;; CHECK-NEXT: --enable-all) ;; CHECK-NEXT: +;; CHECK-NEXT: --save-all-working,-saw Save all intermediate working files, as +;; CHECK-NEXT: $WORKING.0, .1, .2 etc +;; CHECK-NEXT: ;; CHECK-NEXT: ;; CHECK-NEXT: Tool options: ;; CHECK-NEXT: -------------