diff options
-rw-r--r-- | src/passes/ExtractFunction.cpp | 4 | ||||
-rw-r--r-- | src/support/command-line.cpp | 9 | ||||
-rw-r--r-- | src/support/command-line.h | 14 | ||||
-rw-r--r-- | src/tools/optimization-options.h | 28 | ||||
-rw-r--r-- | test/passes/extract-function=foo.txt (renamed from test/passes/extract-function_pass-arg=extract@foo.txt) | 0 | ||||
-rw-r--r-- | test/passes/extract-function=foo.wast (renamed from test/passes/extract-function_pass-arg=extract@foo.wast) | 0 | ||||
-rw-r--r-- | test/passes/extract-function_pass-arg=extract-function@foo.txt | 28 | ||||
-rw-r--r-- | test/passes/extract-function_pass-arg=extract-function@foo.wast | 36 |
8 files changed, 104 insertions, 15 deletions
diff --git a/src/passes/ExtractFunction.cpp b/src/passes/ExtractFunction.cpp index 626ac1ee7..77c0cabb6 100644 --- a/src/passes/ExtractFunction.cpp +++ b/src/passes/ExtractFunction.cpp @@ -28,8 +28,8 @@ namespace wasm { struct ExtractFunction : public Pass { void run(PassRunner* runner, Module* module) override { Name name = runner->options.getArgument( - "extract", - "ExtractFunction usage: wasm-opt --pass-arg=extract@FUNCTION_NAME"); + "extract-function", + "ExtractFunction usage: wasm-opt --extract-function@FUNCTION_NAME"); std::cerr << "extracting " << name << "\n"; bool found = false; for (auto& func : module->functions) { diff --git a/src/support/command-line.cpp b/src/support/command-line.cpp index 0e638173e..1b9f64295 100644 --- a/src/support/command-line.cpp +++ b/src/support/command-line.cpp @@ -136,11 +136,13 @@ void Options::parse(int argc, const char* argv[]) { // Positional. switch (positional) { case Arguments::Zero: + // Optional arguments must use --flag=A format, and not separated by + // spaces (which would be ambiguous). + case Arguments::Optional: std::cerr << "Unexpected positional argument '" << currentOption << "'\n"; exit(EXIT_FAILURE); case Arguments::One: - case Arguments::Optional: if (positionalsSeen) { std::cerr << "Unexpected second positional argument '" << currentOption << "' for " << positionalName << '\n'; @@ -198,11 +200,6 @@ void Options::parse(int argc, const char* argv[]) { } break; case Arguments::Optional: - if (!argument.size()) { - if (i + 1 != e) { - argument = argv[++i]; - } - } break; } option->action(this, argument); diff --git a/src/support/command-line.h b/src/support/command-line.h index 53bdbff28..99d98eec9 100644 --- a/src/support/command-line.h +++ b/src/support/command-line.h @@ -34,7 +34,19 @@ namespace wasm { class Options { public: using Action = std::function<void(Options*, const std::string&)>; - enum class Arguments { Zero, One, N, Optional }; + + enum class Arguments { + // No arguments. + Zero, + // One argument, in the form --flag A or --flag=A + One, + // Multiple arguments, in the form --flag A B C + N, + // An optional single argument, in the form --flag=A (we disallow --flag A + // as that would be ambiguous regarding whether A is another flag, or an + // argument to us). + Optional + }; bool debug; std::map<std::string, std::string> extra; diff --git a/src/tools/optimization-options.h b/src/tools/optimization-options.h index 0e6157473..b7db5d531 100644 --- a/src/tools/optimization-options.h +++ b/src/tools/optimization-options.h @@ -202,12 +202,28 @@ struct OptimizationOptions : public ToolOptions { }); // add passes in registry for (const auto& p : PassRegistry::get()->getRegisteredNames()) { - (*this).add( - std::string("--") + p, - "", - PassRegistry::get()->getPassDescription(p), - Options::Arguments::Zero, - [this, p](Options*, const std::string&) { passes.push_back(p); }); + (*this).add(std::string("--") + p, + "", + PassRegistry::get()->getPassDescription(p), + // Allow an optional parameter to a pass. If provided, it is + // the same as if using --pass-arg, that is, + // + // --foo=ARG + // + // is the same as + // + // --foo --pass-arg=foo@ARG + Options::Arguments::Optional, + [this, p](Options*, const std::string& arg) { + if (!arg.empty()) { + if (passOptions.arguments.count(p)) { + Fatal() + << "Cannot pass multiple pass arguments to " << p; + } + passOptions.arguments[p] = arg; + } + passes.push_back(p); + }); } } diff --git a/test/passes/extract-function_pass-arg=extract@foo.txt b/test/passes/extract-function=foo.txt index 3caf274c3..3caf274c3 100644 --- a/test/passes/extract-function_pass-arg=extract@foo.txt +++ b/test/passes/extract-function=foo.txt diff --git a/test/passes/extract-function_pass-arg=extract@foo.wast b/test/passes/extract-function=foo.wast index ab1d8b269..ab1d8b269 100644 --- a/test/passes/extract-function_pass-arg=extract@foo.wast +++ b/test/passes/extract-function=foo.wast diff --git a/test/passes/extract-function_pass-arg=extract-function@foo.txt b/test/passes/extract-function_pass-arg=extract-function@foo.txt new file mode 100644 index 000000000..3caf274c3 --- /dev/null +++ b/test/passes/extract-function_pass-arg=extract-function@foo.txt @@ -0,0 +1,28 @@ +(module + (type $none_=>_none (func)) + (import "env" "bar" (func $bar)) + (export "foo" (func $foo)) + (func $foo + (call $bar) + ) +) +(module + (type $none_=>_none (func)) + (import "env" "other" (func $other)) + (export "foo" (func $foo)) + (func $foo + (nop) + ) +) +(module + (type $none (func)) + (import "env" "other" (func $other)) + (table $t 10 funcref) + (elem $0 (i32.const 0) $other) + (export "foo" (func $foo)) + (func $foo + (call_indirect (type $none) + (i32.const 10) + ) + ) +) diff --git a/test/passes/extract-function_pass-arg=extract-function@foo.wast b/test/passes/extract-function_pass-arg=extract-function@foo.wast new file mode 100644 index 000000000..ab1d8b269 --- /dev/null +++ b/test/passes/extract-function_pass-arg=extract-function@foo.wast @@ -0,0 +1,36 @@ +(module + (func $foo + (call $bar) + ) + (func $bar + (call $foo) + ) + (func $other + (drop (i32.const 1)) + ) +) +(module + ;; Use another function in the table, but the table is not used in the + ;; extracted function + (table $t 10 funcref) + (elem $0 (table $t) (i32.const 0) func $other) + (func $foo + ) + (func $other + (drop (i32.const 1)) + ) +) +(module + ;; Use another function in the table, and the table *is* used. As a result, + ;; the table and its elements will remain. The called function, $other, will + ;; remain as an import that is placed in the table. + (type $none (func)) + (table $t 10 funcref) + (elem $0 (table $t) (i32.const 0) func $other) + (func $foo + (call_indirect (type $none) (i32.const 10)) + ) + (func $other + (drop (i32.const 1)) + ) +) |