18 #include "llvm/Support/FileSystem.h" 19 #include "llvm/Support/Path.h" 24 using namespace clang;
28 #define NULL_FILE "nul" 30 #define NULL_FILE "/dev/null" 35 static void addBCLib(
Compilation &C,
const ArgList &Args,
36 ArgStringList &CmdArgs, ArgStringList LibraryPaths,
39 for (std::string LibraryPath : LibraryPaths) {
41 llvm::sys::path::append(Path, BCName);
43 if (llvm::sys::fs::exists(FullName)) {
44 CmdArgs.push_back(Args.MakeArgString(FullName));
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());
62 ArgStringList LibraryPaths;
65 for (
auto Path : Args.getAllArgValues(options::OPT_hip_device_lib_path_EQ))
66 LibraryPaths.push_back(Args.MakeArgString(Path));
73 for (
auto Lib : Args.getAllArgValues(options::OPT_hip_device_lib_EQ)) {
74 BCLibs.push_back(Args.MakeArgString(Lib));
81 std::string ISAVerBC =
82 "oclc_isa_version_" + SubArchName.drop_front(3).str() +
".amdgcn.bc";
84 llvm::StringRef FlushDenormalControlBC;
85 if (Args.hasArg(options::OPT_fcuda_flush_denormals_to_zero))
86 FlushDenormalControlBC =
"oclc_daz_opt_on.amdgcn.bc";
88 FlushDenormalControlBC =
"oclc_daz_opt_off.amdgcn.bc";
90 BCLibs.append({
"hip.amdgcn.bc",
"opencl.amdgcn.bc",
91 "ocml.amdgcn.bc",
"ockl.amdgcn.bc",
92 "oclc_finite_only_off.amdgcn.bc",
93 FlushDenormalControlBC,
94 "oclc_correctly_rounded_sqrt_on.amdgcn.bc",
95 "oclc_unsafe_math_off.amdgcn.bc", ISAVerBC});
97 for (
auto Lib : BCLibs)
98 addBCLib(C, Args, CmdArgs, LibraryPaths, Lib);
101 CmdArgs.push_back(
"-o");
102 std::string TmpName =
104 const char *OutputFileName =
106 CmdArgs.push_back(OutputFileName);
108 llvm::sys::path::append(ExecPath,
"llvm-link");
109 const char *Exec = Args.MakeArgString(ExecPath);
110 C.
addCommand(llvm::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 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
124 StringRef OOpt =
"3";
125 if (A->getOption().matches(options::OPT_O4) ||
126 A->getOption().matches(options::OPT_Ofast))
128 else if (A->getOption().matches(options::OPT_O0))
130 else if (A->getOption().matches(options::OPT_O)) {
132 OOpt = llvm::StringSwitch<const char *>(A->getValue())
140 OptArgs.push_back(Args.MakeArgString(
"-O" + OOpt));
142 OptArgs.push_back(
"-mtriple=amdgcn-amd-amdhsa");
143 OptArgs.push_back(Args.MakeArgString(
"-mcpu=" + SubArchName));
144 OptArgs.push_back(
"-o");
146 OutputFilePrefix.str() +
"-optimized",
"bc");
147 const char *OutputFileName =
149 OptArgs.push_back(OutputFileName);
151 llvm::sys::path::append(OptPath,
"opt");
152 const char *OptExec = Args.MakeArgString(OptPath);
153 C.
addCommand(llvm::make_unique<Command>(JA, *
this, OptExec, OptArgs, Inputs));
154 return OutputFileName;
157 const char *AMDGCN::Linker::constructLlcCommand(
159 const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
160 llvm::StringRef OutputFilePrefix,
const char *InputFileName)
const {
162 ArgStringList LlcArgs{InputFileName,
"-mtriple=amdgcn-amd-amdhsa",
163 "-filetype=obj",
"-mattr=-code-object-v3",
164 Args.MakeArgString(
"-mcpu=" + SubArchName),
"-o"};
165 std::string LlcOutputFileName =
167 const char *LlcOutputFile =
169 LlcArgs.push_back(LlcOutputFile);
171 llvm::sys::path::append(LlcPath,
"llc");
172 const char *Llc = Args.MakeArgString(LlcPath);
173 C.
addCommand(llvm::make_unique<Command>(JA, *
this, Llc, LlcArgs, Inputs));
174 return LlcOutputFile;
180 const llvm::opt::ArgList &Args,
181 const char *InputFileName)
const {
184 ArgStringList LldArgs{
"-flavor",
"gnu",
"--no-undefined",
188 llvm::sys::path::append(LldPath,
"lld");
189 const char *Lld = Args.MakeArgString(LldPath);
190 C.
addCommand(llvm::make_unique<Command>(JA, *
this, Lld, LldArgs, Inputs));
197 const llvm::opt::ArgList &Args,
const Tool& T) {
200 ArgStringList BundlerArgs;
201 BundlerArgs.push_back(Args.MakeArgString(
"-type=o"));
205 std::string BundlerTargetArg =
"-targets=host-x86_64-unknown-linux";
206 std::string BundlerInputArg =
"-inputs=" NULL_FILE;
208 for (
const auto &II : Inputs) {
209 const auto* A = II.getAction();
210 BundlerTargetArg = BundlerTargetArg +
",hip-amdgcn-amd-amdhsa-" +
211 StringRef(A->getOffloadingArch()).
str();
212 BundlerInputArg = BundlerInputArg +
"," + II.getFilename();
214 BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));
215 BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
217 auto BundlerOutputArg =
218 Args.MakeArgString(std::string(
"-outputs=").append(OutputFileName));
219 BundlerArgs.push_back(BundlerOutputArg);
222 llvm::sys::path::append(BundlerPath,
"clang-offload-bundler");
223 const char *Bundler = Args.MakeArgString(BundlerPath);
224 C.
addCommand(llvm::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs));
233 const char *LinkingOutput)
const {
235 if (JA.
getType() == types::TY_HIP_FATBIN)
238 assert(getToolChain().getTriple().getArch() == llvm::Triple::amdgcn &&
239 "Unsupported target");
242 assert(StringRef(SubArchName).startswith(
"gfx") &&
"Unsupported sub arch");
246 llvm::sys::path::stem(Inputs[0].getFilename()).str() +
"-" + SubArchName;
249 const char *LLVMLinkCommand =
250 constructLLVMLinkCommand(C, JA, Inputs, Args, SubArchName, Prefix);
251 const char *OptCommand = constructOptCommand(C, JA, Inputs, Args, SubArchName,
252 Prefix, LLVMLinkCommand);
253 const char *LlcCommand =
254 constructLlcCommand(C, JA, Inputs, Args, SubArchName, Prefix, OptCommand);
255 constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand);
259 const ToolChain &HostTC,
const ArgList &Args)
260 :
ToolChain(D, Triple, Args), HostTC(HostTC) {
267 const llvm::opt::ArgList &DriverArgs,
268 llvm::opt::ArgStringList &CC1Args,
272 StringRef GpuArch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
273 assert(!GpuArch.empty() &&
"Must have an explicit GPU arch.");
276 "Only HIP offloading kinds are supported for GPUs.");
278 CC1Args.push_back(
"-target-cpu");
279 CC1Args.push_back(DriverArgs.MakeArgStringRef(GpuArch));
280 CC1Args.push_back(
"-fcuda-is-device");
282 if (DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
283 options::OPT_fno_cuda_flush_denormals_to_zero,
false))
284 CC1Args.push_back(
"-fcuda-flush-denormals-to-zero");
286 if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
287 options::OPT_fno_cuda_approx_transcendentals,
false))
288 CC1Args.push_back(
"-fcuda-approx-transcendentals");
290 if (DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
292 CC1Args.push_back(
"-fgpu-rdc");
296 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
297 options::OPT_fvisibility_ms_compat))
298 CC1Args.append({
"-fvisibility",
"hidden"});
301 llvm::opt::DerivedArgList *
305 DerivedArgList *DAL =
308 DAL =
new DerivedArgList(Args.getBaseArgs());
312 for (Arg *A : Args) {
313 if (A->getOption().matches(options::OPT_Xarch__)) {
315 if (BoundArch.empty() || A->getValue(0) != BoundArch)
318 unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
319 unsigned Prev = Index;
320 std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));
330 if (!XarchArg || Index > Prev + 1) {
331 getDriver().
Diag(diag::err_drv_invalid_Xarch_argument_with_args)
332 << A->getAsString(Args);
335 getDriver().
Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
336 << A->getAsString(Args);
339 XarchArg->setBaseArg(A);
340 A = XarchArg.release();
341 DAL->AddSynthesizedArg(A);
346 if (!BoundArch.empty()) {
347 DAL->eraseArg(options::OPT_march_EQ);
348 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch);
369 ArgStringList &CC1Args)
const {
374 ArgStringList &CC1Args)
const {
379 ArgStringList &CC1Args)
const {
397 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