1fe6060f1SDimitry Andric //===- AMDGPUOpenMP.cpp - AMDGPUOpenMP ToolChain Implementation -*- C++ -*-===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric 9fe6060f1SDimitry Andric #include "AMDGPUOpenMP.h" 10fe6060f1SDimitry Andric #include "AMDGPU.h" 11fe6060f1SDimitry Andric #include "CommonArgs.h" 1269ade1e0SDimitry Andric #include "ToolChains/ROCm.h" 13fe6060f1SDimitry Andric #include "clang/Basic/DiagnosticDriver.h" 14fe6060f1SDimitry Andric #include "clang/Driver/Compilation.h" 15fe6060f1SDimitry Andric #include "clang/Driver/Driver.h" 16fe6060f1SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 17fe6060f1SDimitry Andric #include "clang/Driver/InputInfo.h" 18fe6060f1SDimitry Andric #include "clang/Driver/Options.h" 1904eeddc0SDimitry Andric #include "clang/Driver/Tool.h" 2069ade1e0SDimitry Andric #include "llvm/ADT/STLExtras.h" 21fe6060f1SDimitry Andric #include "llvm/Support/FileSystem.h" 22fe6060f1SDimitry Andric #include "llvm/Support/FormatAdapters.h" 23fe6060f1SDimitry Andric #include "llvm/Support/FormatVariadic.h" 24fe6060f1SDimitry Andric #include "llvm/Support/Path.h" 25fe6060f1SDimitry Andric 26fe6060f1SDimitry Andric using namespace clang::driver; 27fe6060f1SDimitry Andric using namespace clang::driver::toolchains; 28fe6060f1SDimitry Andric using namespace clang::driver::tools; 29fe6060f1SDimitry Andric using namespace clang; 30fe6060f1SDimitry Andric using namespace llvm::opt; 31fe6060f1SDimitry Andric 32fe6060f1SDimitry Andric namespace { 33fe6060f1SDimitry Andric 34fe6060f1SDimitry Andric static const char *getOutputFileName(Compilation &C, StringRef Base, 35fe6060f1SDimitry Andric const char *Postfix, 36fe6060f1SDimitry Andric const char *Extension) { 37fe6060f1SDimitry Andric const char *OutputFileName; 38fe6060f1SDimitry Andric if (C.getDriver().isSaveTempsEnabled()) { 39fe6060f1SDimitry Andric OutputFileName = 40fe6060f1SDimitry Andric C.getArgs().MakeArgString(Base.str() + Postfix + "." + Extension); 41fe6060f1SDimitry Andric } else { 42fe6060f1SDimitry Andric std::string TmpName = 43fe6060f1SDimitry Andric C.getDriver().GetTemporaryPath(Base.str() + Postfix, Extension); 44fe6060f1SDimitry Andric OutputFileName = C.addTempFile(C.getArgs().MakeArgString(TmpName)); 45fe6060f1SDimitry Andric } 46fe6060f1SDimitry Andric return OutputFileName; 47fe6060f1SDimitry Andric } 48fe6060f1SDimitry Andric 49fe6060f1SDimitry Andric static void addLLCOptArg(const llvm::opt::ArgList &Args, 50fe6060f1SDimitry Andric llvm::opt::ArgStringList &CmdArgs) { 51fe6060f1SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { 52fe6060f1SDimitry Andric StringRef OOpt = "0"; 53fe6060f1SDimitry Andric if (A->getOption().matches(options::OPT_O4) || 54fe6060f1SDimitry Andric A->getOption().matches(options::OPT_Ofast)) 55fe6060f1SDimitry Andric OOpt = "3"; 56fe6060f1SDimitry Andric else if (A->getOption().matches(options::OPT_O0)) 57fe6060f1SDimitry Andric OOpt = "0"; 58fe6060f1SDimitry Andric else if (A->getOption().matches(options::OPT_O)) { 59fe6060f1SDimitry Andric // Clang and opt support -Os/-Oz; llc only supports -O0, -O1, -O2 and -O3 60fe6060f1SDimitry Andric // so we map -Os/-Oz to -O2. 61fe6060f1SDimitry Andric // Only clang supports -Og, and maps it to -O1. 62fe6060f1SDimitry Andric // We map anything else to -O2. 63fe6060f1SDimitry Andric OOpt = llvm::StringSwitch<const char *>(A->getValue()) 64fe6060f1SDimitry Andric .Case("1", "1") 65fe6060f1SDimitry Andric .Case("2", "2") 66fe6060f1SDimitry Andric .Case("3", "3") 67fe6060f1SDimitry Andric .Case("s", "2") 68fe6060f1SDimitry Andric .Case("z", "2") 69fe6060f1SDimitry Andric .Case("g", "1") 70fe6060f1SDimitry Andric .Default("0"); 71fe6060f1SDimitry Andric } 72fe6060f1SDimitry Andric CmdArgs.push_back(Args.MakeArgString("-O" + OOpt)); 73fe6060f1SDimitry Andric } 74fe6060f1SDimitry Andric } 75fe6060f1SDimitry Andric 76fe6060f1SDimitry Andric static bool checkSystemForAMDGPU(const ArgList &Args, const AMDGPUToolChain &TC, 77fe6060f1SDimitry Andric std::string &GPUArch) { 78fe6060f1SDimitry Andric if (auto Err = TC.getSystemGPUArch(Args, GPUArch)) { 79fe6060f1SDimitry Andric std::string ErrMsg = 80fe6060f1SDimitry Andric llvm::formatv("{0}", llvm::fmt_consume(std::move(Err))); 81fe6060f1SDimitry Andric TC.getDriver().Diag(diag::err_drv_undetermined_amdgpu_arch) << ErrMsg; 82fe6060f1SDimitry Andric return false; 83fe6060f1SDimitry Andric } 84fe6060f1SDimitry Andric 85fe6060f1SDimitry Andric return true; 86fe6060f1SDimitry Andric } 87fe6060f1SDimitry Andric } // namespace 88fe6060f1SDimitry Andric 89fe6060f1SDimitry Andric const char *AMDGCN::OpenMPLinker::constructLLVMLinkCommand( 9069ade1e0SDimitry Andric const toolchains::AMDGPUOpenMPToolChain &AMDGPUOpenMPTC, Compilation &C, 9169ade1e0SDimitry Andric const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, 9269ade1e0SDimitry Andric StringRef SubArchName, StringRef OutputFilePrefix) const { 93fe6060f1SDimitry Andric ArgStringList CmdArgs; 94fe6060f1SDimitry Andric 95fe6060f1SDimitry Andric for (const auto &II : Inputs) 96fe6060f1SDimitry Andric if (II.isFilename()) 97fe6060f1SDimitry Andric CmdArgs.push_back(II.getFilename()); 9869ade1e0SDimitry Andric 9904eeddc0SDimitry Andric bool HasLibm = false; 10069ade1e0SDimitry Andric if (Args.hasArg(options::OPT_l)) { 10169ade1e0SDimitry Andric auto Lm = Args.getAllArgValues(options::OPT_l); 10269ade1e0SDimitry Andric for (auto &Lib : Lm) { 10369ade1e0SDimitry Andric if (Lib == "m") { 10469ade1e0SDimitry Andric HasLibm = true; 10569ade1e0SDimitry Andric break; 10669ade1e0SDimitry Andric } 10769ade1e0SDimitry Andric } 10869ade1e0SDimitry Andric 10969ade1e0SDimitry Andric if (HasLibm) { 110349cc55cSDimitry Andric // This is not certain to work. The device libs added here, and passed to 111349cc55cSDimitry Andric // llvm-link, are missing attributes that they expect to be inserted when 112349cc55cSDimitry Andric // passed to mlink-builtin-bitcode. The amdgpu backend does not generate 113349cc55cSDimitry Andric // conservatively correct code when attributes are missing, so this may 114349cc55cSDimitry Andric // be the root cause of miscompilations. Passing via mlink-builtin-bitcode 115349cc55cSDimitry Andric // ultimately hits CodeGenModule::addDefaultFunctionDefinitionAttributes 116349cc55cSDimitry Andric // on each function, see D28538 for context. 117349cc55cSDimitry Andric // Potential workarounds: 118349cc55cSDimitry Andric // - unconditionally link all of the device libs to every translation 119349cc55cSDimitry Andric // unit in clang via mlink-builtin-bitcode 120349cc55cSDimitry Andric // - build a libm bitcode file as part of the DeviceRTL and explictly 121349cc55cSDimitry Andric // mlink-builtin-bitcode the rocm device libs components at build time 122349cc55cSDimitry Andric // - drop this llvm-link fork in favour or some calls into LLVM, chosen 123349cc55cSDimitry Andric // to do basically the same work as llvm-link but with that call first 124349cc55cSDimitry Andric // - write an opt pass that sets that on every function it sees and pipe 125349cc55cSDimitry Andric // the device-libs bitcode through that on the way to this llvm-link 12669ade1e0SDimitry Andric SmallVector<std::string, 12> BCLibs = 12769ade1e0SDimitry Andric AMDGPUOpenMPTC.getCommonDeviceLibNames(Args, SubArchName.str()); 128*81ad6265SDimitry Andric for (StringRef BCFile : BCLibs) 12969ade1e0SDimitry Andric CmdArgs.push_back(Args.MakeArgString(BCFile)); 13069ade1e0SDimitry Andric } 13169ade1e0SDimitry Andric } 13269ade1e0SDimitry Andric 133349cc55cSDimitry Andric AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, CmdArgs, "amdgcn", 13404eeddc0SDimitry Andric SubArchName, /*isBitCodeSDL=*/true, 13504eeddc0SDimitry Andric /*postClangLink=*/false); 136fe6060f1SDimitry Andric // Add an intermediate output file. 137fe6060f1SDimitry Andric CmdArgs.push_back("-o"); 138fe6060f1SDimitry Andric const char *OutputFileName = 139fe6060f1SDimitry Andric getOutputFileName(C, OutputFilePrefix, "-linked", "bc"); 140fe6060f1SDimitry Andric CmdArgs.push_back(OutputFileName); 141fe6060f1SDimitry Andric const char *Exec = 142fe6060f1SDimitry Andric Args.MakeArgString(getToolChain().GetProgramPath("llvm-link")); 143fe6060f1SDimitry Andric C.addCommand(std::make_unique<Command>( 144fe6060f1SDimitry Andric JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs, 145fe6060f1SDimitry Andric InputInfo(&JA, Args.MakeArgString(OutputFileName)))); 14604eeddc0SDimitry Andric 14704eeddc0SDimitry Andric // If we linked in libm definitions late we run another round of optimizations 14804eeddc0SDimitry Andric // to inline the definitions and fold what is foldable. 14904eeddc0SDimitry Andric if (HasLibm) { 15004eeddc0SDimitry Andric ArgStringList OptCmdArgs; 15104eeddc0SDimitry Andric const char *OptOutputFileName = 15204eeddc0SDimitry Andric getOutputFileName(C, OutputFilePrefix, "-linked-opt", "bc"); 15304eeddc0SDimitry Andric addLLCOptArg(Args, OptCmdArgs); 15404eeddc0SDimitry Andric OptCmdArgs.push_back(OutputFileName); 15504eeddc0SDimitry Andric OptCmdArgs.push_back("-o"); 15604eeddc0SDimitry Andric OptCmdArgs.push_back(OptOutputFileName); 15704eeddc0SDimitry Andric const char *OptExec = 15804eeddc0SDimitry Andric Args.MakeArgString(getToolChain().GetProgramPath("opt")); 15904eeddc0SDimitry Andric C.addCommand(std::make_unique<Command>( 16004eeddc0SDimitry Andric JA, *this, ResponseFileSupport::AtFileCurCP(), OptExec, OptCmdArgs, 16104eeddc0SDimitry Andric InputInfo(&JA, Args.MakeArgString(OutputFileName)), 16204eeddc0SDimitry Andric InputInfo(&JA, Args.MakeArgString(OptOutputFileName)))); 16304eeddc0SDimitry Andric OutputFileName = OptOutputFileName; 16404eeddc0SDimitry Andric } 16504eeddc0SDimitry Andric 166fe6060f1SDimitry Andric return OutputFileName; 167fe6060f1SDimitry Andric } 168fe6060f1SDimitry Andric 169fe6060f1SDimitry Andric const char *AMDGCN::OpenMPLinker::constructLlcCommand( 170fe6060f1SDimitry Andric Compilation &C, const JobAction &JA, const InputInfoList &Inputs, 171fe6060f1SDimitry Andric const llvm::opt::ArgList &Args, llvm::StringRef SubArchName, 172fe6060f1SDimitry Andric llvm::StringRef OutputFilePrefix, const char *InputFileName, 173fe6060f1SDimitry Andric bool OutputIsAsm) const { 174fe6060f1SDimitry Andric // Construct llc command. 175fe6060f1SDimitry Andric ArgStringList LlcArgs; 176fe6060f1SDimitry Andric // The input to llc is the output from opt. 177fe6060f1SDimitry Andric LlcArgs.push_back(InputFileName); 178fe6060f1SDimitry Andric // Pass optimization arg to llc. 179fe6060f1SDimitry Andric addLLCOptArg(Args, LlcArgs); 180fe6060f1SDimitry Andric LlcArgs.push_back("-mtriple=amdgcn-amd-amdhsa"); 181fe6060f1SDimitry Andric LlcArgs.push_back(Args.MakeArgString("-mcpu=" + SubArchName)); 182fe6060f1SDimitry Andric LlcArgs.push_back( 183fe6060f1SDimitry Andric Args.MakeArgString(Twine("-filetype=") + (OutputIsAsm ? "asm" : "obj"))); 184fe6060f1SDimitry Andric 185fe6060f1SDimitry Andric for (const Arg *A : Args.filtered(options::OPT_mllvm)) { 186fe6060f1SDimitry Andric LlcArgs.push_back(A->getValue(0)); 187fe6060f1SDimitry Andric } 188fe6060f1SDimitry Andric 189fe6060f1SDimitry Andric // Add output filename 190fe6060f1SDimitry Andric LlcArgs.push_back("-o"); 191fe6060f1SDimitry Andric const char *LlcOutputFile = 192fe6060f1SDimitry Andric getOutputFileName(C, OutputFilePrefix, "", OutputIsAsm ? "s" : "o"); 193fe6060f1SDimitry Andric LlcArgs.push_back(LlcOutputFile); 194fe6060f1SDimitry Andric const char *Llc = Args.MakeArgString(getToolChain().GetProgramPath("llc")); 195fe6060f1SDimitry Andric C.addCommand(std::make_unique<Command>( 196fe6060f1SDimitry Andric JA, *this, ResponseFileSupport::AtFileCurCP(), Llc, LlcArgs, Inputs, 197fe6060f1SDimitry Andric InputInfo(&JA, Args.MakeArgString(LlcOutputFile)))); 198fe6060f1SDimitry Andric return LlcOutputFile; 199fe6060f1SDimitry Andric } 200fe6060f1SDimitry Andric 201fe6060f1SDimitry Andric void AMDGCN::OpenMPLinker::constructLldCommand( 202fe6060f1SDimitry Andric Compilation &C, const JobAction &JA, const InputInfoList &Inputs, 203fe6060f1SDimitry Andric const InputInfo &Output, const llvm::opt::ArgList &Args, 204fe6060f1SDimitry Andric const char *InputFileName) const { 205fe6060f1SDimitry Andric // Construct lld command. 206fe6060f1SDimitry Andric // The output from ld.lld is an HSA code object file. 207fe6060f1SDimitry Andric ArgStringList LldArgs{"-flavor", "gnu", "--no-undefined", 208fe6060f1SDimitry Andric "-shared", "-o", Output.getFilename(), 209fe6060f1SDimitry Andric InputFileName}; 210fe6060f1SDimitry Andric 211fe6060f1SDimitry Andric const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld")); 212fe6060f1SDimitry Andric C.addCommand(std::make_unique<Command>( 213fe6060f1SDimitry Andric JA, *this, ResponseFileSupport::AtFileCurCP(), Lld, LldArgs, Inputs, 214fe6060f1SDimitry Andric InputInfo(&JA, Args.MakeArgString(Output.getFilename())))); 215fe6060f1SDimitry Andric } 216fe6060f1SDimitry Andric 217fe6060f1SDimitry Andric // For amdgcn the inputs of the linker job are device bitcode and output is 218fe6060f1SDimitry Andric // object file. It calls llvm-link, opt, llc, then lld steps. 219fe6060f1SDimitry Andric void AMDGCN::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA, 220fe6060f1SDimitry Andric const InputInfo &Output, 221fe6060f1SDimitry Andric const InputInfoList &Inputs, 222fe6060f1SDimitry Andric const ArgList &Args, 223fe6060f1SDimitry Andric const char *LinkingOutput) const { 224fe6060f1SDimitry Andric const ToolChain &TC = getToolChain(); 225fe6060f1SDimitry Andric assert(getToolChain().getTriple().isAMDGCN() && "Unsupported target"); 226fe6060f1SDimitry Andric 227fe6060f1SDimitry Andric const toolchains::AMDGPUOpenMPToolChain &AMDGPUOpenMPTC = 228fe6060f1SDimitry Andric static_cast<const toolchains::AMDGPUOpenMPToolChain &>(TC); 229fe6060f1SDimitry Andric 230fe6060f1SDimitry Andric std::string GPUArch = Args.getLastArgValue(options::OPT_march_EQ).str(); 231fe6060f1SDimitry Andric if (GPUArch.empty()) { 232fe6060f1SDimitry Andric if (!checkSystemForAMDGPU(Args, AMDGPUOpenMPTC, GPUArch)) 233fe6060f1SDimitry Andric return; 234fe6060f1SDimitry Andric } 235fe6060f1SDimitry Andric 236fe6060f1SDimitry Andric // Prefix for temporary file name. 237fe6060f1SDimitry Andric std::string Prefix; 238fe6060f1SDimitry Andric for (const auto &II : Inputs) 239fe6060f1SDimitry Andric if (II.isFilename()) 240fe6060f1SDimitry Andric Prefix = llvm::sys::path::stem(II.getFilename()).str() + "-" + GPUArch; 241fe6060f1SDimitry Andric assert(Prefix.length() && "no linker inputs are files "); 242fe6060f1SDimitry Andric 243fe6060f1SDimitry Andric // Each command outputs different files. 24469ade1e0SDimitry Andric const char *LLVMLinkCommand = constructLLVMLinkCommand( 24569ade1e0SDimitry Andric AMDGPUOpenMPTC, C, JA, Inputs, Args, GPUArch, Prefix); 246fe6060f1SDimitry Andric 247fe6060f1SDimitry Andric // Produce readable assembly if save-temps is enabled. 248fe6060f1SDimitry Andric if (C.getDriver().isSaveTempsEnabled()) 249fe6060f1SDimitry Andric constructLlcCommand(C, JA, Inputs, Args, GPUArch, Prefix, LLVMLinkCommand, 250fe6060f1SDimitry Andric /*OutputIsAsm=*/true); 251fe6060f1SDimitry Andric const char *LlcCommand = constructLlcCommand(C, JA, Inputs, Args, GPUArch, 252fe6060f1SDimitry Andric Prefix, LLVMLinkCommand); 253fe6060f1SDimitry Andric constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand); 254fe6060f1SDimitry Andric } 255fe6060f1SDimitry Andric 256fe6060f1SDimitry Andric AMDGPUOpenMPToolChain::AMDGPUOpenMPToolChain(const Driver &D, 257fe6060f1SDimitry Andric const llvm::Triple &Triple, 258fe6060f1SDimitry Andric const ToolChain &HostTC, 259fe6060f1SDimitry Andric const ArgList &Args) 260fe6060f1SDimitry Andric : ROCMToolChain(D, Triple, Args), HostTC(HostTC) { 261fe6060f1SDimitry Andric // Lookup binaries into the driver directory, this is used to 262fe6060f1SDimitry Andric // discover the clang-offload-bundler executable. 263fe6060f1SDimitry Andric getProgramPaths().push_back(getDriver().Dir); 264fe6060f1SDimitry Andric } 265fe6060f1SDimitry Andric 266fe6060f1SDimitry Andric void AMDGPUOpenMPToolChain::addClangTargetOptions( 267fe6060f1SDimitry Andric const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, 268fe6060f1SDimitry Andric Action::OffloadKind DeviceOffloadingKind) const { 269fe6060f1SDimitry Andric HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind); 270fe6060f1SDimitry Andric 271fe6060f1SDimitry Andric std::string GPUArch = DriverArgs.getLastArgValue(options::OPT_march_EQ).str(); 272fe6060f1SDimitry Andric if (GPUArch.empty()) { 273fe6060f1SDimitry Andric if (!checkSystemForAMDGPU(DriverArgs, *this, GPUArch)) 274fe6060f1SDimitry Andric return; 275fe6060f1SDimitry Andric } 276fe6060f1SDimitry Andric 277fe6060f1SDimitry Andric assert(DeviceOffloadingKind == Action::OFK_OpenMP && 278fe6060f1SDimitry Andric "Only OpenMP offloading kinds are supported."); 279fe6060f1SDimitry Andric 280fe6060f1SDimitry Andric CC1Args.push_back("-target-cpu"); 281fe6060f1SDimitry Andric CC1Args.push_back(DriverArgs.MakeArgStringRef(GPUArch)); 282fe6060f1SDimitry Andric CC1Args.push_back("-fcuda-is-device"); 283fe6060f1SDimitry Andric 284fe6060f1SDimitry Andric if (DriverArgs.hasArg(options::OPT_nogpulib)) 285fe6060f1SDimitry Andric return; 286fe6060f1SDimitry Andric 2871fd87a68SDimitry Andric // Link the bitcode library late if we're using device LTO. 2881fd87a68SDimitry Andric if (getDriver().isUsingLTO(/* IsOffload */ true)) 2891fd87a68SDimitry Andric return; 2901fd87a68SDimitry Andric 291*81ad6265SDimitry Andric addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, GPUArch, getTriple()); 292fe6060f1SDimitry Andric } 293fe6060f1SDimitry Andric 294fe6060f1SDimitry Andric llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs( 295fe6060f1SDimitry Andric const llvm::opt::DerivedArgList &Args, StringRef BoundArch, 296fe6060f1SDimitry Andric Action::OffloadKind DeviceOffloadKind) const { 297fe6060f1SDimitry Andric DerivedArgList *DAL = 298fe6060f1SDimitry Andric HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind); 299fe6060f1SDimitry Andric if (!DAL) 300fe6060f1SDimitry Andric DAL = new DerivedArgList(Args.getBaseArgs()); 301fe6060f1SDimitry Andric 302fe6060f1SDimitry Andric const OptTable &Opts = getDriver().getOpts(); 303fe6060f1SDimitry Andric 30404eeddc0SDimitry Andric if (DeviceOffloadKind == Action::OFK_OpenMP) { 30504eeddc0SDimitry Andric for (Arg *A : Args) 30604eeddc0SDimitry Andric if (!llvm::is_contained(*DAL, A)) 30704eeddc0SDimitry Andric DAL->append(A); 30804eeddc0SDimitry Andric 309*81ad6265SDimitry Andric if (!DAL->hasArg(options::OPT_march_EQ)) { 310*81ad6265SDimitry Andric std::string Arch = BoundArch.str(); 311*81ad6265SDimitry Andric if (BoundArch.empty()) 31204eeddc0SDimitry Andric checkSystemForAMDGPU(Args, *this, Arch); 31304eeddc0SDimitry Andric DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), Arch); 31404eeddc0SDimitry Andric } 31504eeddc0SDimitry Andric 31604eeddc0SDimitry Andric return DAL; 31704eeddc0SDimitry Andric } 31804eeddc0SDimitry Andric 319fe6060f1SDimitry Andric for (Arg *A : Args) { 320fe6060f1SDimitry Andric DAL->append(A); 321fe6060f1SDimitry Andric } 322fe6060f1SDimitry Andric 323fe6060f1SDimitry Andric if (!BoundArch.empty()) { 324fe6060f1SDimitry Andric DAL->eraseArg(options::OPT_march_EQ); 325fe6060f1SDimitry Andric DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), 326fe6060f1SDimitry Andric BoundArch); 327fe6060f1SDimitry Andric } 328fe6060f1SDimitry Andric 329fe6060f1SDimitry Andric return DAL; 330fe6060f1SDimitry Andric } 331fe6060f1SDimitry Andric 332fe6060f1SDimitry Andric Tool *AMDGPUOpenMPToolChain::buildLinker() const { 333fe6060f1SDimitry Andric assert(getTriple().isAMDGCN()); 334fe6060f1SDimitry Andric return new tools::AMDGCN::OpenMPLinker(*this); 335fe6060f1SDimitry Andric } 336fe6060f1SDimitry Andric 337fe6060f1SDimitry Andric void AMDGPUOpenMPToolChain::addClangWarningOptions( 338fe6060f1SDimitry Andric ArgStringList &CC1Args) const { 339fe6060f1SDimitry Andric HostTC.addClangWarningOptions(CC1Args); 340fe6060f1SDimitry Andric } 341fe6060f1SDimitry Andric 342fe6060f1SDimitry Andric ToolChain::CXXStdlibType 343fe6060f1SDimitry Andric AMDGPUOpenMPToolChain::GetCXXStdlibType(const ArgList &Args) const { 344fe6060f1SDimitry Andric return HostTC.GetCXXStdlibType(Args); 345fe6060f1SDimitry Andric } 346fe6060f1SDimitry Andric 347fe6060f1SDimitry Andric void AMDGPUOpenMPToolChain::AddClangSystemIncludeArgs( 348fe6060f1SDimitry Andric const ArgList &DriverArgs, ArgStringList &CC1Args) const { 349fe6060f1SDimitry Andric HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args); 350fe6060f1SDimitry Andric } 351fe6060f1SDimitry Andric 352fe6060f1SDimitry Andric void AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs(const ArgList &Args, 353fe6060f1SDimitry Andric ArgStringList &CC1Args) const { 354fe6060f1SDimitry Andric HostTC.AddIAMCUIncludeArgs(Args, CC1Args); 355fe6060f1SDimitry Andric } 356fe6060f1SDimitry Andric 357fe6060f1SDimitry Andric SanitizerMask AMDGPUOpenMPToolChain::getSupportedSanitizers() const { 358fe6060f1SDimitry Andric // The AMDGPUOpenMPToolChain only supports sanitizers in the sense that it 359fe6060f1SDimitry Andric // allows sanitizer arguments on the command line if they are supported by the 360fe6060f1SDimitry Andric // host toolchain. The AMDGPUOpenMPToolChain will actually ignore any command 361fe6060f1SDimitry Andric // line arguments for any of these "supported" sanitizers. That means that no 362fe6060f1SDimitry Andric // sanitization of device code is actually supported at this time. 363fe6060f1SDimitry Andric // 364fe6060f1SDimitry Andric // This behavior is necessary because the host and device toolchains 365fe6060f1SDimitry Andric // invocations often share the command line, so the device toolchain must 366fe6060f1SDimitry Andric // tolerate flags meant only for the host toolchain. 367fe6060f1SDimitry Andric return HostTC.getSupportedSanitizers(); 368fe6060f1SDimitry Andric } 369fe6060f1SDimitry Andric 370fe6060f1SDimitry Andric VersionTuple 371fe6060f1SDimitry Andric AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver *D, 372fe6060f1SDimitry Andric const ArgList &Args) const { 373fe6060f1SDimitry Andric return HostTC.computeMSVCVersion(D, Args); 374fe6060f1SDimitry Andric } 375