diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -8200,14 +8200,19 @@ ArgStringList FeatureArgs; TC->addClangTargetOptions(TCArgs, FeatureArgs, Action::OFK_OpenMP); auto FeatureIt = llvm::find(FeatureArgs, "-target-feature"); - CmdArgs.push_back(Args.MakeArgString( - "-target-feature=" + TC->getTripleString() + "=" + *(FeatureIt + 1))); + if (FeatureIt != FeatureArgs.end()) + CmdArgs.push_back( + Args.MakeArgString("-target-feature=" + TC->getTripleString() + + "=" + *(FeatureIt + 1))); } // Pass in the bitcode library to be linked during LTO. for (auto &I : llvm::make_range(OpenMPTCRange.first, OpenMPTCRange.second)) { const ToolChain *TC = I.second; + if (!(TC->getTriple().isNVPTX() || TC->getTriple().isAMDGPU())) + continue; + const Driver &TCDriver = TC->getDriver(); const ArgList &TCArgs = C.getArgsForToolChain(TC, "", Action::OFK_OpenMP); StringRef Arch = TCArgs.getLastArgValue(options::OPT_march_EQ); diff --git a/clang/test/Driver/openmp-offload.c b/clang/test/Driver/openmp-offload.c --- a/clang/test/Driver/openmp-offload.c +++ b/clang/test/Driver/openmp-offload.c @@ -657,3 +657,9 @@ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-IS-DEVICE %s // CHK-FOPENMP-IS-DEVICE: clang{{.*}} "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" {{.*}}.c" + +/// Check arguments to the linker wrapper +// RUN: %clang -### -no-canonical-prefixes -target powerpc64le-linux -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -fopenmp-new-driver %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-NEW-DRIVER %s + +// CHK-NEW-DRIVER: clang-linker-wrapper{{.*}}"-host-triple" "powerpc64le-unknown-linux"{{.*}}--{{.*}}"-lomp"{{.*}}"-lomptarget" diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -646,6 +646,83 @@ } } // namespace amdgcn +namespace generic { + +const char *getLDMOption(const llvm::Triple &T) { + switch (T.getArch()) { + case llvm::Triple::x86: + if (T.isOSIAMCU()) + return "elf_iamcu"; + return "elf_i386"; + case llvm::Triple::aarch64: + return "aarch64linux"; + case llvm::Triple::aarch64_be: + return "aarch64linuxb"; + case llvm::Triple::ppc64: + return "elf64ppc"; + case llvm::Triple::ppc64le: + return "elf64lppc"; + case llvm::Triple::x86_64: + if (T.isX32()) + return "elf32_x86_64"; + return "elf_x86_64"; + case llvm::Triple::ve: + return "elf64ve"; + default: + return nullptr; + } +} + +Expected link(ArrayRef InputFiles, Triple TheTriple, + StringRef Arch) { + // Create a new file to write the linked device image to. + SmallString<128> TempFile; + if (Error Err = createOutputFile(sys::path::filename(ExecutableName) + "-" + + TheTriple.getArchName() + "-" + Arch, + "out", TempFile)) + return std::move(Err); + + // Use the host linker to perform generic offloading. Use the same libraries + // and paths as the host application does. + SmallVector CmdArgs; + CmdArgs.push_back(LinkerUserPath); + CmdArgs.push_back("-m"); + CmdArgs.push_back(getLDMOption(TheTriple)); + CmdArgs.push_back("-shared"); + for (auto AI = HostLinkerArgs.begin(), AE = HostLinkerArgs.end(); AI != AE; + ++AI) { + StringRef Arg = *AI; + if (Arg.startswith("-L")) + CmdArgs.push_back(Arg); + else if (Arg.startswith("-l")) + CmdArgs.push_back(Arg); + else if (Arg.startswith("--as-needed")) + CmdArgs.push_back(Arg); + else if (Arg.startswith("--no-as-needed")) + CmdArgs.push_back(Arg); + else if (Arg.startswith("-rpath")) { + CmdArgs.push_back(Arg); + CmdArgs.push_back(*(AI + 1)); + } else if (Arg.startswith("-dynamic-linker")) { + CmdArgs.push_back(Arg); + CmdArgs.push_back(*(AI + 1)); + } + } + CmdArgs.push_back("-Bsymbolic"); + CmdArgs.push_back("-o"); + CmdArgs.push_back(TempFile); + + // Add extracted input files. + for (StringRef Input : InputFiles) + CmdArgs.push_back(Input); + + if (sys::ExecuteAndWait(LinkerUserPath, CmdArgs)) + return createStringError(inconvertibleErrorCode(), "'linker' failed"); + + return static_cast(TempFile); +} +} // namespace generic + Expected linkDevice(ArrayRef InputFiles, Triple TheTriple, StringRef Arch) { switch (TheTriple.getArch()) { @@ -656,7 +733,11 @@ return amdgcn::link(InputFiles, TheTriple, Arch); case Triple::x86: case Triple::x86_64: - // TODO: x86 linking support. + case Triple::aarch64: + case Triple::aarch64_be: + case Triple::ppc64: + case Triple::ppc64le: + return generic::link(InputFiles, TheTriple, Arch); default: return createStringError(inconvertibleErrorCode(), TheTriple.getArchName() +