17 #include "llvm/Support/FileSystem.h" 18 #include "llvm/Support/Path.h" 23 using namespace clang;
26 #if defined(_WIN32) || defined(_WIN64) 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 *Extension) {
54 const char *OutputFileName;
57 C.
getArgs().MakeArgString(Base.str() + Postfix +
"." + Extension);
63 return OutputFileName;
66 static void addOptLevelArgs(
const llvm::opt::ArgList &Args,
67 llvm::opt::ArgStringList &CmdArgs,
69 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
71 if (A->getOption().matches(options::OPT_O4) ||
72 A->getOption().matches(options::OPT_Ofast))
74 else if (A->getOption().matches(options::OPT_O0))
76 else if (A->getOption().matches(options::OPT_O)) {
81 OOpt = llvm::StringSwitch<const char *>(A->getValue())
85 .Case(
"s", IsLlc ?
"2" :
"s")
86 .Case(
"z", IsLlc ?
"2" :
"z")
90 CmdArgs.push_back(Args.MakeArgString(
"-O" + OOpt));
95 const char *AMDGCN::Linker::constructLLVMLinkCommand(
97 const ArgList &Args, StringRef SubArchName,
98 StringRef OutputFilePrefix)
const {
99 ArgStringList CmdArgs;
101 for (
const auto &II : Inputs)
102 CmdArgs.push_back(II.getFilename());
105 CmdArgs.push_back(
"-o");
106 auto OutputFileName = getOutputFileName(C, OutputFilePrefix,
"-linked",
"bc");
107 CmdArgs.push_back(OutputFileName);
109 Args.MakeArgString(getToolChain().GetProgramPath(
"llvm-link"));
110 C.
addCommand(std::make_unique<Command>(JA, *
this, Exec, CmdArgs, Inputs));
111 return OutputFileName;
114 const char *AMDGCN::Linker::constructOptCommand(
116 const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
117 llvm::StringRef OutputFilePrefix,
const char *InputFileName)
const {
119 ArgStringList OptArgs;
121 OptArgs.push_back(InputFileName);
123 addOptLevelArgs(Args, OptArgs);
124 OptArgs.push_back(
"-mtriple=amdgcn-amd-amdhsa");
125 OptArgs.push_back(Args.MakeArgString(
"-mcpu=" + SubArchName));
127 for (
const Arg *A : Args.filtered(options::OPT_mllvm)) {
128 OptArgs.push_back(A->getValue(0));
131 OptArgs.push_back(
"-o");
132 auto OutputFileName =
133 getOutputFileName(C, OutputFilePrefix,
"-optimized",
"bc");
134 OptArgs.push_back(OutputFileName);
135 const char *OptExec =
136 Args.MakeArgString(getToolChain().GetProgramPath(
"opt"));
137 C.
addCommand(std::make_unique<Command>(JA, *
this, OptExec, OptArgs, Inputs));
138 return OutputFileName;
141 const char *AMDGCN::Linker::constructLlcCommand(
143 const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
144 llvm::StringRef OutputFilePrefix,
const char *InputFileName,
145 bool OutputIsAsm)
const {
147 ArgStringList LlcArgs;
149 LlcArgs.push_back(InputFileName);
151 addOptLevelArgs(Args, LlcArgs,
true);
152 LlcArgs.push_back(
"-mtriple=amdgcn-amd-amdhsa");
153 LlcArgs.push_back(Args.MakeArgString(
"-mcpu=" + SubArchName));
155 Args.MakeArgString(Twine(
"-filetype=") + (OutputIsAsm ?
"asm" :
"obj")));
158 std::vector<llvm::StringRef> Features;
160 Args, Features, options::OPT_m_amdgpu_Features_Group);
163 std::string MAttrString =
"-mattr=";
164 for(
auto OneFeature : Features) {
165 MAttrString.append(Args.MakeArgString(OneFeature));
166 if (OneFeature != Features.back())
167 MAttrString.append(
",");
169 if(!Features.empty())
170 LlcArgs.push_back(Args.MakeArgString(MAttrString));
172 for (
const Arg *A : Args.filtered(options::OPT_mllvm)) {
173 LlcArgs.push_back(A->getValue(0));
177 LlcArgs.push_back(
"-o");
179 getOutputFileName(C, OutputFilePrefix,
"", OutputIsAsm ?
"s" :
"o");
180 LlcArgs.push_back(LlcOutputFile);
181 const char *Llc = Args.MakeArgString(getToolChain().GetProgramPath(
"llc"));
182 C.
addCommand(std::make_unique<Command>(JA, *
this, Llc, LlcArgs, Inputs));
183 return LlcOutputFile;
189 const llvm::opt::ArgList &Args,
190 const char *InputFileName)
const {
193 ArgStringList LldArgs{
194 "-flavor",
"gnu",
"-shared",
"-o", Output.
getFilename(), InputFileName};
195 const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath(
"lld"));
196 C.
addCommand(std::make_unique<Command>(JA, *
this, Lld, LldArgs, Inputs));
203 const llvm::opt::ArgList &Args,
const Tool& T) {
206 ArgStringList BundlerArgs;
207 BundlerArgs.push_back(Args.MakeArgString(
"-type=o"));
211 std::string BundlerTargetArg =
"-targets=host-x86_64-unknown-linux";
212 std::string BundlerInputArg =
"-inputs=" NULL_FILE;
214 for (
const auto &II : Inputs) {
215 const auto* A = II.getAction();
216 BundlerTargetArg = BundlerTargetArg +
",hip-amdgcn-amd-amdhsa-" +
217 StringRef(A->getOffloadingArch()).str();
218 BundlerInputArg = BundlerInputArg +
"," + II.getFilename();
220 BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));
221 BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
223 auto BundlerOutputArg =
224 Args.MakeArgString(std::string(
"-outputs=").append(OutputFileName));
225 BundlerArgs.push_back(BundlerOutputArg);
227 const char *Bundler = Args.MakeArgString(
229 C.
addCommand(std::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs));
238 const char *LinkingOutput)
const {
240 if (JA.
getType() == types::TY_HIP_FATBIN)
243 assert(getToolChain().getTriple().getArch() == llvm::Triple::amdgcn &&
244 "Unsupported target");
247 assert(StringRef(SubArchName).startswith(
"gfx") &&
"Unsupported sub arch");
250 std::string Prefix = llvm::sys::path::stem(Inputs[0].getFilename()).str();
252 Prefix +=
"-" + SubArchName;
255 const char *LLVMLinkCommand =
256 constructLLVMLinkCommand(C, JA, Inputs, Args, SubArchName, Prefix);
257 const char *OptCommand = constructOptCommand(C, JA, Inputs, Args, SubArchName,
258 Prefix, LLVMLinkCommand);
260 constructLlcCommand(C, JA, Inputs, Args, SubArchName, Prefix, OptCommand,
262 const char *LlcCommand =
263 constructLlcCommand(C, JA, Inputs, Args, SubArchName, Prefix, OptCommand);
264 constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand);
268 const ToolChain &HostTC,
const ArgList &Args)
269 :
ToolChain(D, Triple, Args), HostTC(HostTC) {
276 const llvm::opt::ArgList &DriverArgs,
277 llvm::opt::ArgStringList &CC1Args,
281 StringRef GpuArch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
282 assert(!GpuArch.empty() &&
"Must have an explicit GPU arch.");
285 "Only HIP offloading kinds are supported for GPUs.");
287 CC1Args.push_back(
"-target-cpu");
288 CC1Args.push_back(DriverArgs.MakeArgStringRef(GpuArch));
289 CC1Args.push_back(
"-fcuda-is-device");
291 if (DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
292 options::OPT_fno_cuda_flush_denormals_to_zero,
false))
293 CC1Args.push_back(
"-fcuda-flush-denormals-to-zero");
295 if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
296 options::OPT_fno_cuda_approx_transcendentals,
false))
297 CC1Args.push_back(
"-fcuda-approx-transcendentals");
299 if (DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
301 CC1Args.push_back(
"-fgpu-rdc");
303 StringRef MaxThreadsPerBlock =
304 DriverArgs.getLastArgValue(options::OPT_gpu_max_threads_per_block_EQ);
305 if (!MaxThreadsPerBlock.empty()) {
307 std::string(
"--gpu-max-threads-per-block=") + MaxThreadsPerBlock.str();
308 CC1Args.push_back(DriverArgs.MakeArgStringRef(ArgStr));
311 if (DriverArgs.hasFlag(options::OPT_fgpu_allow_device_init,
312 options::OPT_fno_gpu_allow_device_init,
false))
313 CC1Args.push_back(
"-fgpu-allow-device-init");
315 CC1Args.push_back(
"-fcuda-allow-variadic-functions");
319 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
320 options::OPT_fvisibility_ms_compat)) {
321 CC1Args.append({
"-fvisibility",
"hidden"});
322 CC1Args.push_back(
"-fapply-global-visibility-to-externs");
325 if (DriverArgs.hasArg(options::OPT_nogpulib))
327 ArgStringList LibraryPaths;
331 DriverArgs.getAllArgValues(options::OPT_hip_device_lib_path_EQ))
332 LibraryPaths.push_back(DriverArgs.MakeArgString(Path));
339 for (
auto Lib : DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ)) {
340 BCLibs.push_back(DriverArgs.MakeArgString(Lib));
344 if (BCLibs.empty()) {
347 std::string GFXVersion = GpuArch.drop_front(3).str();
348 std::string ISAVerBC =
"oclc_isa_version_" + GFXVersion +
".amdgcn.bc";
350 llvm::StringRef FlushDenormalControlBC;
351 if (DriverArgs.hasArg(options::OPT_fcuda_flush_denormals_to_zero))
352 FlushDenormalControlBC =
"oclc_daz_opt_on.amdgcn.bc";
354 FlushDenormalControlBC =
"oclc_daz_opt_off.amdgcn.bc";
356 llvm::StringRef WaveFrontSizeBC;
357 if (stoi(GFXVersion) < 1000)
358 WaveFrontSizeBC =
"oclc_wavefrontsize64_on.amdgcn.bc";
360 WaveFrontSizeBC =
"oclc_wavefrontsize64_off.amdgcn.bc";
362 BCLibs.append({
"hip.amdgcn.bc",
"ocml.amdgcn.bc",
"ockl.amdgcn.bc",
363 "oclc_finite_only_off.amdgcn.bc", FlushDenormalControlBC,
364 "oclc_correctly_rounded_sqrt_on.amdgcn.bc",
365 "oclc_unsafe_math_off.amdgcn.bc", ISAVerBC,
368 for (
auto Lib : BCLibs)
369 addBCLib(
getDriver(), DriverArgs, CC1Args, LibraryPaths, Lib);
372 llvm::opt::DerivedArgList *
376 DerivedArgList *DAL =
379 DAL =
new DerivedArgList(Args.getBaseArgs());
383 for (Arg *A : Args) {
384 if (A->getOption().matches(options::OPT_Xarch__)) {
386 if (BoundArch.empty() || A->getValue(0) != BoundArch)
389 unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
390 unsigned Prev = Index;
391 std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));
401 if (!XarchArg || Index > Prev + 1) {
402 getDriver().
Diag(diag::err_drv_invalid_Xarch_argument_with_args)
403 << A->getAsString(Args);
406 getDriver().
Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
407 << A->getAsString(Args);
410 XarchArg->setBaseArg(A);
411 A = XarchArg.release();
412 DAL->AddSynthesizedArg(A);
417 if (!BoundArch.empty()) {
418 DAL->eraseArg(options::OPT_march_EQ);
419 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch);
440 ArgStringList &CC1Args)
const {
445 ArgStringList &CC1Args)
const {
450 ArgStringList &CC1Args)
const {
468 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
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
bool isSaveTempsEnabled() 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