Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WebAssembly] Disable running wasm-opt on components #98373

Merged
merged 4 commits into from
Jul 23, 2024

Conversation

alexcrichton
Copy link
Contributor

This commit adds a check that disables wasm-opt for the wasm32-wasip2 target because wasm-opt doesn't support components at this time. This also fixes a minor issue from #95208 where if wasm-opt was disabled then the linker wouldn't run at all.

This commit adds a check that disables `wasm-opt` for the
`wasm32-wasip2` target because `wasm-opt` doesn't support components at
this time. This also fixes a minor issue from llvm#95208 where if `wasm-opt`
was disabled then the linker wouldn't run at all.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' labels Jul 10, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 10, 2024

@llvm/pr-subscribers-clang

Author: Alex Crichton (alexcrichton)

Changes

This commit adds a check that disables wasm-opt for the wasm32-wasip2 target because wasm-opt doesn't support components at this time. This also fixes a minor issue from #95208 where if wasm-opt was disabled then the linker wouldn't run at all.


Full diff: https://github.com/llvm/llvm-project/pull/98373.diff

1 Files Affected:

  • (modified) clang/lib/Driver/ToolChains/WebAssembly.cpp (+47-38)
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 60bd97e0ee987..2753645f4700f 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -61,6 +61,10 @@ std::string wasm::Linker::getLinkerPath(const ArgList &Args) const {
   return ToolChain.GetProgramPath(ToolChain.getDefaultLinker());
 }
 
+static bool IsWasip2(const llvm::Triple &TargetTriple) {
+  return TargetTriple.getOSName() == "wasip2";
+}
+
 void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                 const InputInfo &Output,
                                 const InputInfoList &Inputs,
@@ -158,46 +162,51 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   CmdArgs.push_back("-o");
   CmdArgs.push_back(Output.getFilename());
 
-  if (Args.hasFlag(options::OPT_wasm_opt, options::OPT_no_wasm_opt, true)) {
-    // When optimizing, if wasm-opt is available, run it.
-    std::string WasmOptPath;
-    if (Args.getLastArg(options::OPT_O_Group)) {
-      WasmOptPath = ToolChain.GetProgramPath("wasm-opt");
-      if (WasmOptPath == "wasm-opt") {
-        WasmOptPath = {};
-      }
+  // Don't use wasm-opt by default on `wasip2` as it doesn't have support for
+  // components at this time. Retain the historical default otherwise, though,
+  // of running `wasm-opt` by default.
+  bool WasmOptDefault = !IsWasip2(ToolChain.getTriple());
+  bool RunWasmOpt = Args.hasFlag(options::OPT_wasm_opt, options::OPT_no_wasm_opt, WasmOptDefault);
+
+  // If wasm-opt is enabled and optimizations are happening look for the
+  // `wasm-opt` program. If it's not found auto-disable it.
+  std::string WasmOptPath;
+  if (RunWasmOpt && Args.getLastArg(options::OPT_O_Group)) {
+    WasmOptPath = ToolChain.GetProgramPath("wasm-opt");
+    if (WasmOptPath == "wasm-opt") {
+      WasmOptPath = {};
     }
+  }
 
-    if (!WasmOptPath.empty()) {
-      CmdArgs.push_back("--keep-section=target_features");
-    }
+  if (!WasmOptPath.empty()) {
+    CmdArgs.push_back("--keep-section=target_features");
+  }
 
-    C.addCommand(std::make_unique<Command>(JA, *this,
-                                           ResponseFileSupport::AtFileCurCP(),
-                                           Linker, CmdArgs, Inputs, Output));
-
-    if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
-      if (!WasmOptPath.empty()) {
-        StringRef OOpt = "s";
-        if (A->getOption().matches(options::OPT_O4) ||
-            A->getOption().matches(options::OPT_Ofast))
-          OOpt = "4";
-        else if (A->getOption().matches(options::OPT_O0))
-          OOpt = "0";
-        else if (A->getOption().matches(options::OPT_O))
-          OOpt = A->getValue();
-
-        if (OOpt != "0") {
-          const char *WasmOpt = Args.MakeArgString(WasmOptPath);
-          ArgStringList OptArgs;
-          OptArgs.push_back(Output.getFilename());
-          OptArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt));
-          OptArgs.push_back("-o");
-          OptArgs.push_back(Output.getFilename());
-          C.addCommand(std::make_unique<Command>(
-              JA, *this, ResponseFileSupport::AtFileCurCP(), WasmOpt, OptArgs,
-              Inputs, Output));
-        }
+  C.addCommand(std::make_unique<Command>(JA, *this,
+                                         ResponseFileSupport::AtFileCurCP(),
+                                         Linker, CmdArgs, Inputs, Output));
+
+  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+    if (!WasmOptPath.empty()) {
+      StringRef OOpt = "s";
+      if (A->getOption().matches(options::OPT_O4) ||
+          A->getOption().matches(options::OPT_Ofast))
+        OOpt = "4";
+      else if (A->getOption().matches(options::OPT_O0))
+        OOpt = "0";
+      else if (A->getOption().matches(options::OPT_O))
+        OOpt = A->getValue();
+
+      if (OOpt != "0") {
+        const char *WasmOpt = Args.MakeArgString(WasmOptPath);
+        ArgStringList OptArgs;
+        OptArgs.push_back(Output.getFilename());
+        OptArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt));
+        OptArgs.push_back("-o");
+        OptArgs.push_back(Output.getFilename());
+        C.addCommand(std::make_unique<Command>(
+            JA, *this, ResponseFileSupport::AtFileCurCP(), WasmOpt, OptArgs,
+            Inputs, Output));
       }
     }
   }
