Strip the producers section in --strip-producers (#1875)

WebAssembly/tool-conventions#93 has a summary of emscripten's current thinking on this. For Binaryen, we don't want to do anything to the producers section by default, but do want it to be possible to optionally remove it. To achieve that, this PR

 * creates a --strip-producers pass that removes that section.
 * creates a --strip-debug pass that removes debug info, same as the old --strip, which is still around but deprecated.

A followup in emscripten will use this pass by default.
diff --git a/src/passes/Strip.cpp b/src/passes/Strip.cpp
index d2ebbe1..8ab712c 100644
--- a/src/passes/Strip.cpp
+++ b/src/passes/Strip.cpp
@@ -15,10 +15,12 @@
  */
 
 //
-// Similar to strip-ing a native binary, this removes debug info
-// and related things like source map URLs, names section, etc.
+// Similar to strip-ing a native binary, this family of passes can
+// removes debug info and other things.
 //
 
+#include <functional>
+
 #include "wasm.h"
 #include "wasm-binary.h"
 #include "pass.h"
@@ -28,6 +30,12 @@
 namespace wasm {
 
 struct Strip : public Pass {
+  // A function that returns true if the method should be removed.
+  typedef std::function<bool (UserSection&)> Decider;
+  Decider decider;
+
+  Strip(Decider decider) : decider(decider) {}
+
   void run(PassRunner* runner, Module* module) override {
     // Remove name and debug sections.
     auto& sections = module->userSections;
@@ -35,12 +43,7 @@
       std::remove_if(
         sections.begin(),
         sections.end(),
-        [&](const UserSection& curr) {
-          return curr.name == BinaryConsts::UserSections::Name ||
-                 curr.name == BinaryConsts::UserSections::SourceMapUrl ||
-                 curr.name.find(".debug") == 0 ||
-                 curr.name.find("reloc..debug") == 0;
-        }
+        decider
       ),
       sections.end()
     );
@@ -53,8 +56,19 @@
   }
 };
 
-Pass *createStripPass() {
-  return new Strip();
+Pass *createStripDebugPass() {
+  return new Strip([&](const UserSection& curr) {
+    return curr.name == BinaryConsts::UserSections::Name ||
+           curr.name == BinaryConsts::UserSections::SourceMapUrl ||
+           curr.name.find(".debug") == 0 ||
+           curr.name.find("reloc..debug") == 0;
+  });
+}
+
+Pass *createStripProducersPass() {
+  return new Strip([&](const UserSection& curr) {
+    return curr.name == BinaryConsts::UserSections::Producers;
+  });
 }
 
 } // namespace wasm
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index cae6986..2872575 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -133,7 +133,9 @@
   registerPass("souperify-single-use", "emit Souper IR in text form (single-use nodes only)", createSouperifySingleUsePass);
   registerPass("spill-pointers", "spill pointers to the C stack (useful for Boehm-style GC)", createSpillPointersPass);
   registerPass("ssa", "ssa-ify variables so that they have a single assignment", createSSAifyPass);
-  registerPass("strip", "strip debug info (including the names section)", createStripPass);
+  registerPass("strip", "deprecated; same as strip-debug", createStripDebugPass);
+  registerPass("strip-debug", "strip debug info (including the names section)", createStripDebugPass);
+  registerPass("strip-producers", "strip the wasm producers section", createStripProducersPass);
   registerPass("trap-mode-clamp", "replace trapping operations with clamping semantics", createTrapModeClamp);
   registerPass("trap-mode-js", "replace trapping operations with js semantics", createTrapModeJS);
   registerPass("untee", "removes local.tees, replacing them with sets and gets", createUnteePass);
diff --git a/src/passes/passes.h b/src/passes/passes.h
index b043034..15493f3 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -84,7 +84,8 @@
 Pass* createSimplifyLocalsNoTeePass();
 Pass* createSimplifyLocalsNoStructurePass();
 Pass* createSimplifyLocalsNoTeeNoStructurePass();
-Pass* createStripPass();
+Pass* createStripDebugPass();
+Pass* createStripProducersPass();
 Pass* createSouperifyPass();
 Pass* createSouperifySingleUsePass();
 Pass* createSpillPointersPass();
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index a5b1e10..2402375 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -344,6 +344,7 @@
 extern const char* SourceMapUrl;
 extern const char* Dylink;
 extern const char* Linking;
+extern const char* Producers;
 
 enum Subsection {
   NameFunction = 1,
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 187328e..90a588b 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -719,7 +719,7 @@
   } else {
     // an unfamiliar custom section
     if (sectionName.equals(BinaryConsts::UserSections::Linking)) {
-      std::cerr << "warning: linking section is present, which binaryen cannot handle yet - relocations will be invalidated!\n";
+      std::cerr << "warning: linking section is present, so this is not a standard wasm file - binaryen cannot handle this properly!\n";
     }
     wasm.userSections.resize(wasm.userSections.size() + 1);
     auto& section = wasm.userSections.back();
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 757bc18..0d5f3d5 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -31,6 +31,7 @@
 const char* SourceMapUrl = "sourceMappingURL";
 const char* Dylink = "dylink";
 const char* Linking = "linking";
+const char* Producers = "producers";
 }
 }
 
