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/Tool.h"
14#include "clang/Options/Options.h"
15#include "llvm/ADT/STLExtras.h"
16
17using namespace clang::driver;
18using namespace clang::driver::toolchains;
19using namespace clang::driver::tools;
20using namespace clang;
21using namespace llvm::opt;
22
23AMDGPUOpenMPToolChain::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(Elt: getDriver().Dir);
31}
32
33void AMDGPUOpenMPToolChain::addClangTargetOptions(
34 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
35 Action::OffloadKind DeviceOffloadingKind) const {
36 HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind: DeviceOffloadingKind);
37
38 assert(DeviceOffloadingKind == Action::OFK_OpenMP &&
39 "Only OpenMP offloading kinds are supported.");
40
41 if (!DriverArgs.hasFlag(Pos: options::OPT_offloadlib, Neg: options::OPT_no_offloadlib,
42 Default: true))
43 return;
44
45 for (auto BCFile : getDeviceLibs(Args: DriverArgs, DeviceOffloadKind: DeviceOffloadingKind)) {
46 CC1Args.push_back(Elt: BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
47 : "-mlink-bitcode-file");
48 CC1Args.push_back(Elt: DriverArgs.MakeArgString(Str: BCFile.Path));
49 }
50
51 // Link the bitcode library late if we're using device LTO.
52 if (getDriver().isUsingOffloadLTO())
53 return;
54}
55
56llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs(
57 const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
58 Action::OffloadKind DeviceOffloadKind) const {
59 DerivedArgList *DAL =
60 HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind);
61
62 if (!DAL)
63 DAL = new DerivedArgList(Args.getBaseArgs());
64
65 const OptTable &Opts = getDriver().getOpts();
66
67 for (Arg *A : Args) {
68 // Filter unsupported sanitizers passed from the HostTC.
69 if (!handleSanitizeOption(TC: *this, DAL&: *DAL, DriverArgs: Args, TargetID: BoundArch, A))
70 DAL->append(A);
71 }
72
73 if (!BoundArch.empty()) {
74 DAL->eraseArg(Id: options::OPT_march_EQ);
75 DAL->AddJoinedArg(BaseArg: nullptr, Opt: Opts.getOption(Opt: options::OPT_march_EQ),
76 Value: BoundArch);
77 }
78
79 return DAL;
80}
81
82void AMDGPUOpenMPToolChain::addClangWarningOptions(
83 ArgStringList &CC1Args) const {
84 AMDGPUToolChain::addClangWarningOptions(CC1Args);
85 HostTC.addClangWarningOptions(CC1Args);
86}
87
88ToolChain::CXXStdlibType
89AMDGPUOpenMPToolChain::GetCXXStdlibType(const ArgList &Args) const {
90 return HostTC.GetCXXStdlibType(Args);
91}
92
93void AMDGPUOpenMPToolChain::AddClangCXXStdlibIncludeArgs(
94 const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1Args) const {
95 HostTC.AddClangCXXStdlibIncludeArgs(DriverArgs: Args, CC1Args);
96}
97
98void AMDGPUOpenMPToolChain::AddClangSystemIncludeArgs(
99 const ArgList &DriverArgs, ArgStringList &CC1Args) const {
100 HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
101}
102
103void AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
104 ArgStringList &CC1Args) const {
105 HostTC.AddIAMCUIncludeArgs(DriverArgs: Args, CC1Args);
106}
107
108SanitizerMask AMDGPUOpenMPToolChain::getSupportedSanitizers() const {
109 // The AMDGPUOpenMPToolChain only supports sanitizers in the sense that it
110 // allows sanitizer arguments on the command line if they are supported by the
111 // host toolchain. The AMDGPUOpenMPToolChain will later filter unsupported
112 // sanitizers from the command line arguments.
113 //
114 // This behavior is necessary because the host and device toolchains
115 // invocations often share the command line, so the device toolchain must
116 // tolerate flags meant only for the host toolchain.
117 return HostTC.getSupportedSanitizers();
118}
119
120VersionTuple
121AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver *D,
122 const ArgList &Args) const {
123 return HostTC.computeMSVCVersion(D, Args);
124}
125
126llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
127AMDGPUOpenMPToolChain::getDeviceLibs(
128 const llvm::opt::ArgList &Args,
129 const Action::OffloadKind DeviceOffloadingKind) const {
130 if (!Args.hasFlag(Pos: options::OPT_offloadlib, Neg: options::OPT_no_offloadlib, Default: true))
131 return {};
132
133 StringRef GpuArch = getProcessorFromTargetID(
134 T: getTriple(), OffloadArch: Args.getLastArgValue(Id: options::OPT_march_EQ));
135
136 SmallVector<BitCodeLibraryInfo, 12> BCLibs;
137 for (auto BCLib :
138 getCommonDeviceLibNames(DriverArgs: Args, GPUArch: GpuArch.str(), DeviceOffloadingKind))
139 BCLibs.emplace_back(Args&: BCLib);
140
141 return BCLibs;
142}
143