@@ -241,7 +250,7 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
 }
 
 const char *WebAssembly::getDefaultLinker() const {
-  if (getOS() == "wasip2")
+  if (IsWasip2(getTriple()))
     return "wasm-component-ld";
   return "wasm-ld";
 }

@llvmbot
Copy link
Member

llvmbot commented Jul 10, 2024

@llvm/pr-subscribers-clang-driver

Author: Alex Crichton (alexcrichton)

Changes

This commit adds a check that disables wasm-opt for the wasm32-wasip2 target because wasm-opt doesn't support components at this time. This also fixes a minor issue from #95208 where if wasm-opt was disabled then the linker wouldn't run at all.


Full diff: https://github.com/llvm/llvm-project/pull/98373.diff

1 Files Affected:

  • (modified) clang/lib/Driver/ToolChains/WebAssembly.cpp (+47-38)
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 60bd97e0ee987..2753645f4700f 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -61,6 +61,10 @@ std::string wasm::Linker::getLinkerPath(const ArgList &Args) const {
   return ToolChain.GetProgramPath(ToolChain.getDefaultLinker());
 }
 
+static bool IsWasip2(const llvm::Triple &TargetTriple) {
+  return TargetTriple.getOSName() == "wasip2";
+}
+
 void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                 const InputInfo &Output,
                                 const InputInfoList &Inputs,
@@ -158,46 +162,51 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   CmdArgs.push_back("-o");
   CmdArgs.push_back(Output.getFilename());
 
