diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp index b8c2573d6265fb..b7c6efab83e806 100644 --- a/clang/lib/Driver/ToolChains/WebAssembly.cpp +++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp @@ -44,8 +44,15 @@ std::string wasm::Linker::getLinkerPath(const ArgList &Args) const { llvm::sys::fs::can_execute(UseLinker)) return std::string(UseLinker); - // Accept 'lld', and 'ld' as aliases for the default linker - if (UseLinker != "lld" && UseLinker != "ld") + // Interpret 'lld' as explicitly requesting `wasm-ld`, so look for that + // linker. Note that for `wasm32-wasip2` this overrides the default linker + // of `wasm-component-ld`. + if (UseLinker == "lld") { + return ToolChain.GetProgramPath("wasm-ld"); + } + + // Allow 'ld' as an alias for the default linker + if (UseLinker != "ld") ToolChain.getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args); } @@ -73,6 +80,16 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_s)) CmdArgs.push_back("--strip-all"); + // On `wasip2` the default linker is `wasm-component-ld` which wraps the + // execution of `wasm-ld`. Find `wasm-ld` and pass it as an argument of where + // to find it to avoid it needing to hunt and rediscover or search `PATH` for + // where it is. + if (llvm::sys::path::stem(Linker).ends_with_insensitive( + "wasm-component-ld")) { + CmdArgs.push_back("--wasm-ld-path"); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetProgramPath("wasm-ld"))); + } + Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u}); ToolChain.AddFilePathLibArgs(Args, CmdArgs); @@ -221,6 +238,12 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple, } } +const char *WebAssembly::getDefaultLinker() const { + if (getOS() == "wasip2") + return "wasm-component-ld"; + return "wasm-ld"; +} + bool WebAssembly::IsMathErrnoDefault() const { return false; } bool WebAssembly::IsObjCNonFragileABIDefault() const { return true; } diff --git a/clang/lib/Driver/ToolChains/WebAssembly.h b/clang/lib/Driver/ToolChains/WebAssembly.h index ae60f464c10818..76e0ca39bd748d 100644 --- a/clang/lib/Driver/ToolChains/WebAssembly.h +++ b/clang/lib/Driver/ToolChains/WebAssembly.h @@ -67,7 +67,7 @@ class LLVM_LIBRARY_VISIBILITY WebAssembly final : public ToolChain { llvm::opt::ArgStringList &CmdArgs) const override; SanitizerMask getSupportedSanitizers() const override; - const char *getDefaultLinker() const override { return "wasm-ld"; } + const char *getDefaultLinker() const override; CXXStdlibType GetDefaultCXXStdlibType() const override { return ToolChain::CST_Libcxx; diff --git a/clang/test/Driver/wasm-toolchain.c b/clang/test/Driver/wasm-toolchain.c index f950283ec42aa0..88590a3ba4c453 100644 --- a/clang/test/Driver/wasm-toolchain.c +++ b/clang/test/Driver/wasm-toolchain.c @@ -197,3 +197,27 @@ // RUN: not %clang -### %s --target=wasm32-unknown-unknown --sysroot=%s/no-sysroot-there -fPIC -mno-mutable-globals %s 2>&1 \ // RUN: | FileCheck -check-prefix=PIC_NO_MUTABLE_GLOBALS %s // PIC_NO_MUTABLE_GLOBALS: error: invalid argument '-fPIC' not allowed with '-mno-mutable-globals' + +// Test that `wasm32-wasip2` invokes the `wasm-component-ld` linker by default +// instead of `wasm-ld`. + +// RUN: %clang -### -O2 --target=wasm32-wasip2 %s --sysroot /foo 2>&1 \ +// RUN: | FileCheck -check-prefix=LINK_WASIP2 %s +// LINK_WASIP2: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// LINK_WASIP2: wasm-component-ld{{.*}}" "-L/foo/lib/wasm32-wasip2" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" + +// Test that on `wasm32-wasip2` the `wasm-component-ld` programs is told where +// to find `wasm-ld` by default. + +// RUN: %clang -### -O2 --target=wasm32-wasip2 %s --sysroot /foo 2>&1 \ +// RUN: | FileCheck -check-prefix=LINK_WASIP2_FIND_WASMLD %s +// LINK_WASIP2_FIND_WASMLD: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// LINK_WASIP2_FIND_WASMLD: wasm-component-ld{{.*}}" {{.*}} "--wasm-ld-path" "{{.*}}wasm-ld{{.*}}" {{.*}} "[[temp]]" {{.*}} + +// If `wasm32-wasip2` is configured with `wasm-ld` as a linker then don't pass +// the `--wasm-ld-path` flag. + +// RUN: %clang -### -O2 --target=wasm32-wasip2 -fuse-ld=lld %s --sysroot /foo 2>&1 \ +// RUN: | FileCheck -check-prefix=LINK_WASIP2_USE_WASMLD %s +// LINK_WASIP2_USE_WASMLD: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// LINK_WASIP2_USE_WASMLD: wasm-ld{{.*}}" "-m" "wasm32" {{.*}} "[[temp]]" {{.*}}