| /* |
| * Copyright 2018 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. |
| */ |
| |
| #ifndef wasm_tools_tool_options_h |
| #define wasm_tools_tool_options_h |
| |
| #include "ir/module-utils.h" |
| #include "pass.h" |
| #include "support/command-line.h" |
| |
| // |
| // Shared options for commandline tools |
| // |
| |
| namespace wasm { |
| |
| struct ToolOptions : public Options { |
| PassOptions passOptions; |
| |
| bool quiet = false; |
| bool preserveTypeOrder = false; |
| IRProfile profile = IRProfile::Normal; |
| |
| constexpr static const char* ToolOptionsCategory = "Tool options"; |
| |
| ToolOptions(const std::string& command, const std::string& description) |
| : Options(command, description) { |
| (*this) |
| .add("--mvp-features", |
| "-mvp", |
| "Disable all non-MVP features", |
| ToolOptionsCategory, |
| Arguments::Zero, |
| [this](Options*, const std::string&) { |
| enabledFeatures.setMVP(); |
| disabledFeatures.setAll(); |
| }) |
| .add("--all-features", |
| "-all", |
| "Enable all features", |
| ToolOptionsCategory, |
| Arguments::Zero, |
| [this](Options*, const std::string&) { |
| enabledFeatures.setAll(); |
| disabledFeatures.setMVP(); |
| }) |
| .add("--detect-features", |
| "", |
| "(deprecated - this flag does nothing)", |
| ToolOptionsCategory, |
| Arguments::Zero, |
| [](Options*, const std::string&) {}) |
| .add("--quiet", |
| "-q", |
| "Emit less verbose output and hide trivial warnings.", |
| ToolOptionsCategory, |
| Arguments::Zero, |
| [this](Options*, const std::string&) { quiet = true; }) |
| .add( |
| "--experimental-poppy", |
| "", |
| "Parse wast files as Poppy IR for testing purposes.", |
| ToolOptionsCategory, |
| Arguments::Zero, |
| [this](Options*, const std::string&) { profile = IRProfile::Poppy; }); |
| (*this) |
| .addFeature(FeatureSet::SignExt, "sign extension operations") |
| .addFeature(FeatureSet::Atomics, "atomic operations") |
| .addFeature(FeatureSet::MutableGlobals, "mutable globals") |
| .addFeature(FeatureSet::TruncSat, "nontrapping float-to-int operations") |
| .addFeature(FeatureSet::SIMD, "SIMD operations and types") |
| .addFeature(FeatureSet::BulkMemory, |
| "bulk memory operations", |
| FeatureSet(FeatureSet::BulkMemoryOpt)) |
| .addFeature(FeatureSet::BulkMemoryOpt, |
| "memory.copy and memory.fill", |
| FeatureSet::None, |
| FeatureSet(FeatureSet::BulkMemory)) |
| .addFeature(FeatureSet::CallIndirectOverlong, |
| "LEB encoding of call-indirect (Ignored for compatibility as " |
| "it has no effect on Binaryen)") |
| .addFeature(FeatureSet::ExceptionHandling, |
| "exception handling operations") |
| .addFeature(FeatureSet::TailCall, "tail call operations") |
| .addFeature(FeatureSet::ReferenceTypes, "reference types") |
| .addFeature(FeatureSet::Multivalue, "multivalue functions") |
| .addFeature(FeatureSet::GC, "garbage collection") |
| .addFeature(FeatureSet::Memory64, "memory64") |
| .addFeature(FeatureSet::RelaxedSIMD, "relaxed SIMD") |
| .addFeature(FeatureSet::ExtendedConst, "extended const expressions") |
| .addFeature(FeatureSet::Strings, "strings") |
| .addFeature(FeatureSet::MultiMemory, "multimemory") |
| .addFeature(FeatureSet::StackSwitching, "stack switching") |
| .addFeature(FeatureSet::SharedEverything, "shared-everything threads") |
| .addFeature(FeatureSet::FP16, "float 16 operations") |
| .addFeature(FeatureSet::CustomDescriptors, |
| "custom descriptors (RTTs) and exact references") |
| .add("--enable-typed-function-references", |
| "", |
| "Deprecated compatibility flag", |
| ToolOptionsCategory, |
| Options::Arguments::Zero, |
| [](Options* o, const std::string& argument) { |
| std::cerr |
| << "Warning: Typed function references have been made part of " |
| "GC and --enable-typed-function-references is deprecated\n"; |
| }) |
| .add("--disable-typed-function-references", |
| "", |
| "Deprecated compatibility flag", |
| ToolOptionsCategory, |
| Options::Arguments::Zero, |
| [](Options* o, const std::string& argument) { |
| std::cerr |
| << "Warning: Typed function references have been made part of " |
| "GC and --disable-typed-function-references is deprecated\n"; |
| }) |
| .add("--no-validation", |
| "-n", |
| "Disables validation, assumes inputs are correct", |
| ToolOptionsCategory, |
| Options::Arguments::Zero, |
| [this](Options* o, const std::string& argument) { |
| passOptions.validate = false; |
| }) |
| .add("--pass-arg", |
| "-pa", |
| "An argument passed along to optimization passes being run. Must be " |
| "in the form KEY@VALUE. If KEY is the name of a pass then it " |
| "applies to the closest instance of that pass before us. If KEY is " |
| "not the name of a pass then it is a global option that applies to " |
| "all pass instances that read it.", |
| ToolOptionsCategory, |
| Options::Arguments::N, |
| [this](Options*, const std::string& argument) { |
| std::string key, value; |
| auto colon = argument.find('@'); |
| if (colon == std::string::npos) { |
| key = argument; |
| value = "1"; |
| } else { |
| key = argument.substr(0, colon); |
| value = argument.substr(colon + 1); |
| } |
| |
| addPassArg(key, value); |
| }) |
| .add( |
| "--closed-world", |
| "-cw", |
| "Assume code outside of the module does not inspect or interact with " |
| "GC and function references, even if they are passed out. The outside " |
| "may hold on to them and pass them back in, but not inspect their " |
| "contents or call them.", |
| ToolOptionsCategory, |
| Options::Arguments::Zero, |
| [this](Options*, const std::string&) { |
| passOptions.closedWorld = true; |
| }) |
| .add( |
| "--preserve-type-order", |
| "", |
| "Preserve the order of types from the input (useful for debugging and " |
| "testing)", |
| ToolOptionsCategory, |
| Options::Arguments::Zero, |
| [&](Options* o, const std::string& arguments) { |
| preserveTypeOrder = true; |
| }) |
| .add("--generate-stack-ir", |
| "", |
| "generate StackIR during writing", |
| ToolOptionsCategory, |
| Options::Arguments::Zero, |
| [&](Options* o, const std::string& arguments) { |
| passOptions.generateStackIR = true; |
| }) |
| .add("--optimize-stack-ir", |
| "", |
| "optimize StackIR during writing", |
| ToolOptionsCategory, |
| Options::Arguments::Zero, |
| [&](Options* o, const std::string& arguments) { |
| // Also generate StackIR, to have something to optimize. |
| passOptions.generateStackIR = true; |
| passOptions.optimizeStackIR = true; |
| }) |
| .add("--print-stack-ir", |
| "", |
| "print StackIR during writing", |
| ToolOptionsCategory, |
| Options::Arguments::Zero, |
| [&](Options* o, const std::string& arguments) { |
| // Also generate StackIR, to have something to print. |
| passOptions.generateStackIR = true; |
| passOptions.printStackIR = &std::cout; |
| }); |
| } |
| |
| ToolOptions& addFeature(FeatureSet::Feature feature, |
| const std::string& description, |
| FeatureSet impliedEnable = FeatureSet::None, |
| FeatureSet impliedDisable = FeatureSet::None) { |
| (*this) |
| .add(std::string("--enable-") + FeatureSet::toString(feature), |
| "", |
| std::string("Enable ") + description, |
| ToolOptionsCategory, |
| Arguments::Zero, |
| [this, feature, impliedEnable](Options*, const std::string&) { |
| enabledFeatures.set(feature | impliedEnable, true); |
| disabledFeatures.set(feature | impliedEnable, false); |
| }) |
| |
| .add(std::string("--disable-") + FeatureSet::toString(feature), |
| "", |
| std::string("Disable ") + description, |
| ToolOptionsCategory, |
| Arguments::Zero, |
| [this, feature, impliedDisable](Options*, const std::string&) { |
| enabledFeatures.set(feature | impliedDisable, false); |
| disabledFeatures.set(feature | impliedDisable, true); |
| }); |
| return *this; |
| } |
| |
| void applyOptionsBeforeParse(Module& module) const { |
| module.features.enable(enabledFeatures); |
| module.features.disable(disabledFeatures); |
| } |
| |
| void applyOptionsAfterParse(Module& module) const { |
| if (!preserveTypeOrder) { |
| module.typeIndices.clear(); |
| } |
| } |
| |
| virtual void addPassArg(const std::string& key, const std::string& value) { |
| passOptions.arguments[key] = value; |
| } |
| |
| virtual ~ToolOptions() = default; |
| |
| private: |
| FeatureSet enabledFeatures = FeatureSet::Default; |
| FeatureSet disabledFeatures = FeatureSet::None; |
| }; |
| |
| } // namespace wasm |
| |
| #endif |