Add wasm-linker-path options and leave system linker path unset. (#8591)

Based on discussion at https://github.com/google/iree/pull/8584 and [on Discord](https://discord.com/channels/689900678990135345/689900680009482386/954411704765276180).

This leaves `iree-llvm-system-linker-path` unset in the build system so it always uses the search code in UnixLinkerTool or WindowsLinkerTool, rather than use the generic lld driver.

When used from an install, users can still choose to either trust the automatic discovery or explicitly specify individual linker tools. Now they can also set a different tool for WebAssembly linking.
diff --git a/build_tools/bazel/iree_bytecode_module.bzl b/build_tools/bazel/iree_bytecode_module.bzl
index 0fb1e31..c6773a7 100644
--- a/build_tools/bazel/iree_bytecode_module.bzl
+++ b/build_tools/bazel/iree_bytecode_module.bzl
@@ -76,7 +76,8 @@
                 "$(location %s)" % (translate_tool),
                 " ".join(flags),
                 "-iree-llvm-embedded-linker-path=$(location %s)" % (linker_tool),
-                "-iree-llvm-system-linker-path=$(location %s)" % (linker_tool),
+                "-iree-llvm-wasm-linker-path=$(location %s)" % (linker_tool),
+                # Note: -iree-llvm-system-linker-path is left unspecified.
                 "-o $(location %s)" % (module),
                 "$(location %s)" % (translate_src),
             ]),
diff --git a/build_tools/cmake/iree_bytecode_module.cmake b/build_tools/cmake/iree_bytecode_module.cmake
index 08fda98..ea4e77b 100644
--- a/build_tools/cmake/iree_bytecode_module.cmake
+++ b/build_tools/cmake/iree_bytecode_module.cmake
@@ -111,8 +111,9 @@
   # If an LLVM CPU backend is enabled, supply the linker tool.
   if(IREE_LLD_TARGET)
     iree_get_executable_path(_LINKER_TOOL_EXECUTABLE "lld")
-    list(APPEND _ARGS "-iree-llvm-system-linker-path=\"${_LINKER_TOOL_EXECUTABLE}\"")
     list(APPEND _ARGS "-iree-llvm-embedded-linker-path=\"${_LINKER_TOOL_EXECUTABLE}\"")
+    list(APPEND _ARGS "-iree-llvm-wasm-linker-path=\"${_LINKER_TOOL_EXECUTABLE}\"")
+    # Note: -iree-llvm-system-linker-path is left unspecified.
   endif()
 
   # Depending on the binary instead of the target here given we might not have
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.cpp b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.cpp
index f4a7abc..7cdd79b 100644
--- a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.cpp
+++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.cpp
@@ -137,12 +137,12 @@
       llvm::cl::init(targetOptions.debugSymbols));
   targetOptions.debugSymbols = clDebugSymbols;
 
