diff options
-rwxr-xr-x | scripts/fuzz_opt.py | 23 | ||||
-rw-r--r-- | src/ir/module-utils.h | 13 | ||||
-rw-r--r-- | src/passes/RoundTrip.cpp | 43 | ||||
-rw-r--r-- | src/tools/wasm-opt.cpp | 39 | ||||
-rw-r--r-- | test/passes/roundtrip.txt | 4 | ||||
-rw-r--r-- | test/passes/strip-target-features_roundtrip_print-features_all-features.txt | 22 | ||||
-rw-r--r-- | test/passes/strip-target-features_roundtrip_print-features_all-features.wast | 14 |
7 files changed, 74 insertions, 84 deletions
diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py index bc3b9fd5d..b3310cad0 100755 --- a/scripts/fuzz_opt.py +++ b/scripts/fuzz_opt.py @@ -450,7 +450,7 @@ class CompareVMs(TestCaseHandler): class FuzzExec(TestCaseHandler): def get_commands(self, wasm, opts, random_seed): return [ - '%(MAX_INTERPRETER_ENV_VAR)s=%(MAX_INTERPRETER_DEPTH)d %(wasm_opt)s --fuzz-exec --fuzz-binary %(opts)s %(wasm)s' % { + '%(MAX_INTERPRETER_ENV_VAR)s=%(MAX_INTERPRETER_DEPTH)d %(wasm_opt)s --fuzz-exec %(opts)s %(wasm)s' % { 'MAX_INTERPRETER_ENV_VAR': MAX_INTERPRETER_ENV_VAR, 'MAX_INTERPRETER_DEPTH': MAX_INTERPRETER_DEPTH, 'wasm_opt': in_bin('wasm-opt'), @@ -764,16 +764,25 @@ opt_choices = [ def randomize_opt_flags(): - ret = [] + flag_groups = [] + has_flatten = False # core opts while 1: choice = random.choice(opt_choices) - if '--flatten' in ret and '--flatten' in choice: - print('avoiding multiple --flatten in a single command, due to exponential overhead') - else: - ret += choice - if len(ret) > 20 or random.random() < 0.3: + if '--flatten' in choice: + if has_flatten: + print('avoiding multiple --flatten in a single command, due to exponential overhead') + continue + else: + has_flatten = True + flag_groups.append(choice) + if len(flag_groups) > 20 or random.random() < 0.3: break + # maybe add an extra round trip + if random.random() < 0.5: + pos = random.randint(0, len(flag_groups)) + flag_groups = flag_groups[:pos] + [['--roundtrip']] + flag_groups[pos:] + ret = [flag for group in flag_groups for flag in group] # modifiers (if not already implied by a -O? option) if '-O' not in str(ret): if random.random() < 0.5: diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h index e589f5052..ab23649f7 100644 --- a/src/ir/module-utils.h +++ b/src/ir/module-utils.h @@ -99,17 +99,8 @@ inline void copyModule(const Module& in, Module& out) { } inline void clearModule(Module& wasm) { - wasm.exports.clear(); - wasm.functions.clear(); - wasm.globals.clear(); - wasm.events.clear(); - wasm.table.clear(); - wasm.memory.clear(); - wasm.start = Name(); - wasm.userSections.clear(); - wasm.debugInfoFileNames.clear(); - wasm.updateMaps(); - wasm.allocator.clear(); + wasm.~Module(); + new (&wasm) Module; } // Renaming diff --git a/src/passes/RoundTrip.cpp b/src/passes/RoundTrip.cpp index 5410ad87b..754881fe4 100644 --- a/src/passes/RoundTrip.cpp +++ b/src/passes/RoundTrip.cpp @@ -20,17 +20,9 @@ // parameter. // -#ifdef _WIN32 -#include <io.h> -#endif - -#include <cstdlib> -#include <vector> - #include "ir/module-utils.h" #include "pass.h" -#include "support/file.h" -#include "wasm-io.h" +#include "wasm-binary.h" #include "wasm.h" using namespace std; @@ -39,28 +31,19 @@ namespace wasm { struct RoundTrip : public Pass { void run(PassRunner* runner, Module* module) override { - std::string templateName = "byn_round_trip_XXXXXX"; - std::vector<char> buffer(templateName.begin(), templateName.end()); - buffer.push_back(0); -#ifndef _WIN32 - auto fd = mkstemp(buffer.data()); - WASM_UNUSED(fd); - std::string tempName(buffer.begin(), buffer.end()); -#else - std::string tempName = _mktemp(buffer.data()); -#endif - // Write - ModuleWriter writer; - writer.setBinary(true); - writer.setDebugInfo(runner->options.debugInfo); - writer.write(*module, tempName); - // Read + BufferWithRandomAccess buffer; + // Save features, which would not otherwise make it through a round trip if + // the target features section has been stripped. + auto features = module->features; + // Write, clear, and read the module + WasmBinaryWriter(module, buffer).write(); ModuleUtils::clearModule(*module); - ModuleReader reader; - reader.setDWARF(runner->options.debugInfo); - reader.read(tempName, *module); - // Clean up - std::remove(tempName.c_str()); + auto input = buffer.getAsChars(); + WasmBinaryBuilder parser(*module, input); + parser.setDWARF(runner->options.debugInfo); + parser.read(); + // Reapply features + module->features = features; } }; diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index 6fd3b7c8d..a215aca32 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -79,7 +79,6 @@ int main(int argc, const char* argv[]) { bool converge = false; bool fuzzExecBefore = false; bool fuzzExecAfter = false; - bool fuzzBinary = false; std::string extraFuzzCommand; bool translateToFuzz = false; bool fuzzPasses = false; @@ -127,12 +126,6 @@ int main(int argc, const char* argv[]) { [&](Options* o, const std::string& arguments) { fuzzExecBefore = fuzzExecAfter = true; }) - .add("--fuzz-binary", - "-fb", - "Convert to binary and back after optimizations and before fuzz-exec, " - "helping fuzzing find binary format bugs", - Options::Arguments::Zero, - [&](Options* o, const std::string& arguments) { fuzzBinary = true; }) .add("--extra-fuzz-command", "-efc", "An extra command to run on the output before and after optimizing. " @@ -328,28 +321,6 @@ int main(int argc, const char* argv[]) { std::cout << "[extra-fuzz-command first output:]\n" << firstOutput << '\n'; } - Module* curr = &wasm; - Module other; - - if (fuzzExecAfter && fuzzBinary) { - BufferWithRandomAccess buffer; - // write the binary - WasmBinaryWriter writer(&wasm, buffer); - writer.write(); - // read the binary - auto input = buffer.getAsChars(); - WasmBinaryBuilder parser(other, input); - parser.read(); - options.applyFeatures(other); - if (options.passOptions.validate) { - bool valid = WasmValidator().validate(other); - if (!valid) { - Fatal() << "fuzz-binary must always generate a valid module"; - } - } - curr = &other; - } - if (!options.runningPasses()) { if (!options.quiet) { std::cerr << "warning: no passes specified, not doing any work\n"; @@ -357,9 +328,9 @@ int main(int argc, const char* argv[]) { } else { BYN_TRACE("running passes...\n"); auto runPasses = [&]() { - options.runPasses(*curr); + options.runPasses(wasm); if (options.passOptions.validate) { - bool valid = WasmValidator().validate(*curr); + bool valid = WasmValidator().validate(wasm); if (!valid) { exitOnInvalidWasm("error after opts"); } @@ -371,7 +342,7 @@ int main(int argc, const char* argv[]) { // size no longer decreasing. auto getSize = [&]() { BufferWithRandomAccess buffer; - WasmBinaryWriter writer(curr, buffer); + WasmBinaryWriter writer(&wasm, buffer); writer.write(); return buffer.size(); }; @@ -389,7 +360,7 @@ int main(int argc, const char* argv[]) { } if (fuzzExecAfter) { - results.check(*curr); + results.check(wasm); } if (options.extra.count("output") == 0) { @@ -407,7 +378,7 @@ int main(int argc, const char* argv[]) { writer.setSourceMapFilename(outputSourceMapFilename); writer.setSourceMapUrl(outputSourceMapUrl); } - writer.write(*curr, options.extra["output"]); + writer.write(wasm, options.extra["output"]); if (extraFuzzCommand.size() > 0) { auto secondOutput = runCommand(extraFuzzCommand); diff --git a/test/passes/roundtrip.txt b/test/passes/roundtrip.txt index 508676657..c2a19480d 100644 --- a/test/passes/roundtrip.txt +++ b/test/passes/roundtrip.txt @@ -6,6 +6,6 @@ ) ) (module - (memory $ 1 1) - (table $ 0 funcref) + (memory $0 1 1) + (table $0 0 funcref) ) diff --git a/test/passes/strip-target-features_roundtrip_print-features_all-features.txt b/test/passes/strip-target-features_roundtrip_print-features_all-features.txt new file mode 100644 index 000000000..c8d989c93 --- /dev/null +++ b/test/passes/strip-target-features_roundtrip_print-features_all-features.txt @@ -0,0 +1,22 @@ +--enable-threads +--enable-mutable-globals +--enable-nontrapping-float-to-int +--enable-simd +--enable-bulk-memory +--enable-sign-ext +--enable-exception-handling +--enable-tail-call +--enable-reference-types +--enable-multivalue +(module + (type $none_=>_v128_anyref (func (result v128 anyref))) + (func $foo (result v128 anyref) + (tuple.make + (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000) + (ref.null) + ) + ) + (func $bar (result v128 anyref) + (return_call $foo) + ) +) diff --git a/test/passes/strip-target-features_roundtrip_print-features_all-features.wast b/test/passes/strip-target-features_roundtrip_print-features_all-features.wast new file mode 100644 index 000000000..214289904 --- /dev/null +++ b/test/passes/strip-target-features_roundtrip_print-features_all-features.wast @@ -0,0 +1,14 @@ +;; Test that features enabled on the IR Module survive a round trip +;; even if the target features section is stripped first + +(module + (func $foo (result v128 anyref ) + (tuple.make + (v128.const i32x4 0 0 0 0) + (ref.null) + ) + ) + (func $bar (result v128 anyref) + (return_call $foo) + ) +) |