17 #include "llvm/Support/FileSystem.h" 18 #include "llvm/Support/Path.h" 23 using namespace clang;
27 #define NULL_FILE "nul" 29 #define NULL_FILE "/dev/null" 34 static void addBCLib(
const Driver &D,
const ArgList &Args,
35 ArgStringList &CmdArgs, ArgStringList LibraryPaths,
38 for (std::string LibraryPath : LibraryPaths) {
40 llvm::sys::path::append(Path, BCName);
42 if (llvm::sys::fs::exists(FullName)) {
43 CmdArgs.push_back(
"-mlink-builtin-bitcode");
44 CmdArgs.push_back(Args.MakeArgString(FullName));
48 D.
Diag(diag::err_drv_no_such_file) << BCName;
53 const char *AMDGCN::Linker::constructLLVMLinkCommand(
55 const ArgList &Args, StringRef SubArchName,
56 StringRef OutputFilePrefix)
const {
57 ArgStringList CmdArgs;
59 for (
const auto &II : Inputs)
60 CmdArgs.push_back(II.getFilename());
63 CmdArgs.push_back(
"-o");
66 const char *OutputFileName =
68 CmdArgs.push_back(OutputFileName);
70 llvm::sys::path::append(ExecPath,
"llvm-link");
71 const char *Exec = Args.MakeArgString(ExecPath);
72 C.
addCommand(llvm::make_unique<Command>(JA, *
this, Exec, CmdArgs, Inputs));
73 return OutputFileName;
76 const char *AMDGCN::Linker::constructOptCommand(
78 const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
79 llvm::StringRef OutputFilePrefix,
const char *InputFileName)
const {
81 ArgStringList OptArgs;
83 OptArgs.push_back(InputFileName);
85 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
87 if (A->getOption().matches(options::OPT_O4) ||
88 A->getOption().matches(options::OPT_Ofast))
90 else if (A->getOption().matches(options::OPT_O0))
92 else if (A->getOption().matches(options::OPT_O)) {
94 OOpt = llvm::StringSwitch<const char *>(A->getValue())
102 OptArgs.push_back(Args.MakeArgString(
"-O" + OOpt));
104 OptArgs.push_back(
"-mtriple=amdgcn-amd-amdhsa");
105 OptArgs.push_back(Args.MakeArgString(
"-mcpu=" + SubArchName));
107 for (
const Arg *A : Args.filtered(options::OPT_mllvm)) {
108 OptArgs.push_back(A->getValue(0));
111 OptArgs.push_back(
"-o");
113 OutputFilePrefix.str() +
"-optimized",
"bc");
114 const char *OutputFileName =
116 OptArgs.push_back(OutputFileName);
118 llvm::sys::path::append(OptPath,
"opt");
119 const char *OptExec = Args.MakeArgString(OptPath);
120 C.
addCommand(llvm::make_unique<Command>(JA, *
this, OptExec, OptArgs, Inputs));
121 return OutputFileName;
124 const char *AMDGCN::Linker::constructLlcCommand(
126 const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
127 llvm::StringRef OutputFilePrefix,
const char *InputFileName)
const {
129 ArgStringList LlcArgs{InputFileName,
"-mtriple=amdgcn-amd-amdhsa",
131 Args.MakeArgString(
"-mcpu=" + SubArchName)};
134 std::vector<llvm::StringRef> Features;
136 Args, Features, options::OPT_m_amdgpu_Features_Group);
139 std::string MAttrString =
"-mattr=";
140 for(
auto OneFeature : Features) {
141 MAttrString.append(Args.MakeArgString(OneFeature));
142 if (OneFeature != Features.back())
143 MAttrString.append(
",");
145 if(!Features.empty())
146 LlcArgs.push_back(Args.MakeArgString(MAttrString));
148 for (
const Arg *A : Args.filtered(options::OPT_mllvm)) {
149 LlcArgs.push_back(A->getValue(0));
153 LlcArgs.push_back(
"-o");
154 std::string LlcOutputFileName =
156 const char *LlcOutputFile =
158 LlcArgs.push_back(LlcOutputFile);
160 llvm::sys::path::append(LlcPath,
"llc");
161 const char *Llc = Args.MakeArgString(LlcPath);
162 C.
addCommand(llvm::make_unique<Command>(JA, *
this, Llc, LlcArgs, Inputs));
163 return LlcOutputFile;
169 const llvm::opt::ArgList &Args,
170 const char *InputFileName)
const {
173 ArgStringList LldArgs{
174 "-flavor",
"gnu",
"-shared",
"-o", Output.
getFilename(), InputFileName};
176 llvm::sys::path::append(LldPath,
"lld");
177 const char *Lld = Args.MakeArgString(LldPath);
178 C.
addCommand(llvm::make_unique<Command>(JA, *
this, Lld, LldArgs, Inputs));
185 const llvm::opt::ArgList &Args,
const Tool& T) {
188 ArgStringList BundlerArgs;
189 BundlerArgs.push_back(Args.MakeArgString(
"-type=o"));
193 std::string BundlerTargetArg =
"-targets=host-x86_64-unknown-linux";
194 std::string BundlerInputArg =
"-inputs=" NULL_FILE;
196 for (
const auto &II : Inputs) {
197 const auto* A = II.getAction();
198 BundlerTargetArg = BundlerTargetArg +
",hip-amdgcn-amd-amdhsa-" +
199 StringRef(A->getOffloadingArch()).str();
200 BundlerInputArg = BundlerInputArg +
"," + II.getFilename();
202 BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));
203 BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
205 auto BundlerOutputArg =
206 Args.MakeArgString(std::string(
"-outputs=").append(OutputFileName));
207 BundlerArgs.push_back(BundlerOutputArg);
210 llvm::sys::path::append(BundlerPath,
"clang-offload-bundler");
211 const char *Bundler = Args.MakeArgString(BundlerPath);
212 C.
addCommand(llvm::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs));
221 const char *LinkingOutput)
const {
223 if (JA.
getType() == types::TY_HIP_FATBIN)
226 assert(getToolChain().getTriple().getArch() == llvm::Triple::amdgcn &&
227 "Unsupported target");
230 assert(StringRef(SubArchName).startswith(
"gfx") &&
"Unsupported sub arch");
234 llvm::sys::path::stem(Inputs[0].getFilename()).str() +
"-" + SubArchName;
237 const char *LLVMLinkCommand =
238 constructLLVMLinkCommand(C, JA, Inputs, Args, SubArchName, Prefix);
239 const char *OptCommand = constructOptCommand(C, JA, Inputs, Args, SubArchName,
240 Prefix, LLVMLinkCommand);
241 const char *LlcCommand =
242 constructLlcCommand(C, JA, Inputs, Args, SubArchName, Prefix, OptCommand);
243 constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand);
247 const ToolChain &HostTC,
const ArgList &Args)
248 :
ToolChain(D, Triple, Args), HostTC(HostTC) {
255 const llvm::opt::ArgList &DriverArgs,
256 llvm::opt::ArgStringList &CC1Args,
260 StringRef GpuArch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
261 assert(!GpuArch.empty() &&
"Must have an explicit GPU arch.");
264 "Only HIP offloading kinds are supported for GPUs.");
266 CC1Args.push_back(
"-target-cpu");
267 CC1Args.push_back(DriverArgs.MakeArgStringRef(GpuArch));
268 CC1Args.push_back(
"-fcuda-is-device");
270 if (DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
271 options::OPT_fno_cuda_flush_denormals_to_zero,
false))
272 CC1Args.push_back(
"-fcuda-flush-denormals-to-zero");
274 if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
275 options::OPT_fno_cuda_approx_transcendentals,
false))
276 CC1Args.push_back(
"-fcuda-approx-transcendentals");
278 if (DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
280 CC1Args.push_back(
"-fgpu-rdc");
284 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
285 options::OPT_fvisibility_ms_compat)) {
286 CC1Args.append({
"-fvisibility",
"hidden"});
287 CC1Args.push_back(
"-fapply-global-visibility-to-externs");
289 ArgStringList LibraryPaths;
293 DriverArgs.getAllArgValues(options::OPT_hip_device_lib_path_EQ))
294 LibraryPaths.push_back(DriverArgs.MakeArgString(Path));
301 for (
auto Lib : DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ)) {
302 BCLibs.push_back(DriverArgs.MakeArgString(Lib));
306 if (BCLibs.empty()) {
309 std::string GFXVersion = GpuArch.drop_front(3).str();
310 std::string ISAVerBC =
"oclc_isa_version_" + GFXVersion +
".amdgcn.bc";
312 llvm::StringRef FlushDenormalControlBC;
313 if (DriverArgs.hasArg(options::OPT_fcuda_flush_denormals_to_zero))
314 FlushDenormalControlBC =
"oclc_daz_opt_on.amdgcn.bc";
316 FlushDenormalControlBC =
"oclc_daz_opt_off.amdgcn.bc";
318 llvm::StringRef WaveFrontSizeBC;
319 if (stoi(GFXVersion) < 1000)
320 WaveFrontSizeBC =
"oclc_wavefrontsize64_on.amdgcn.bc";
322 WaveFrontSizeBC =
"oclc_wavefrontsize64_off.amdgcn.bc";
324 BCLibs.append({
"hip.amdgcn.bc",
"opencl.amdgcn.bc",
"ocml.amdgcn.bc",
325 "ockl.amdgcn.bc",
"oclc_finite_only_off.amdgcn.bc",
326 FlushDenormalControlBC,
327 "oclc_correctly_rounded_sqrt_on.amdgcn.bc",
328 "oclc_unsafe_math_off.amdgcn.bc", ISAVerBC,
331 for (
auto Lib : BCLibs)
332 addBCLib(
getDriver(), DriverArgs, CC1Args, LibraryPaths, Lib);
335 llvm::opt::DerivedArgList *
339 DerivedArgList *DAL =
342 DAL =
new DerivedArgList(Args.getBaseArgs());
346 for (Arg *A : Args) {
347 if (A->getOption().matches(options::OPT_Xarch__)) {
349 if (BoundArch.empty() || A->getValue(0) != BoundArch)
352 unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
353 unsigned Prev = Index;
354 std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));
364 if (!XarchArg || Index > Prev + 1) {
365 getDriver().
Diag(diag::err_drv_invalid_Xarch_argument_with_args)
366 << A->getAsString(Args);
369 getDriver().
Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
370 << A->getAsString(Args);
373 XarchArg->setBaseArg(A);
374 A = XarchArg.release();
375 DAL->AddSynthesizedArg(A);
380 if (!BoundArch.empty()) {
381 DAL->eraseArg(options::OPT_march_EQ);
382 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch);
403 ArgStringList &CC1Args)
const {
408 ArgStringList &CC1Args)
const {
413 ArgStringList &CC1Args)
const {
431 const ArgList &Args)
const {
std::string GetTemporaryPath(StringRef Prefix, StringRef Suffix) const
GetTemporaryPath - Return the pathname of a temporary file to use as part of compilation; the file wi...
DiagnosticBuilder Diag(unsigned DiagID) const
std::string Dir
The path the driver executable was in, as invoked from the command line.
types::ID getType() const
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
void addCommand(std::unique_ptr< Command > C)
const llvm::opt::DerivedArgList & getArgs() const
Dataflow Directional Tag Classes.
Compilation - A set of tasks to perform for a single driver invocation.
const Driver & getDriver() const
const llvm::opt::OptTable & getOpts() const
const char * addTempFile(const char *Name)
addTempFile - Add a file to remove on exit, and returns its argument.
const char * getOffloadingArch() const