-  if (Args.hasFlag(options::OPT_wasm_opt, options::OPT_no_wasm_opt, true)) {
-    // When optimizing, if wasm-opt is available, run it.
-    std::string WasmOptPath;
-    if (Args.getLastArg(options::OPT_O_Group)) {
-      WasmOptPath = ToolChain.GetProgramPath("wasm-opt");
-      if (WasmOptPath == "wasm-opt") {
-        WasmOptPath = {};
-      }
+  // Don't use wasm-opt by default on `wasip2` as it doesn't have support for
+  // components at this time. Retain the historical default otherwise, though,
+  // of running `wasm-opt` by default.
+  bool WasmOptDefault = !IsWasip2(ToolChain.getTriple());
+  bool RunWasmOpt = Args.hasFlag(options::OPT_wasm_opt, options::OPT_no_wasm_opt, WasmOptDefault);
+
+  // If wasm-opt is enabled and optimizations are happening look for the
+  // `wasm-opt` program. If it's not found auto-disable it.
+  std::string WasmOptPath;
+  if (RunWasmOpt && Args.getLastArg(options::OPT_O_Group)) {
+    WasmOptPath = ToolChain.GetProgramPath("wasm-opt");
+    if (WasmOptPath == "wasm-opt") {
+      WasmOptPath = {};
     }
+  }
 
-    if (!WasmOptPath.empty()) {
-      CmdArgs.push_back("--keep-section=target_features");
-    }
+  if (!WasmOptPath.empty()) {
+    CmdArgs.push_back("--keep-section=target_features");
+  }
 
-    C.addCommand(std::make_unique<Command>(JA, *this,
-                                           ResponseFileSupport::AtFileCurCP(),
-                                           Linker, CmdArgs, Inputs, Output));
-
-    if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
-      if (!WasmOptPath.empty()) {
-        StringRef OOpt = "s";
-        if (A->getOption().matches(options::OPT_O4) ||
-            A->getOption().matches(options::OPT_Ofast))
-          OOpt = "4";
-        else if (A->getOption().matches(options::OPT_O0))
-          OOpt = "0";
-        else if (A->getOption().matches(options::OPT_O))
-          OOpt = A->getValue();
-
-        if (OOpt != "0") {
-          const char *WasmOpt = Args.MakeArgString(WasmOptPath);
-          ArgStringList OptArgs;
-          OptArgs.push_back(Output.getFilename());
-          OptArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt));
-          OptArgs.push_back("-o");
-          OptArgs.push_back(Output.getFilename());
-          C.addCommand(std::make_unique<Command>(
-              JA, *this, ResponseFileSupport::AtFileCurCP(), WasmOpt, OptArgs,
-              Inputs, Output));
-        }
+  C.addCommand(std::make_unique<Command>(JA, *this,
+                                         ResponseFileSupport::AtFileCurCP(),
+                                         Linker, CmdArgs, Inputs, Output));
+
+  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+    if (!WasmOptPath.empty()) {
+      StringRef OOpt = "s";
+      if (A->getOption().matches(options::OPT_O4) ||
+          A->getOption().matches(options::OPT_Ofast))
+        OOpt = "4";
+      else if (A->getOption().matches(options::OPT_O0))
+        OOpt = "0";
+      else if (A->getOption().matches(options::OPT_O))
+        OOpt = A->getValue();
+
+      if (OOpt != "0") {
+        const char *WasmOpt = Args.MakeArgString(WasmOptPath);
+        ArgStringList OptArgs;
+        OptArgs.push_back(Output.getFilename());
+        OptArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt));
+        OptArgs.push_back("-o");
+        OptArgs.push_back(Output.getFilename());
+        C.addCommand(std::make_unique<Command>(
+            JA, *this, ResponseFileSupport::AtFileCurCP(), WasmOpt, OptArgs,
+            Inputs, Output));
       }
     }
   }
@@ -241,7 +250,7 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
 }
 
 const char *WebAssembly::getDefaultLinker() const {
-  if (getOS() == "wasip2")
+  if (IsWasip2(getTriple()))
     return "wasm-component-ld";
   return "wasm-ld";
 }

Copy link

github-actions bot commented Jul 10, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@@ -61,6 +61,10 @@ std::string wasm::Linker::getLinkerPath(const ArgList &Args) const {
return ToolChain.GetProgramPath(ToolChain.getDefaultLinker());
}