-  static llvm::cl::opt<std::string> clLinkerPath(
+  static llvm::cl::opt<std::string> clSystemLinkerPath(
       "iree-llvm-system-linker-path",
       llvm::cl::desc("Tool used to link system shared libraries produced by "
                      "IREE (for -iree-llvm-link-embedded=false)."),
       llvm::cl::init(""));
-  targetOptions.linkerPath = clLinkerPath;
+  targetOptions.systemLinkerPath = clSystemLinkerPath;
 
   static llvm::cl::opt<std::string> clEmbeddedLinkerPath(
       "iree-llvm-embedded-linker-path",
@@ -151,6 +151,13 @@
       llvm::cl::init(""));
   targetOptions.embeddedLinkerPath = clEmbeddedLinkerPath;
 
+  static llvm::cl::opt<std::string> clWasmLinkerPath(
+      "iree-llvm-wasm-linker-path",
+      llvm::cl::desc("Tool used to link WebAssembly modules produced by "
+                     "IREE (for -iree-llvm-target-triple=wasm32-*)."),
+      llvm::cl::init(""));
+  targetOptions.wasmLinkerPath = clWasmLinkerPath;
+
   static llvm::cl::opt<bool> clLinkEmbedded(
       "iree-llvm-link-embedded",
       llvm::cl::desc("Links binaries into a platform-agnostic ELF to be loaded "
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.h b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.h
index a20cf0e..2a833db 100644
--- a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.h
+++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.h
@@ -41,13 +41,17 @@
   // Sanitizer Kind for CPU Kernels
   SanitizerKind sanitizerKind = SanitizerKind::kNone;
 
-  // Tool to use for linking (like lld). Acts as a prefix to the command line
-  // and can contain additional arguments.
-  std::string linkerPath;
+  // Tool to use for native platform linking (like ld on Unix or link.exe on
+  // Windows). Acts as a prefix to the command line and can contain additional
+  // arguments.
+  std::string systemLinkerPath;
 
-  // Tool to use for linking embedded ELFs specifically. Must be lld.
+  // Tool to use for linking embedded ELFs. Must be lld.
   std::string embeddedLinkerPath;
 
+  // Tool to use for linking WebAssembly modules. Must be wasm-ld or lld.
+  std::string wasmLinkerPath;
+
   // Build for the IREE embedded platform-agnostic ELF loader.
   // Note: this is ignored for target machines that do not support the ELF
   // loader, such as WebAssembly.
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LinkerTool.cpp b/iree/compiler/Dialect/HAL/Target/LLVM/LinkerTool.cpp
index 5142475..5b52c4d 100644
--- a/iree/compiler/Dialect/HAL/Target/LLVM/LinkerTool.cpp
+++ b/iree/compiler/Dialect/HAL/Target/LLVM/LinkerTool.cpp
@@ -110,8 +110,8 @@
 std::string LinkerTool::getSystemToolPath() const {
   // Always use the -iree-llvm-system-linker-path flag when specified as it's
   // explicitly telling us what to use.
-  if (!targetOptions.linkerPath.empty()) {
-    return targetOptions.linkerPath;
+  if (!targetOptions.systemLinkerPath.empty()) {
+    return targetOptions.systemLinkerPath;
   }
 
   // Allow users to override the automatic search with an environment variable.
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/internal/WasmLinkerTool.cpp b/iree/compiler/Dialect/HAL/Target/LLVM/internal/WasmLinkerTool.cpp
index 1569979..39ac106 100644
--- a/iree/compiler/Dialect/HAL/Target/LLVM/internal/WasmLinkerTool.cpp
+++ b/iree/compiler/Dialect/HAL/Target/LLVM/internal/WasmLinkerTool.cpp
@@ -37,13 +37,21 @@
  public:
   using LinkerTool::LinkerTool;
 
-  std::string getSystemToolPath() const override {
-    // First check for setting the linker explicitly.
-    auto toolPath = LinkerTool::getSystemToolPath();
-    if (!toolPath.empty()) return toolPath;
+  std::string getWasmToolPath() const {
+    // Always use the -iree-llvm-wasm-linker-path flag when specified as it's
+    // explicitly telling us what to use.
+    if (!targetOptions.wasmLinkerPath.empty()) {
+      return targetOptions.wasmLinkerPath;
+    }
+
+    // Allow overriding the automatic search with an environment variable.
+    char *linkerPath = std::getenv("IREE_LLVMAOT_WASM_LINKER_PATH");
+    if (linkerPath) {
+      return std::string(linkerPath);
+    }
 
     // No explicit linker specified, search the environment for common tools.
-    toolPath = findToolInEnvironment(
+    std::string toolPath = findToolInEnvironment(
         {"wasm-ld", "iree-lld", "lld", "ld.lld", "lld-link"});
     if (!toolPath.empty()) return toolPath;
 
@@ -79,7 +87,7 @@
     artifacts.libraryFile.close();
 
     SmallVector<std::string, 8> flags = {
-        getSystemToolPath(),
+        getWasmToolPath(),
 
         // Forces LLD to act like wasm ld and produce WebAssembly files.
         // If not specified then lld tries to figure out what it is by progname