18 #include "llvm/Support/FileSystem.h" 19 #include "llvm/Support/Path.h" 24 using namespace clang;
29 static void addBCLib(
Compilation &C,
const ArgList &Args,
30 ArgStringList &CmdArgs, ArgStringList LibraryPaths,
33 for (std::string LibraryPath : LibraryPaths) {
35 llvm::sys::path::append(Path, BCName);
37 if (llvm::sys::fs::exists(FullName)) {
38 CmdArgs.push_back(Args.MakeArgString(FullName));
47 const char *AMDGCN::Linker::constructLLVMLinkCommand(
49 const ArgList &Args, StringRef SubArchName,
50 StringRef OutputFilePrefix)
const {
51 ArgStringList CmdArgs;
53 for (
const auto &II : Inputs)
54 CmdArgs.push_back(II.getFilename());
56 ArgStringList LibraryPaths;
59 for (
auto Path : Args.getAllArgValues(options::OPT_hip_device_lib_path_EQ))
60 LibraryPaths.push_back(Args.MakeArgString(Path));
67 for (
auto Lib : Args.getAllArgValues(options::OPT_hip_device_lib_EQ)) {
68 BCLibs.push_back(Args.MakeArgString(Lib));
75 std::string ISAVerBC =
76 "oclc_isa_version_" + SubArchName.drop_front(3).str() +
".amdgcn.bc";
78 llvm::StringRef FlushDenormalControlBC;
79 if (Args.hasArg(options::OPT_fcuda_flush_denormals_to_zero))
80 FlushDenormalControlBC =
"oclc_daz_opt_on.amdgcn.bc";
82 FlushDenormalControlBC =
"oclc_daz_opt_off.amdgcn.bc";
84 BCLibs.append({
"opencl.amdgcn.bc",
85 "ocml.amdgcn.bc",
"ockl.amdgcn.bc",
"irif.amdgcn.bc",
86 "oclc_finite_only_off.amdgcn.bc",
87 FlushDenormalControlBC,
88 "oclc_correctly_rounded_sqrt_on.amdgcn.bc",
89 "oclc_unsafe_math_off.amdgcn.bc", ISAVerBC});
91 for (
auto Lib : BCLibs)
92 addBCLib(C, Args, CmdArgs, LibraryPaths, Lib);
95 CmdArgs.push_back(
"-o");
98 const char *OutputFileName =
100 CmdArgs.push_back(OutputFileName);
102 llvm::sys::path::append(ExecPath,
"llvm-link");
103 const char *Exec = Args.MakeArgString(ExecPath);
104 C.
addCommand(llvm::make_unique<Command>(JA, *
this, Exec, CmdArgs, Inputs));
105 return OutputFileName;
108 const char *AMDGCN::Linker::constructOptCommand(
110 const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
111 llvm::StringRef OutputFilePrefix,
const char *InputFileName)
const {
113 ArgStringList OptArgs;
115 OptArgs.push_back(InputFileName);
117 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
118 StringRef OOpt =
"3";
119 if (A->getOption().matches(options::OPT_O4) ||
120 A->getOption().matches(options::OPT_Ofast))
122 else if (A->getOption().matches(options::OPT_O0))
124 else if (A->getOption().matches(options::OPT_O)) {
126 OOpt = llvm::StringSwitch<const char *>(A->getValue())
134 OptArgs.push_back(Args.MakeArgString(
"-O" + OOpt));
136 OptArgs.push_back(
"-mtriple=amdgcn-amd-amdhsa");
137 OptArgs.push_back(Args.MakeArgString(
"-mcpu=" + SubArchName));
138 OptArgs.push_back(
"-o");
140 OutputFilePrefix.str() +
"-optimized",
"bc");
141 const char *OutputFileName =
143 OptArgs.push_back(OutputFileName);
145 llvm::sys::path::append(OptPath,
"opt");
146 const char *OptExec = Args.MakeArgString(OptPath);
147 C.
addCommand(llvm::make_unique<Command>(JA, *
this, OptExec, OptArgs, Inputs));
148 return OutputFileName;
151 const char *AMDGCN::Linker::constructLlcCommand(
153 const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
154 llvm::StringRef OutputFilePrefix,
const char *InputFileName)
const {
156 ArgStringList LlcArgs{InputFileName,
"-mtriple=amdgcn-amd-amdhsa",
158 Args.MakeArgString(
"-mcpu=" + SubArchName),
"-o"};
159 std::string LlcOutputFileName =
161 const char *LlcOutputFile =
163 LlcArgs.push_back(LlcOutputFile);
165 llvm::sys::path::append(LlcPath,
"llc");
166 const char *Llc = Args.MakeArgString(LlcPath);
167 C.
addCommand(llvm::make_unique<Command>(JA, *
this, Llc, LlcArgs, Inputs));
168 return LlcOutputFile;
174 const llvm::opt::ArgList &Args,
175 const char *InputFileName)
const {
178 ArgStringList LldArgs{
"-flavor",
"gnu",
"--no-undefined",
182 llvm::sys::path::append(LldPath,
"lld");
183 const char *Lld = Args.MakeArgString(LldPath);
184 C.
addCommand(llvm::make_unique<Command>(JA, *
this, Lld, LldArgs, Inputs));
193 const char *LinkingOutput)
const {
195 assert(getToolChain().getTriple().getArch() == llvm::Triple::amdgcn &&
196 "Unsupported target");
199 assert(StringRef(SubArchName).startswith(
"gfx") &&
"Unsupported sub arch");
203 llvm::sys::path::stem(Inputs[0].getFilename()).str() +
"-" + SubArchName;
206 const char *LLVMLinkCommand =
207 constructLLVMLinkCommand(C, JA, Inputs, Args, SubArchName, Prefix);
208 const char *OptCommand = constructOptCommand(C, JA, Inputs, Args, SubArchName,
209 Prefix, LLVMLinkCommand);
210 const char *LlcCommand =
211 constructLlcCommand(C, JA, Inputs, Args, SubArchName, Prefix, OptCommand);
212 constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand);
216 const ToolChain &HostTC,
const ArgList &Args)
217 :
ToolChain(D, Triple, Args), HostTC(HostTC) {
224 const llvm::opt::ArgList &DriverArgs,
225 llvm::opt::ArgStringList &CC1Args,
229 StringRef GpuArch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
230 assert(!GpuArch.empty() &&
"Must have an explicit GPU arch.");
233 "Only HIP offloading kinds are supported for GPUs.");
235 CC1Args.push_back(
"-target-cpu");
236 CC1Args.push_back(DriverArgs.MakeArgStringRef(GpuArch));
237 CC1Args.push_back(
"-fcuda-is-device");
239 if (DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
240 options::OPT_fno_cuda_flush_denormals_to_zero,
false))
241 CC1Args.push_back(
"-fcuda-flush-denormals-to-zero");
243 if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
244 options::OPT_fno_cuda_approx_transcendentals,
false))
245 CC1Args.push_back(
"-fcuda-approx-transcendentals");
247 if (DriverArgs.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc,
249 CC1Args.push_back(
"-fcuda-rdc");
252 llvm::opt::DerivedArgList *
256 DerivedArgList *DAL =
259 DAL =
new DerivedArgList(Args.getBaseArgs());
263 for (Arg *A : Args) {
264 if (A->getOption().matches(options::OPT_Xarch__)) {
266 if (BoundArch.empty() || A->getValue(0) != BoundArch)
269 unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
270 unsigned Prev = Index;
271 std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));
281 if (!XarchArg || Index > Prev + 1) {
282 getDriver().
Diag(diag::err_drv_invalid_Xarch_argument_with_args)
283 << A->getAsString(Args);
286 getDriver().
Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
287 << A->getAsString(Args);
290 XarchArg->setBaseArg(A);
291 A = XarchArg.release();
292 DAL->AddSynthesizedArg(A);
297 if (!BoundArch.empty()) {
298 DAL->eraseArg(options::OPT_march_EQ);
299 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch);
320 ArgStringList &CC1Args)
const {
325 ArgStringList &CC1Args)
const {
330 ArgStringList &CC1Args)
const {
348 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.
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