static bool IsWasip2(const llvm::Triple &TargetTriple) {
return TargetTriple.getOSName() == "wasip2";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess WASI preview3 and the future will be the same. Should we invert the test and only check for wasip1 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable to me yeah 👍

Copy link
Collaborator

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we write a test for this?

@alexcrichton
Copy link
Contributor Author

Is there a way to "fake" a wasm-opt executable? I didn't find any existing tests for the wasm-opt integration and it's auto-disabled if wasm-opt isn't found on $PATH, which doesn't happen by default in the test suite, so unless I can set up wasm-opt to show up in $PATH as part of the test I'm not sure how to test

@sbc100
Copy link
Collaborator

sbc100 commented Jul 10, 2024

Is there a way to "fake" a wasm-opt executable? I didn't find any existing tests for the wasm-opt integration and it's auto-disabled if wasm-opt isn't found on $PATH, which doesn't happen by default in the test suite, so unless I can set up wasm-opt to show up in $PATH as part of the test I'm not sure how to test

Ah.. I guess if there are no existing tests then maybe this is something that is particularly hard to test.

@mh4ck-Thales
Copy link
Contributor

The tests for the use of wasm-opt are hard to integrate into the LLVM project as wasm-opt is not part of the LLVM toolchain itself (which is the initial use case for the new --no-wasm-opt flag: as LLVM is not distributed with wasm-opt by default a same compilation command silently resulted of different binaries depending on the presence or not of wasm-opt...). I guess maybe one can hack the test suite in some way for this specific case, or maybe a suitable solution could be found to integrate wasm-opt into the LLVM distributions.

@alexcrichton would it be relevant to open an issue in the binaryen repo for the support of Wasm components?

@pavelsavara
Copy link

could shell script named wasm-opt on PATH and doing nothing do the trick ?
Or even better it could write it's arguments into some file, so that they could be asserted in the test.

2c

@mh4ck-Thales
Copy link
Contributor

A shell script would work. I don't know how easy it is to create a shell script inside the test suite and use it though, and it would be nice if this fake wasm-opt script could be unique across several tests, to ensure the consistency of those.

@alexcrichton
Copy link
Contributor Author

Ah yeah unfortunately I think it still comes back to how to do all this in the test harness. If there are examples of this elsewhere I'd be happy to investigate and copy. I'm also not sure if shell scripts would work for Windows...

@sbc100 if you're ok with this without a test though would you be able to merge for me?

@alexcrichton
Copy link
Contributor Author

would it be relevant to open an issue in the binaryen repo for the support of Wasm components?

Oh sorry forgot to respond to this as well. I'm not personally part of the binaryen repo but I suspect they would not object to having an issue to track this.

@sbc100
Copy link
Collaborator

sbc100 commented Jul 11, 2024

I think the problem with creating a dummy shell script is that it would need to work on windows too.. I guess it would be better to have test that run on some platforms that no test at all.

In any case, I'm OK with having this land as-is for now, since this is feature that is already untested.

@mh4ck-Thales
Copy link
Contributor

Seems like bash is present on the GitHub Windows runners. I shouldn't be too hard to create a simple bash script that work both on Windows and Linux. It would add a new dependency for the test suite on Windows however (if bash is not already a dependency for Windows)

@mh4ck-Thales
Copy link
Contributor

@alexcrichton sorry I thought that binaryen was under the bytecode alliance and not the webassembly org. I opened the issue here : WebAssembly/binaryen#6728 , and proposed your idea for a solution.

@alexcrichton
Copy link
Contributor Author

@sbc100 oh I can't merge things myself so if you'd be ok merging for me that'd be appreciated

@alexcrichton
Copy link
Contributor Author

ping @sbc100 would you be able to merge this for me?

@sunfishcode sunfishcode merged commit b4ebf2d into llvm:main Jul 23, 2024
7 checks passed
yuxuanchen1997 pushed a commit that referenced this pull request Jul 25, 2024
Summary:
This commit adds a check that disables `wasm-opt` for the
`wasm32-wasip2` target because `wasm-opt` doesn't support components at
this time. This also fixes a minor issue from #95208 where if `wasm-opt`
was disabled then the linker wouldn't run at all.

Test Plan: 

Reviewers: 

Subscribers: 

Tasks: 

Tags: 


Differential Revision: https://phabricator.intern.facebook.com/D60251310
@alexcrichton alexcrichton deleted the disable-wasm-opt-on-wasip2 branch July 29, 2024 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants