diff --git a/src/support/command-line.cpp b/src/support/command-line.cpp index a80deaac123..30db3f4377d 100644 --- a/src/support/command-line.cpp +++ b/src/support/command-line.cpp @@ -231,10 +231,12 @@ void Options::parse(int argc, const char* argv[]) { // Non-positional. std::string argument; + bool explicitArg = false; auto equal = currentOption.find_first_of('='); if (equal != std::string::npos) { argument = currentOption.substr(equal + 1); currentOption = currentOption.substr(0, equal); + explicitArg = true; } Option* option = nullptr; for (auto& o : options) { @@ -262,7 +264,7 @@ void Options::parse(int argc, const char* argv[]) { } [[fallthrough]]; case Arguments::N: - if (!argument.size()) { + if (!argument.size() && !explicitArg) { if (i + 1 == e) { std::cerr << "Couldn't find expected argument for '" << currentOption << "'\n"; diff --git a/src/tools/wasm-split/split-options.h b/src/tools/wasm-split/split-options.h index 52b59d0c646..fa54103542f 100644 --- a/src/tools/wasm-split/split-options.h +++ b/src/tools/wasm-split/split-options.h @@ -17,6 +17,8 @@ #ifndef wasm_tools_wasm_split_options_h #define wasm_tools_wasm_split_options_h +#include + #include "tools/tool-options.h" namespace wasm { @@ -66,10 +68,10 @@ struct WasmSplitOptions : ToolOptions { std::string primaryOutput; std::string secondaryOutput; - std::string importNamespace; - std::string placeholderNamespacePrefix; - std::string secondaryMemoryName; - std::string exportPrefix; + std::optional importNamespace; + std::optional placeholderNamespacePrefix; + std::optional secondaryMemoryName; + std::optional exportPrefix; std::string manifestFile; std::string outPrefix; diff --git a/src/tools/wasm-split/wasm-split.cpp b/src/tools/wasm-split/wasm-split.cpp index b2e65399774..7171cc6a878 100644 --- a/src/tools/wasm-split/wasm-split.cpp +++ b/src/tools/wasm-split/wasm-split.cpp @@ -115,11 +115,11 @@ void instrumentModule(const WasmSplitOptions& options) { uint64_t moduleHash = hashFile(options.inputFiles[0]); InstrumenterConfig config; - if (options.importNamespace.size()) { - config.importNamespace = options.importNamespace; + if (options.importNamespace) { + config.importNamespace = *options.importNamespace; } - if (options.secondaryMemoryName.size()) { - config.secondaryMemoryName = options.secondaryMemoryName; + if (options.secondaryMemoryName) { + config.secondaryMemoryName = *options.secondaryMemoryName; } config.storageKind = options.storageKind; config.profileExport = options.profileExport; @@ -226,14 +226,14 @@ void setCommonSplitConfigs(ModuleSplitting::Config& config, const WasmSplitOptions& options) { config.usePlaceholders = options.usePlaceholders; config.minimizeNewExportNames = !options.passOptions.debugInfo; - if (options.importNamespace.size()) { - config.importNamespace = options.importNamespace; + if (options.importNamespace) { + config.importNamespace = *options.importNamespace; } - if (options.exportPrefix.size()) { - config.newExportPrefix = options.exportPrefix; + if (options.exportPrefix) { + config.newExportPrefix = *options.exportPrefix; } - if (options.placeholderNamespacePrefix.size()) { - config.placeholderNamespacePrefix = options.placeholderNamespacePrefix; + if (options.placeholderNamespacePrefix) { + config.placeholderNamespacePrefix = *options.placeholderNamespacePrefix; } } diff --git a/test/lit/wasm-split/instrument-in-secondary-memory-custom-names.wast b/test/lit/wasm-split/instrument-in-secondary-memory-custom-names.wast index a211e5d8a5d..b6cbee20d02 100644 --- a/test/lit/wasm-split/instrument-in-secondary-memory-custom-names.wast +++ b/test/lit/wasm-split/instrument-in-secondary-memory-custom-names.wast @@ -1,5 +1,7 @@ ;; RUN: wasm-split %s --instrument --in-secondary-memory --import-namespace=custom_env --secondary-memory-name=custom_name -all -S -o - | filecheck %s +;; RUN: wasm-split %s --instrument --in-secondary-memory --import-namespace= --secondary-memory-name= -all -S -o - | filecheck %s --check-prefix=EMPTY + ;; Check that the output round trips and validates as well ;; RUN: wasm-split %s --instrument --in-secondary-memory -all -g -o %t.wasm ;; RUN: wasm-opt -all %t.wasm -S -o - @@ -29,3 +31,11 @@ ;; CHECK: (i32.atomic.store8 $custom_name ;; CHECK: (i32.atomic.store8 $custom_name offset=1 ;; CHECK: (i32.atomic.load8_u $custom_name + +;; Do the checks for an empty import namespace and empty secondary memory name +;; as well; +;; EMPTY: (import "" "" (memory $"" 1 1 shared)) + +;; EMPTY: (i32.atomic.store8 $"" +;; EMPTY: (i32.atomic.store8 $"" offset=1 +;; EMPTY: (i32.atomic.load8_u $"" diff --git a/test/lit/wasm-split/multi-split-options.wast b/test/lit/wasm-split/multi-split-options.wast index b2286c27771..74fec290394 100644 --- a/test/lit/wasm-split/multi-split-options.wast +++ b/test/lit/wasm-split/multi-split-options.wast @@ -12,6 +12,13 @@ ;; RUN: wasm-split -all -g --multi-split %s --manifest %S/multi-split.wast.manifest --out-prefix=%t --placeholder-namespace=placeholder_env -o %t.wasm ;; RUN: wasm-dis %t.wasm | filecheck %s --check-prefix=PRIMARY-PLACEHOLDER-NAMESPACE +;; Check if empty strings work for options. +;; RUN: wasm-split -all -g --multi-split %s --manifest %S/multi-split.wast.manifest --out-prefix=%t --import-namespace= --placeholder-namespace= --export-prefix= -o %t.wasm +;; RUN: wasm-dis %t.wasm | filecheck %s --check-prefix=PRIMARY-EMPTY +;; RUN: wasm-dis %t1.wasm | filecheck %s --check-prefix=MOD1-EMPTY +;; RUN: wasm-dis %t2.wasm | filecheck %s --check-prefix=MOD2-EMPTY +;; RUN: wasm-dis %t3.wasm | filecheck %s --check-prefix=MOD3-EMPTY + (module ;; PRIMARY-OPTIONS: (type $ret-i64 (func (result i64))) @@ -23,6 +30,11 @@ ;; PRIMARY-PLACEHOLDER-NAMESPACE: (type $ret-f32 (func (result f32))) ;; PRIMARY-PLACEHOLDER-NAMESPACE: (type $ret-i32 (func (result i32))) + ;; PRIMARY-EMPTY: (type $ret-i64 (func (result i64))) + + ;; PRIMARY-EMPTY: (type $ret-f32 (func (result f32))) + + ;; PRIMARY-EMPTY: (type $ret-i32 (func (result i32))) (type $ret-i32 (func (result i32))) (type $ret-i64 (func (result i64))) (type $ret-f32 (func (result f32))) @@ -59,6 +71,38 @@ ;; MOD1-OPTIONS-NEXT: ) ;; MOD1-OPTIONS-NEXT: (i32.const 0) ;; MOD1-OPTIONS-NEXT: ) + ;; MOD1-EMPTY: (type $0 (func (result i64))) + + ;; MOD1-EMPTY: (type $1 (func (result f32))) + + ;; MOD1-EMPTY: (type $2 (func (result i32))) + + ;; MOD1-EMPTY: (import "" "table" (table $timport$0 3 funcref)) + + ;; MOD1-EMPTY: (import "" "trampoline_B" (func $trampoline_B (exact (result i64)))) + + ;; MOD1-EMPTY: (import "" "trampoline_C" (func $trampoline_C (exact (result f32)))) + + ;; MOD1-EMPTY: (elem $0 (i32.const 2) $A) + + ;; MOD1-EMPTY: (func $A (result i32) + ;; MOD1-EMPTY-NEXT: (drop + ;; MOD1-EMPTY-NEXT: (call_ref $2 + ;; MOD1-EMPTY-NEXT: (ref.func $A) + ;; MOD1-EMPTY-NEXT: ) + ;; MOD1-EMPTY-NEXT: ) + ;; MOD1-EMPTY-NEXT: (drop + ;; MOD1-EMPTY-NEXT: (call_ref $0 + ;; MOD1-EMPTY-NEXT: (ref.func $trampoline_B) + ;; MOD1-EMPTY-NEXT: ) + ;; MOD1-EMPTY-NEXT: ) + ;; MOD1-EMPTY-NEXT: (drop + ;; MOD1-EMPTY-NEXT: (call_ref $1 + ;; MOD1-EMPTY-NEXT: (ref.func $trampoline_C) + ;; MOD1-EMPTY-NEXT: ) + ;; MOD1-EMPTY-NEXT: ) + ;; MOD1-EMPTY-NEXT: (i32.const 0) + ;; MOD1-EMPTY-NEXT: ) (func $A (type $ret-i32) (result i32) (drop (call_ref $ret-i32 @@ -110,6 +154,38 @@ ;; MOD2-OPTIONS-NEXT: ) ;; MOD2-OPTIONS-NEXT: (i64.const 0) ;; MOD2-OPTIONS-NEXT: ) + ;; MOD2-EMPTY: (type $0 (func (result i32))) + + ;; MOD2-EMPTY: (type $1 (func (result f32))) + + ;; MOD2-EMPTY: (type $2 (func (result i64))) + + ;; MOD2-EMPTY: (import "" "table" (table $timport$0 3 funcref)) + + ;; MOD2-EMPTY: (import "" "trampoline_A" (func $trampoline_A (exact (result i32)))) + + ;; MOD2-EMPTY: (import "" "trampoline_C" (func $trampoline_C (exact (result f32)))) + + ;; MOD2-EMPTY: (elem $0 (i32.const 0) $B) + + ;; MOD2-EMPTY: (func $B (result i64) + ;; MOD2-EMPTY-NEXT: (drop + ;; MOD2-EMPTY-NEXT: (call_ref $0 + ;; MOD2-EMPTY-NEXT: (ref.func $trampoline_A) + ;; MOD2-EMPTY-NEXT: ) + ;; MOD2-EMPTY-NEXT: ) + ;; MOD2-EMPTY-NEXT: (drop + ;; MOD2-EMPTY-NEXT: (call_ref $2 + ;; MOD2-EMPTY-NEXT: (ref.func $B) + ;; MOD2-EMPTY-NEXT: ) + ;; MOD2-EMPTY-NEXT: ) + ;; MOD2-EMPTY-NEXT: (drop + ;; MOD2-EMPTY-NEXT: (call_ref $1 + ;; MOD2-EMPTY-NEXT: (ref.func $trampoline_C) + ;; MOD2-EMPTY-NEXT: ) + ;; MOD2-EMPTY-NEXT: ) + ;; MOD2-EMPTY-NEXT: (i64.const 0) + ;; MOD2-EMPTY-NEXT: ) (func $B (type $ret-i64) (result i64) (drop (call_ref $ret-i32 @@ -161,6 +237,38 @@ ;; MOD3-OPTIONS-NEXT: ) ;; MOD3-OPTIONS-NEXT: (f32.const 0) ;; MOD3-OPTIONS-NEXT: ) + ;; MOD3-EMPTY: (type $0 (func (result i32))) + + ;; MOD3-EMPTY: (type $1 (func (result i64))) + + ;; MOD3-EMPTY: (type $2 (func (result f32))) + + ;; MOD3-EMPTY: (import "" "table" (table $timport$0 3 funcref)) + + ;; MOD3-EMPTY: (import "" "trampoline_A" (func $trampoline_A (exact (result i32)))) + + ;; MOD3-EMPTY: (import "" "trampoline_B" (func $trampoline_B (exact (result i64)))) + + ;; MOD3-EMPTY: (elem $0 (i32.const 1) $C) + + ;; MOD3-EMPTY: (func $C (result f32) + ;; MOD3-EMPTY-NEXT: (drop + ;; MOD3-EMPTY-NEXT: (call_ref $0 + ;; MOD3-EMPTY-NEXT: (ref.func $trampoline_A) + ;; MOD3-EMPTY-NEXT: ) + ;; MOD3-EMPTY-NEXT: ) + ;; MOD3-EMPTY-NEXT: (drop + ;; MOD3-EMPTY-NEXT: (call_ref $1 + ;; MOD3-EMPTY-NEXT: (ref.func $trampoline_B) + ;; MOD3-EMPTY-NEXT: ) + ;; MOD3-EMPTY-NEXT: ) + ;; MOD3-EMPTY-NEXT: (drop + ;; MOD3-EMPTY-NEXT: (call_ref $2 + ;; MOD3-EMPTY-NEXT: (ref.func $C) + ;; MOD3-EMPTY-NEXT: ) + ;; MOD3-EMPTY-NEXT: ) + ;; MOD3-EMPTY-NEXT: (f32.const 0) + ;; MOD3-EMPTY-NEXT: ) (func $C (type $ret-f32) (result f32) (drop (call_ref $ret-i32 @@ -245,3 +353,39 @@ ;; PRIMARY-PLACEHOLDER-NAMESPACE-NEXT: (i32.const 2) ;; PRIMARY-PLACEHOLDER-NAMESPACE-NEXT: ) ;; PRIMARY-PLACEHOLDER-NAMESPACE-NEXT: ) + +;; PRIMARY-EMPTY: (import ".2" "0" (func $placeholder_0 (result i64))) + +;; PRIMARY-EMPTY: (import ".3" "1" (func $placeholder_1 (result f32))) + +;; PRIMARY-EMPTY: (import ".1" "2" (func $placeholder_2 (result i32))) + +;; PRIMARY-EMPTY: (table $0 3 funcref) + +;; PRIMARY-EMPTY: (elem $0 (i32.const 0) $placeholder_0 $placeholder_1 $placeholder_2) + +;; PRIMARY-EMPTY: (export "trampoline_B" (func $trampoline_B)) + +;; PRIMARY-EMPTY: (export "trampoline_C" (func $trampoline_C)) + +;; PRIMARY-EMPTY: (export "trampoline_A" (func $trampoline_A)) + +;; PRIMARY-EMPTY: (export "table" (table $0)) + +;; PRIMARY-EMPTY: (func $trampoline_B (result i64) +;; PRIMARY-EMPTY-NEXT: (call_indirect (type $ret-i64) +;; PRIMARY-EMPTY-NEXT: (i32.const 0) +;; PRIMARY-EMPTY-NEXT: ) +;; PRIMARY-EMPTY-NEXT: ) + +;; PRIMARY-EMPTY: (func $trampoline_C (result f32) +;; PRIMARY-EMPTY-NEXT: (call_indirect (type $ret-f32) +;; PRIMARY-EMPTY-NEXT: (i32.const 1) +;; PRIMARY-EMPTY-NEXT: ) +;; PRIMARY-EMPTY-NEXT: ) + +;; PRIMARY-EMPTY: (func $trampoline_A (result i32) +;; PRIMARY-EMPTY-NEXT: (call_indirect (type $ret-i32) +;; PRIMARY-EMPTY-NEXT: (i32.const 2) +;; PRIMARY-EMPTY-NEXT: ) +;; PRIMARY-EMPTY-NEXT: )