1 //===- AMDGPUOpenMP.cpp - AMDGPUOpenMP ToolChain Implementation -*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "AMDGPUOpenMP.h" 10 #include "AMDGPU.h" 11 #include "clang/Driver/Compilation.h" 12 #include "clang/Driver/Driver.h" 13 #include "clang/Driver/Options.h" 14 #include "clang/Driver/Tool.h" 15 #include "llvm/ADT/STLExtras.h" 16 17 using namespace clang::driver; 18 using namespace clang::driver::toolchains; 19 using namespace clang::driver::tools; 20 using namespace clang; 21 using namespace llvm::opt; 22 23 AMDGPUOpenMPToolChain::AMDGPUOpenMPToolChain(const Driver &D, 24 const llvm::Triple &Triple, 25 const ToolChain &HostTC, 26 const ArgList &Args) 27 : ROCMToolChain(D, Triple, Args), HostTC(HostTC) { 28 // Lookup binaries into the driver directory, this is used to 29 // discover the 'amdgpu-arch' executable. 30 getProgramPaths().push_back(getDriver().Dir); 31 // Diagnose unsupported sanitizer options only once. 32 diagnoseUnsupportedSanitizers(Args); 33 } 34 35 void AMDGPUOpenMPToolChain::addClangTargetOptions( 36 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, 37 Action::OffloadKind DeviceOffloadingKind) const { 38 HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind); 39 40 assert(DeviceOffloadingKind == Action::OFK_OpenMP && 41 "Only OpenMP offloading kinds are supported."); 42 43 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, 44 true)) 45 return; 46 47 for (auto BCFile : getDeviceLibs(DriverArgs)) { 48 CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode" 49 : "-mlink-bitcode-file"); 50 CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path)); 51 } 52 53 // Link the bitcode library late if we're using device LTO. 54 if (getDriver().isUsingOffloadLTO()) 55 return; 56 } 57 58 llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs( 59 const llvm::opt::DerivedArgList &Args, StringRef BoundArch, 60 Action::OffloadKind DeviceOffloadKind) const { 61 DerivedArgList *DAL = 62 HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind); 63 64 if (!DAL) 65 DAL = new DerivedArgList(Args.getBaseArgs()); 66 67 const OptTable &Opts = getDriver().getOpts(); 68 69 // Skip sanitize options passed from the HostTC. Claim them early. 70 // The decision to sanitize device code is computed only by 71 // 'shouldSkipSanitizeOption'. 72 if (DAL->hasArg(options::OPT_fsanitize_EQ)) 73 DAL->claimAllArgs(options::OPT_fsanitize_EQ); 74 75 for (Arg *A : Args) 76 if (!shouldSkipSanitizeOption(*this, Args, BoundArch, A) && 77 !llvm::is_contained(*DAL, A)) 78 DAL->append(A); 79 80 if (!BoundArch.empty()) { 81 DAL->eraseArg(options::OPT_march_EQ); 82 DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), 83 BoundArch); 84 } 85 86 return DAL; 87 } 88 89 void AMDGPUOpenMPToolChain::addClangWarningOptions( 90 ArgStringList &CC1Args) const { 91 AMDGPUToolChain::addClangWarningOptions(CC1Args); 92 HostTC.addClangWarningOptions(CC1Args); 93 } 94 95 ToolChain::CXXStdlibType 96 AMDGPUOpenMPToolChain::GetCXXStdlibType(const ArgList &Args) const { 97 return HostTC.GetCXXStdlibType(Args); 98 } 99 100 void AMDGPUOpenMPToolChain::AddClangCXXStdlibIncludeArgs( 101 const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1Args) const { 102 HostTC.AddClangCXXStdlibIncludeArgs(Args, CC1Args); 103 } 104 105 void AMDGPUOpenMPToolChain::AddClangSystemIncludeArgs( 106 const ArgList &DriverArgs, ArgStringList &CC1Args) const { 107 HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args); 108 } 109 110 void AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs(const ArgList &Args, 111 ArgStringList &CC1Args) const { 112 HostTC.AddIAMCUIncludeArgs(Args, CC1Args); 113 } 114 115 SanitizerMask AMDGPUOpenMPToolChain::getSupportedSanitizers() const { 116 // The AMDGPUOpenMPToolChain only supports sanitizers in the sense that it 117 // allows sanitizer arguments on the command line if they are supported by the 118 // host toolchain. The AMDGPUOpenMPToolChain will actually ignore any command 119 // line arguments for any of these "supported" sanitizers. That means that no 120 // sanitization of device code is actually supported at this time. 121 // 122 // This behavior is necessary because the host and device toolchains 123 // invocations often share the command line, so the device toolchain must 124 // tolerate flags meant only for the host toolchain. 125 return HostTC.getSupportedSanitizers(); 126 } 127 128 VersionTuple 129 AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver *D, 130 const ArgList &Args) const { 131 return HostTC.computeMSVCVersion(D, Args); 132 } 133 134 llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12> 135 AMDGPUOpenMPToolChain::getDeviceLibs(const llvm::opt::ArgList &Args) const { 136 if (!Args.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, true)) 137 return {}; 138 139 StringRef GpuArch = getProcessorFromTargetID( 140 getTriple(), Args.getLastArgValue(options::OPT_march_EQ)); 141 142 SmallVector<BitCodeLibraryInfo, 12> BCLibs; 143 for (auto BCLib : getCommonDeviceLibNames(Args, GpuArch.str(), 144 /*IsOpenMP=*/true)) 145 BCLibs.emplace_back(BCLib); 146 147 return BCLibs; 148 } 149