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" 1969ade1e0SDimitry Andric #include "llvm/ADT/STLExtras.h" 20fe6060f1SDimitry Andric #include "llvm/Support/FileSystem.h" 21fe6060f1SDimitry Andric #include "llvm/Support/FormatAdapters.h" 22fe6060f1SDimitry Andric #include "llvm/Support/FormatVariadic.h" 23fe6060f1SDimitry Andric #include "llvm/Support/Path.h" 24fe6060f1SDimitry Andric 25fe6060f1SDimitry Andric using namespace clang::driver; 26fe6060f1SDimitry Andric using namespace clang::driver::toolchains; 27fe6060f1SDimitry Andric using namespace clang::driver::tools; 28fe6060f1SDimitry Andric using namespace clang; 29fe6060f1SDimitry Andric using namespace llvm::opt; 30fe6060f1SDimitry Andric 31fe6060f1SDimitry Andric namespace { 32fe6060f1SDimitry Andric 33fe6060f1SDimitry Andric static const char *getOutputFileName(Compilation &C, StringRef Base, 34fe6060f1SDimitry Andric const char *Postfix, 35fe6060f1SDimitry Andric const char *Extension) { 36fe6060f1SDimitry Andric const char *OutputFileName; 37fe6060f1SDimitry Andric if (C.getDriver().isSaveTempsEnabled()) { 38fe6060f1SDimitry Andric OutputFileName = 39fe6060f1SDimitry Andric C.getArgs().MakeArgString(Base.str() + Postfix + "." + Extension); 40fe6060f1SDimitry Andric } else { 41fe6060f1SDimitry Andric std::string TmpName = 42fe6060f1SDimitry Andric C.getDriver().GetTemporaryPath(Base.str() + Postfix, Extension); 43fe6060f1SDimitry Andric OutputFileName = C.addTempFile(C.getArgs().MakeArgString(TmpName)); 44fe6060f1SDimitry Andric } 45fe6060f1SDimitry Andric return OutputFileName; 46fe6060f1SDimitry Andric } 47fe6060f1SDimitry Andric 48fe6060f1SDimitry Andric static void addLLCOptArg(const llvm::opt::ArgList &Args, 49fe6060f1SDimitry Andric llvm::opt::ArgStringList &CmdArgs) { 50fe6060f1SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { 51fe6060f1SDimitry Andric StringRef OOpt = "0"; 52fe6060f1SDimitry Andric if (A->getOption().matches(options::OPT_O4) || 53fe6060f1SDimitry Andric A->getOption().matches(options::OPT_Ofast)) 54fe6060f1SDimitry Andric OOpt = "3"; 55fe6060f1SDimitry Andric else if (A->getOption().matches(options::OPT_O0)) 56fe6060f1SDimitry Andric OOpt = "0"; 57fe6060f1SDimitry Andric else if (A->getOption().matches(options::OPT_O)) { 58fe6060f1SDimitry Andric // Clang and opt support -Os/-Oz; llc only supports -O0, -O1, -O2 and -O3 59fe6060f1SDimitry Andric // so we map -Os/-Oz to -O2. 60fe6060f1SDimitry Andric // Only clang supports -Og, and maps it to -O1. 61fe6060f1SDimitry Andric // We map anything else to -O2. 62fe6060f1SDimitry Andric OOpt = llvm::StringSwitch<const char *>(A->getValue()) 63fe6060f1SDimitry Andric .Case("1", "1") 64fe6060f1SDimitry Andric .Case("2", "2") 65fe6060f1SDimitry Andric .Case("3", "3") 66fe6060f1SDimitry Andric .Case("s", "2") 67fe6060f1SDimitry Andric .Case("z", "2") 68fe6060f1SDimitry Andric .Case("g", "1") 69fe6060f1SDimitry Andric .Default("0"); 70fe6060f1SDimitry Andric } 71fe6060f1SDimitry Andric CmdArgs.push_back(Args.MakeArgString("-O" + OOpt)); 72fe6060f1SDimitry Andric } 73fe6060f1SDimitry Andric } 74fe6060f1SDimitry Andric 75fe6060f1SDimitry Andric static bool checkSystemForAMDGPU(const ArgList &Args, const AMDGPUToolChain &TC, 76fe6060f1SDimitry Andric std::string &GPUArch) { 77fe6060f1SDimitry Andric if (auto Err = TC.getSystemGPUArch(Args, GPUArch)) { 78fe6060f1SDimitry Andric std::string ErrMsg = 79fe6060f1SDimitry Andric llvm::formatv("{0}", llvm::fmt_consume(std::move(Err))); 80fe6060f1SDimitry Andric TC.getDriver().Diag(diag::err_drv_undetermined_amdgpu_arch) << ErrMsg; 81fe6060f1SDimitry Andric return false; 82fe6060f1SDimitry Andric } 83fe6060f1SDimitry Andric 84fe6060f1SDimitry Andric return true; 85fe6060f1SDimitry Andric } 86fe6060f1SDimitry Andric } // namespace 87fe6060f1SDimitry Andric 88fe6060f1SDimitry Andric const char *AMDGCN::OpenMPLinker::constructLLVMLinkCommand( 8969ade1e0SDimitry Andric const toolchains::AMDGPUOpenMPToolChain &AMDGPUOpenMPTC, Compilation &C, 9069ade1e0SDimitry Andric const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, 9169ade1e0SDimitry Andric StringRef SubArchName, StringRef OutputFilePrefix) const { 92fe6060f1SDimitry Andric ArgStringList CmdArgs; 93fe6060f1SDimitry Andric 94fe6060f1SDimitry Andric for (const auto &II : Inputs) 95fe6060f1SDimitry Andric if (II.isFilename()) 96fe6060f1SDimitry Andric CmdArgs.push_back(II.getFilename()); 9769ade1e0SDimitry Andric 9869ade1e0SDimitry Andric if (Args.hasArg(options::OPT_l)) { 9969ade1e0SDimitry Andric auto Lm = Args.getAllArgValues(options::OPT_l); 10069ade1e0SDimitry Andric bool HasLibm = false; 10169ade1e0SDimitry Andric for (auto &Lib : Lm) { 10269ade1e0SDimitry Andric if (Lib == "m") { 10369ade1e0SDimitry Andric HasLibm = true; 10469ade1e0SDimitry Andric break; 10569ade1e0SDimitry Andric } 10669ade1e0SDimitry Andric } 10769ade1e0SDimitry Andric 10869ade1e0SDimitry Andric if (HasLibm) { 109*349cc55cSDimitry Andric // This is not certain to work. The device libs added here, and passed to 110*349cc55cSDimitry Andric // llvm-link, are missing attributes that they expect to be inserted when 111*349cc55cSDimitry Andric // passed to mlink-builtin-bitcode. The amdgpu backend does not generate 112*349cc55cSDimitry Andric // conservatively correct code when attributes are missing, so this may 113*349cc55cSDimitry Andric // be the root cause of miscompilations. Passing via mlink-builtin-bitcode 114*349cc55cSDimitry Andric // ultimately hits CodeGenModule::addDefaultFunctionDefinitionAttributes 115*349cc55cSDimitry Andric // on each function, see D28538 for context. 116*349cc55cSDimitry Andric // Potential workarounds: 117*349cc55cSDimitry Andric // - unconditionally link all of the device libs to every translation 118*349cc55cSDimitry Andric // unit in clang via mlink-builtin-bitcode 119*349cc55cSDimitry Andric // - build a libm bitcode file as part of the DeviceRTL and explictly 120*349cc55cSDimitry Andric // mlink-builtin-bitcode the rocm device libs components at build time 121*349cc55cSDimitry Andric // - drop this llvm-link fork in favour or some calls into LLVM, chosen 122*349cc55cSDimitry Andric // to do basically the same work as llvm-link but with that call first 123*349cc55cSDimitry Andric // - write an opt pass that sets that on every function it sees and pipe 124*349cc55cSDimitry Andric // the device-libs bitcode through that on the way to this llvm-link 12569ade1e0SDimitry Andric SmallVector<std::string, 12> BCLibs = 12669ade1e0SDimitry Andric AMDGPUOpenMPTC.getCommonDeviceLibNames(Args, SubArchName.str()); 12769ade1e0SDimitry Andric llvm::for_each(BCLibs, [&](StringRef BCFile) { 12869ade1e0SDimitry Andric CmdArgs.push_back(Args.MakeArgString(BCFile)); 12969ade1e0SDimitry Andric }); 13069ade1e0SDimitry Andric } 13169ade1e0SDimitry Andric } 13269ade1e0SDimitry Andric 133*349cc55cSDimitry Andric AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, CmdArgs, "amdgcn", 134*349cc55cSDimitry Andric SubArchName, 135*349cc55cSDimitry Andric /* bitcode SDL?*/ true, 136*349cc55cSDimitry Andric /* PostClang Link? */ false); 137fe6060f1SDimitry Andric // Add an intermediate output file. 138fe6060f1SDimitry Andric CmdArgs.push_back("-o"); 139fe6060f1SDimitry Andric const char *OutputFileName = 140fe6060f1SDimitry Andric getOutputFileName(C, OutputFilePrefix, "-linked", "bc"); 141fe6060f1SDimitry Andric CmdArgs.push_back(OutputFileName); 142fe6060f1SDimitry Andric const char *Exec = 143fe6060f1SDimitry Andric Args.MakeArgString(getToolChain().GetProgramPath("llvm-link")); 144fe6060f1SDimitry Andric C.addCommand(std::make_unique<Command>( 145fe6060f1SDimitry Andric JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs, 146fe6060f1SDimitry Andric InputInfo(&JA, Args.MakeArgString(OutputFileName)))); 147fe6060f1SDimitry Andric return OutputFileName; 148fe6060f1SDimitry Andric } 149fe6060f1SDimitry Andric 150fe6060f1SDimitry Andric const char *AMDGCN::OpenMPLinker::constructLlcCommand( 151fe6060f1SDimitry Andric Compilation &C, const JobAction &JA, const InputInfoList &Inputs, 152fe6060f1SDimitry Andric const llvm::opt::ArgList &Args, llvm::StringRef SubArchName, 153fe6060f1SDimitry Andric llvm::StringRef OutputFilePrefix, const char *InputFileName, 154fe6060f1SDimitry Andric bool OutputIsAsm) const { 155fe6060f1SDimitry Andric // Construct llc command. 156fe6060f1SDimitry Andric ArgStringList LlcArgs; 157fe6060f1SDimitry Andric // The input to llc is the output from opt. 158fe6060f1SDimitry Andric LlcArgs.push_back(InputFileName); 159fe6060f1SDimitry Andric // Pass optimization arg to llc. 160fe6060f1SDimitry Andric addLLCOptArg(Args, LlcArgs); 161fe6060f1SDimitry Andric LlcArgs.push_back("-mtriple=amdgcn-amd-amdhsa"); 162fe6060f1SDimitry Andric LlcArgs.push_back(Args.MakeArgString("-mcpu=" + SubArchName)); 163fe6060f1SDimitry Andric LlcArgs.push_back( 164fe6060f1SDimitry Andric Args.MakeArgString(Twine("-filetype=") + (OutputIsAsm ? "asm" : "obj"))); 165fe6060f1SDimitry Andric 166fe6060f1SDimitry Andric for (const Arg *A : Args.filtered(options::OPT_mllvm)) { 167fe6060f1SDimitry Andric LlcArgs.push_back(A->getValue(0)); 168fe6060f1SDimitry Andric } 169fe6060f1SDimitry Andric 170fe6060f1SDimitry Andric // Add output filename 171fe6060f1SDimitry Andric LlcArgs.push_back("-o"); 172fe6060f1SDimitry Andric const char *LlcOutputFile = 173fe6060f1SDimitry Andric getOutputFileName(C, OutputFilePrefix, "", OutputIsAsm ? "s" : "o"); 174fe6060f1SDimitry Andric LlcArgs.push_back(LlcOutputFile); 175fe6060f1SDimitry Andric const char *Llc = Args.MakeArgString(getToolChain().GetProgramPath("llc")); 176fe6060f1SDimitry Andric C.addCommand(std::make_unique<Command>( 177fe6060f1SDimitry Andric JA, *this, ResponseFileSupport::AtFileCurCP(), Llc, LlcArgs, Inputs, 178fe6060f1SDimitry Andric InputInfo(&JA, Args.MakeArgString(LlcOutputFile)))); 179fe6060f1SDimitry Andric return LlcOutputFile; 180fe6060f1SDimitry Andric } 181fe6060f1SDimitry Andric 182fe6060f1SDimitry Andric void AMDGCN::OpenMPLinker::constructLldCommand( 183fe6060f1SDimitry Andric Compilation &C, const JobAction &JA, const InputInfoList &Inputs, 184fe6060f1SDimitry Andric const InputInfo &Output, const llvm::opt::ArgList &Args, 185fe6060f1SDimitry Andric const char *InputFileName) const { 186fe6060f1SDimitry Andric // Construct lld command. 187fe6060f1SDimitry Andric // The output from ld.lld is an HSA code object file. 188fe6060f1SDimitry Andric ArgStringList LldArgs{"-flavor", "gnu", "--no-undefined", 189fe6060f1SDimitry Andric "-shared", "-o", Output.getFilename(), 190fe6060f1SDimitry Andric InputFileName}; 191fe6060f1SDimitry Andric 192fe6060f1SDimitry Andric const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld")); 193fe6060f1SDimitry Andric C.addCommand(std::make_unique<Command>( 194fe6060f1SDimitry Andric JA, *this, ResponseFileSupport::AtFileCurCP(), Lld, LldArgs, Inputs, 195fe6060f1SDimitry Andric InputInfo(&JA, Args.MakeArgString(Output.getFilename())))); 196fe6060f1SDimitry Andric } 197fe6060f1SDimitry Andric 198fe6060f1SDimitry Andric // For amdgcn the inputs of the linker job are device bitcode and output is 199fe6060f1SDimitry Andric // object file. It calls llvm-link, opt, llc, then lld steps. 200fe6060f1SDimitry Andric void AMDGCN::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA, 201fe6060f1SDimitry Andric const InputInfo &Output, 202fe6060f1SDimitry Andric const InputInfoList &Inputs, 203fe6060f1SDimitry Andric const ArgList &Args, 204fe6060f1SDimitry Andric const char *LinkingOutput) const { 205fe6060f1SDimitry Andric const ToolChain &TC = getToolChain(); 206fe6060f1SDimitry Andric assert(getToolChain().getTriple().isAMDGCN() && "Unsupported target"); 207fe6060f1SDimitry Andric 208fe6060f1SDimitry Andric const toolchains::AMDGPUOpenMPToolChain &AMDGPUOpenMPTC = 209fe6060f1SDimitry Andric static_cast<const toolchains::AMDGPUOpenMPToolChain &>(TC); 210fe6060f1SDimitry Andric 211fe6060f1SDimitry Andric std::string GPUArch = Args.getLastArgValue(options::OPT_march_EQ).str(); 212fe6060f1SDimitry Andric if (GPUArch.empty()) { 213fe6060f1SDimitry Andric if (!checkSystemForAMDGPU(Args, AMDGPUOpenMPTC, GPUArch)) 214fe6060f1SDimitry Andric return; 215fe6060f1SDimitry Andric } 216fe6060f1SDimitry Andric 217fe6060f1SDimitry Andric // Prefix for temporary file name. 218fe6060f1SDimitry Andric std::string Prefix; 219fe6060f1SDimitry Andric for (const auto &II : Inputs) 220fe6060f1SDimitry Andric if (II.isFilename()) 221fe6060f1SDimitry Andric Prefix = llvm::sys::path::stem(II.getFilename()).str() + "-" + GPUArch; 222fe6060f1SDimitry Andric assert(Prefix.length() && "no linker inputs are files "); 223fe6060f1SDimitry Andric 224fe6060f1SDimitry Andric // Each command outputs different files. 22569ade1e0SDimitry Andric const char *LLVMLinkCommand = constructLLVMLinkCommand( 22669ade1e0SDimitry Andric AMDGPUOpenMPTC, C, JA, Inputs, Args, GPUArch, Prefix); 227fe6060f1SDimitry Andric 228fe6060f1SDimitry Andric // Produce readable assembly if save-temps is enabled. 229fe6060f1SDimitry Andric if (C.getDriver().isSaveTempsEnabled()) 230fe6060f1SDimitry Andric constructLlcCommand(C, JA, Inputs, Args, GPUArch, Prefix, LLVMLinkCommand, 231fe6060f1SDimitry Andric /*OutputIsAsm=*/true); 232fe6060f1SDimitry Andric const char *LlcCommand = constructLlcCommand(C, JA, Inputs, Args, GPUArch, 233fe6060f1SDimitry Andric Prefix, LLVMLinkCommand); 234fe6060f1SDimitry Andric constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand); 235fe6060f1SDimitry Andric } 236fe6060f1SDimitry Andric 237fe6060f1SDimitry Andric AMDGPUOpenMPToolChain::AMDGPUOpenMPToolChain(const Driver &D, 238fe6060f1SDimitry Andric const llvm::Triple &Triple, 239fe6060f1SDimitry Andric const ToolChain &HostTC, 240fe6060f1SDimitry Andric const ArgList &Args) 241fe6060f1SDimitry Andric : ROCMToolChain(D, Triple, Args), HostTC(HostTC) { 242fe6060f1SDimitry Andric // Lookup binaries into the driver directory, this is used to 243fe6060f1SDimitry Andric // discover the clang-offload-bundler executable. 244fe6060f1SDimitry Andric getProgramPaths().push_back(getDriver().Dir); 245fe6060f1SDimitry Andric } 246fe6060f1SDimitry Andric 247fe6060f1SDimitry Andric void AMDGPUOpenMPToolChain::addClangTargetOptions( 248fe6060f1SDimitry Andric const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, 249fe6060f1SDimitry Andric Action::OffloadKind DeviceOffloadingKind) const { 250fe6060f1SDimitry Andric HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind); 251fe6060f1SDimitry Andric 252fe6060f1SDimitry Andric std::string GPUArch = DriverArgs.getLastArgValue(options::OPT_march_EQ).str(); 253fe6060f1SDimitry Andric if (GPUArch.empty()) { 254fe6060f1SDimitry Andric if (!checkSystemForAMDGPU(DriverArgs, *this, GPUArch)) 255fe6060f1SDimitry Andric return; 256fe6060f1SDimitry Andric } 257fe6060f1SDimitry Andric 258fe6060f1SDimitry Andric assert(DeviceOffloadingKind == Action::OFK_OpenMP && 259fe6060f1SDimitry Andric "Only OpenMP offloading kinds are supported."); 260fe6060f1SDimitry Andric 261fe6060f1SDimitry Andric CC1Args.push_back("-target-cpu"); 262fe6060f1SDimitry Andric CC1Args.push_back(DriverArgs.MakeArgStringRef(GPUArch)); 263fe6060f1SDimitry Andric CC1Args.push_back("-fcuda-is-device"); 264fe6060f1SDimitry Andric 265fe6060f1SDimitry Andric if (DriverArgs.hasArg(options::OPT_nogpulib)) 266fe6060f1SDimitry Andric return; 267fe6060f1SDimitry Andric 268fe6060f1SDimitry Andric std::string BitcodeSuffix; 269fe6060f1SDimitry Andric if (DriverArgs.hasFlag(options::OPT_fopenmp_target_new_runtime, 270fe6060f1SDimitry Andric options::OPT_fno_openmp_target_new_runtime, false)) 271*349cc55cSDimitry Andric BitcodeSuffix = "new-amdgpu-" + GPUArch; 272fe6060f1SDimitry Andric else 273fe6060f1SDimitry Andric BitcodeSuffix = "amdgcn-" + GPUArch; 274fe6060f1SDimitry Andric 275fe6060f1SDimitry Andric addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, BitcodeSuffix, 276fe6060f1SDimitry Andric getTriple()); 277fe6060f1SDimitry Andric } 278fe6060f1SDimitry Andric 279fe6060f1SDimitry Andric llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs( 280fe6060f1SDimitry Andric const llvm::opt::DerivedArgList &Args, StringRef BoundArch, 281fe6060f1SDimitry Andric Action::OffloadKind DeviceOffloadKind) const { 282fe6060f1SDimitry Andric DerivedArgList *DAL = 283fe6060f1SDimitry Andric HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind); 284fe6060f1SDimitry Andric if (!DAL) 285fe6060f1SDimitry Andric DAL = new DerivedArgList(Args.getBaseArgs()); 286fe6060f1SDimitry Andric 287fe6060f1SDimitry Andric const OptTable &Opts = getDriver().getOpts(); 288fe6060f1SDimitry Andric 289fe6060f1SDimitry Andric if (DeviceOffloadKind != Action::OFK_OpenMP) { 290fe6060f1SDimitry Andric for (Arg *A : Args) { 291fe6060f1SDimitry Andric DAL->append(A); 292fe6060f1SDimitry Andric } 293fe6060f1SDimitry Andric } 294fe6060f1SDimitry Andric 295fe6060f1SDimitry Andric if (!BoundArch.empty()) { 296fe6060f1SDimitry Andric DAL->eraseArg(options::OPT_march_EQ); 297fe6060f1SDimitry Andric DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), 298fe6060f1SDimitry Andric BoundArch); 299fe6060f1SDimitry Andric } 300fe6060f1SDimitry Andric 301fe6060f1SDimitry Andric return DAL; 302fe6060f1SDimitry Andric } 303fe6060f1SDimitry Andric 304fe6060f1SDimitry Andric Tool *AMDGPUOpenMPToolChain::buildLinker() const { 305fe6060f1SDimitry Andric assert(getTriple().isAMDGCN()); 306fe6060f1SDimitry Andric return new tools::AMDGCN::OpenMPLinker(*this); 307fe6060f1SDimitry Andric } 308fe6060f1SDimitry Andric 309fe6060f1SDimitry Andric void AMDGPUOpenMPToolChain::addClangWarningOptions( 310fe6060f1SDimitry Andric ArgStringList &CC1Args) const { 311fe6060f1SDimitry Andric HostTC.addClangWarningOptions(CC1Args); 312fe6060f1SDimitry Andric } 313fe6060f1SDimitry Andric 314fe6060f1SDimitry Andric ToolChain::CXXStdlibType 315fe6060f1SDimitry Andric AMDGPUOpenMPToolChain::GetCXXStdlibType(const ArgList &Args) const { 316fe6060f1SDimitry Andric return HostTC.GetCXXStdlibType(Args); 317fe6060f1SDimitry Andric } 318fe6060f1SDimitry Andric 319fe6060f1SDimitry Andric void AMDGPUOpenMPToolChain::AddClangSystemIncludeArgs( 320fe6060f1SDimitry Andric const ArgList &DriverArgs, ArgStringList &CC1Args) const { 321fe6060f1SDimitry Andric HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args); 322fe6060f1SDimitry Andric } 323fe6060f1SDimitry Andric 324fe6060f1SDimitry Andric void AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs(const ArgList &Args, 325fe6060f1SDimitry Andric ArgStringList &CC1Args) const { 326fe6060f1SDimitry Andric HostTC.AddIAMCUIncludeArgs(Args, CC1Args); 327fe6060f1SDimitry Andric } 328fe6060f1SDimitry Andric 329fe6060f1SDimitry Andric SanitizerMask AMDGPUOpenMPToolChain::getSupportedSanitizers() const { 330fe6060f1SDimitry Andric // The AMDGPUOpenMPToolChain only supports sanitizers in the sense that it 331fe6060f1SDimitry Andric // allows sanitizer arguments on the command line if they are supported by the 332fe6060f1SDimitry Andric // host toolchain. The AMDGPUOpenMPToolChain will actually ignore any command 333fe6060f1SDimitry Andric // line arguments for any of these "supported" sanitizers. That means that no 334fe6060f1SDimitry Andric // sanitization of device code is actually supported at this time. 335fe6060f1SDimitry Andric // 336fe6060f1SDimitry Andric // This behavior is necessary because the host and device toolchains 337fe6060f1SDimitry Andric // invocations often share the command line, so the device toolchain must 338fe6060f1SDimitry Andric // tolerate flags meant only for the host toolchain. 339fe6060f1SDimitry Andric return HostTC.getSupportedSanitizers(); 340fe6060f1SDimitry Andric } 341fe6060f1SDimitry Andric 342fe6060f1SDimitry Andric VersionTuple 343fe6060f1SDimitry Andric AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver *D, 344fe6060f1SDimitry Andric const ArgList &Args) const { 345fe6060f1SDimitry Andric return HostTC.computeMSVCVersion(D, Args); 346fe6060f1SDimitry Andric } 347