diff --git a/test/metadatas.wasm b/test/metadatas.wasm
new file mode 100644
index 0000000..ea79730
--- /dev/null
+++ b/test/metadatas.wasm
Binary files differ
diff --git a/test/metadatas.wasm.fromBinary b/test/metadatas.wasm.fromBinary
new file mode 100644
index 0000000..2e65316
--- /dev/null
+++ b/test/metadatas.wasm.fromBinary
@@ -0,0 +1,10 @@
+(module
+ (type $0 (func))
+ (export "a" (func $0))
+ (func $0 (; 0 ;) (type $0)
+  (nop)
+ )
+ ;; custom section "emscripten_metadata", size 7
+ ;; custom section "producers", size 187
+)
+
diff --git a/test/passes/metrics_strip-debug_metrics.bin.txt b/test/passes/metrics_strip-debug_metrics.bin.txt
new file mode 100644
index 0000000..dbb3dcc
--- /dev/null
+++ b/test/passes/metrics_strip-debug_metrics.bin.txt
@@ -0,0 +1,17 @@
+total
+ [funcs]        : 1       
+ [total]        : 1       
+ nop            : 1       
+total
+ [funcs]        : 1       
+ [total]        : 1       
+ nop            : 1       
+(module
+ (type $0 (func))
+ (export "a" (func $0))
+ (func $0 (; 0 ;) (type $0)
+  (nop)
+ )
+ ;; custom section "emscripten_metadata", size 7
+ ;; custom section "producers", size 187
+)
diff --git a/test/passes/metrics_strip-debug_metrics.wasm b/test/passes/metrics_strip-debug_metrics.wasm
new file mode 100644
index 0000000..ea79730
--- /dev/null
+++ b/test/passes/metrics_strip-debug_metrics.wasm
Binary files differ
diff --git a/test/passes/metrics_strip-producers_metrics.bin.txt b/test/passes/metrics_strip-producers_metrics.bin.txt
new file mode 100644
index 0000000..6ddfa58
--- /dev/null
+++ b/test/passes/metrics_strip-producers_metrics.bin.txt
@@ -0,0 +1,16 @@
+total
+ [funcs]        : 1       
+ [total]        : 1       
+ nop            : 1       
+total
+ [funcs]        : 1       
+ [total]        : 1       
+ nop            : 1       
+(module
+ (type $0 (func))
+ (export "a" (func $0))
+ (func $0 (; 0 ;) (type $0)
+  (nop)
+ )
+ ;; custom section "emscripten_metadata", size 7
+)
diff --git a/test/passes/metrics_strip-producers_metrics.wasm b/test/passes/metrics_strip-producers_metrics.wasm
new file mode 100644
index 0000000..ea79730
--- /dev/null
+++ b/test/passes/metrics_strip-producers_metrics.wasm
Binary files differ
diff --git a/test/passes/strip.bin.txt b/test/passes/strip-debug.bin.txt
similarity index 100%
rename from test/passes/strip.bin.txt
rename to test/passes/strip-debug.bin.txt
diff --git a/test/passes/strip.wasm b/test/passes/strip-debug.wasm
similarity index 100%
rename from test/passes/strip.wasm
rename to test/passes/strip-debug.wasm
Binary files differ
diff --git a/test/passes/strip-producers.bin.txt b/test/passes/strip-producers.bin.txt
new file mode 100644
index 0000000..dcc8ab9
--- /dev/null
+++ b/test/passes/strip-producers.bin.txt
@@ -0,0 +1,22 @@
+(module
+ (type $0 (func (result i32)))
+ (import "env" "__linear_memory" (memory $0 0))
+ (import "env" "__indirect_function_table" (table $timport$1 0 funcref))
+ (func $0 (; 0 ;) (type $0) (result i32)
+  (local $0 i32)
+  (local.set $0
+   (i32.const 1)
+  )
+  (return
+   (local.get $0)
+  )
+ )
+ ;; custom section ".debug_str", size 246
+ ;; custom section ".debug_abbrev", size 52
+ ;; custom section ".debug_info", size 69
+ ;; custom section ".debug_macinfo", size 1
+ ;; custom section ".debug_line", size 56
+ ;; custom section "zinking", size 28
+ ;; custom section "reloc..debug_info", size 47
+ ;; custom section "reloc..debug_line", size 6
+)
diff --git a/test/passes/strip.wasm b/test/passes/strip-producers.wasm
similarity index 100%
copy from test/passes/strip.wasm
copy to test/passes/strip-producers.wasm
Binary files differ