1 //===-- clang-linker-wrapper/ClangLinkerWrapper.cpp - wrapper over linker-===//
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 // This tool works as a wrapper over a linking job. This tool is used to create
10 // linked device images for offloading. It scans the linker's input for embedded
11 // device offloading data stored in sections `.llvm.offloading` and extracts it
12 // as a temporary file. The extracted device files will then be passed to a
13 // device linking job to create a final device image.
14 //
15 //===---------------------------------------------------------------------===//
16 
17 #include "OffloadWrapper.h"
18 #include "clang/Basic/Version.h"
19 #include "llvm/BinaryFormat/Magic.h"
20 #include "llvm/Bitcode/BitcodeWriter.h"
21 #include "llvm/CodeGen/CommandFlags.h"
22 #include "llvm/IR/Constants.h"
23 #include "llvm/IR/DiagnosticPrinter.h"
24 #include "llvm/IR/Module.h"
25 #include "llvm/IRReader/IRReader.h"
26 #include "llvm/LTO/LTO.h"
27 #include "llvm/MC/TargetRegistry.h"
28 #include "llvm/Object/Archive.h"
29 #include "llvm/Object/ArchiveWriter.h"
30 #include "llvm/Object/Binary.h"
31 #include "llvm/Object/ELFObjectFile.h"
32 #include "llvm/Object/IRObjectFile.h"
33 #include "llvm/Object/ObjectFile.h"
34 #include "llvm/Object/OffloadBinary.h"
35 #include "llvm/Option/ArgList.h"
36 #include "llvm/Option/OptTable.h"
37 #include "llvm/Option/Option.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/Errc.h"
40 #include "llvm/Support/FileOutputBuffer.h"
41 #include "llvm/Support/FileSystem.h"
42 #include "llvm/Support/Host.h"
43 #include "llvm/Support/InitLLVM.h"
44 #include "llvm/Support/MemoryBuffer.h"
45 #include "llvm/Support/Path.h"
46 #include "llvm/Support/Program.h"
47 #include "llvm/Support/Signals.h"
48 #include "llvm/Support/SourceMgr.h"
49 #include "llvm/Support/StringSaver.h"
50 #include "llvm/Support/TargetSelect.h"
51 #include "llvm/Support/WithColor.h"
52 #include "llvm/Support/raw_ostream.h"
53 #include "llvm/Target/TargetMachine.h"
54 
55 using namespace llvm;
56 using namespace llvm::opt;
57 using namespace llvm::object;
58 
59 /// Path of the current binary.
60 static const char *LinkerExecutable;
61 
62 /// Ssave intermediary results.
63 static bool SaveTemps = false;
64 
65 /// Print arguments without executing.
66 static bool DryRun = false;
67 
68 /// Print verbose output.
69 static bool Verbose = false;
70 
71 /// Filename of the executable being created.
72 static StringRef ExecutableName;
73 
74 /// Binary path for the CUDA installation.
75 static std::string CudaBinaryPath;
76 
77 /// Temporary files created by the linker wrapper.
78 static std::list<SmallString<128>> TempFiles;
79 
80 /// Codegen flags for LTO backend.
81 static codegen::RegisterCodeGenFlags CodeGenFlags;
82 
83 /// Global flag to indicate that the LTO pipeline threw an error.
84 static std::atomic<bool> LTOError;
85 
86 using OffloadingImage = OffloadBinary::OffloadingImage;
87 
88 /// A class to contain the binary information for a single OffloadBinary.
89 class OffloadFile : public OwningBinary<OffloadBinary> {
90 public:
91   using TargetID = std::pair<StringRef, StringRef>;
92 
93   OffloadFile(std::unique_ptr<OffloadBinary> Binary,
94               std::unique_ptr<MemoryBuffer> Buffer)
95       : OwningBinary<OffloadBinary>(std::move(Binary), std::move(Buffer)) {}
96 
97   /// We use the Triple and Architecture pair to group linker inputs together.
98   /// This conversion function lets us use these files in a hash-map.
99   operator TargetID() const {
100     return std::make_pair(getBinary()->getTriple(), getBinary()->getArch());
101   }
102 };
103 
104 namespace llvm {
105 // Provide DenseMapInfo so that OffloadKind can be used in a DenseMap.
106 template <> struct DenseMapInfo<OffloadKind> {
107   static inline OffloadKind getEmptyKey() { return OFK_LAST; }
108   static inline OffloadKind getTombstoneKey() {
109     return static_cast<OffloadKind>(OFK_LAST + 1);
110   }
111   static unsigned getHashValue(const OffloadKind &Val) { return Val; }
112 
113   static bool isEqual(const OffloadKind &LHS, const OffloadKind &RHS) {
114     return LHS == RHS;
115   }
116 };
117 } // namespace llvm
118 
119 namespace {
120 using std::error_code;
121 
122 /// Must not overlap with llvm::opt::DriverFlag.
123 enum WrapperFlags {
124   WrapperOnlyOption = (1 << 4), // Options only used by the linker wrapper.
125   DeviceOnlyOption = (1 << 5),  // Options only used for device linking.
126 };
127 
128 enum ID {
129   OPT_INVALID = 0, // This is not an option ID.
130 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
131                HELPTEXT, METAVAR, VALUES)                                      \
132   OPT_##ID,
133 #include "LinkerWrapperOpts.inc"
134   LastOption
135 #undef OPTION
136 };
137 
138 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
139 #include "LinkerWrapperOpts.inc"
140 #undef PREFIX
141 
142 static const OptTable::Info InfoTable[] = {
143 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
144                HELPTEXT, METAVAR, VALUES)                                      \
145   {PREFIX, NAME,  HELPTEXT,    METAVAR,     OPT_##ID,  Option::KIND##Class,    \
146    PARAM,  FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, VALUES},
147 #include "LinkerWrapperOpts.inc"
148 #undef OPTION
149 };
150 
151 class WrapperOptTable : public opt::OptTable {
152 public:
153   WrapperOptTable() : OptTable(InfoTable) {}
154 };
155 
156 const OptTable &getOptTable() {
157   static const WrapperOptTable *Table = []() {
158     auto Result = std::make_unique<WrapperOptTable>();
159     return Result.release();
160   }();
161   return *Table;
162 }
163 
164 Error extractFromBuffer(std::unique_ptr<MemoryBuffer> Buffer,
165                         SmallVectorImpl<OffloadFile> &DeviceFiles);
166 
167 void printCommands(ArrayRef<StringRef> CmdArgs) {
168   if (CmdArgs.empty())
169     return;
170 
171   llvm::errs() << " \"" << CmdArgs.front() << "\" ";
172   for (auto IC = std::next(CmdArgs.begin()), IE = CmdArgs.end(); IC != IE; ++IC)
173     llvm::errs() << *IC << (std::next(IC) != IE ? " " : "\n");
174 }
175 
176 [[noreturn]] void reportError(Error E) {
177   outs().flush();
178   logAllUnhandledErrors(std::move(E),
179                         WithColor::error(errs(), LinkerExecutable));
180   exit(EXIT_FAILURE);
181 }
182 
183 /// Create an extra user-specified \p OffloadFile.
184 /// TODO: We should find a way to wrap these as libraries instead.
185 Expected<OffloadFile> getInputBitcodeLibrary(StringRef Input) {
186   auto DeviceAndPath = StringRef(Input).split('=');
187   auto StringAndArch = DeviceAndPath.first.rsplit('-');
188   auto KindAndTriple = StringAndArch.first.split('-');
189 
190   llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> ImageOrError =
191       llvm::MemoryBuffer::getFileOrSTDIN(DeviceAndPath.second);
192   if (std::error_code EC = ImageOrError.getError())
193     return createFileError(DeviceAndPath.second, EC);
194 
195   OffloadingImage Image{};
196   Image.TheImageKind = IMG_Bitcode;
197   Image.TheOffloadKind = getOffloadKind(KindAndTriple.first);
198   Image.StringData = {{"triple", KindAndTriple.second},
199                       {"arch", StringAndArch.second}};
200   Image.Image = std::move(*ImageOrError);
201 
202   std::unique_ptr<MemoryBuffer> Binary = OffloadBinary::write(Image);
203   auto NewBinaryOrErr = OffloadBinary::create(*Binary);
204   if (!NewBinaryOrErr)
205     return NewBinaryOrErr.takeError();
206   return OffloadFile(std::move(*NewBinaryOrErr), std::move(Binary));
207 }
208 
209 std::string getMainExecutable(const char *Name) {
210   void *Ptr = (void *)(intptr_t)&getMainExecutable;
211   auto COWPath = sys::fs::getMainExecutable(Name, Ptr);
212   return sys::path::parent_path(COWPath).str();
213 }
214 
215 /// Get a temporary filename suitable for output.
216 Expected<StringRef> createOutputFile(const Twine &Prefix, StringRef Extension) {
217   SmallString<128> OutputFile;
218   if (SaveTemps) {
219     (Prefix + "." + Extension).toNullTerminatedStringRef(OutputFile);
220   } else {
221     if (std::error_code EC =
222             sys::fs::createTemporaryFile(Prefix, Extension, OutputFile))
223       return createFileError(OutputFile, EC);
224   }
225 
226   TempFiles.emplace_back(std::move(OutputFile));
227   return TempFiles.back();
228 }
229 
230 /// Execute the command \p ExecutablePath with the arguments \p Args.
231 Error executeCommands(StringRef ExecutablePath, ArrayRef<StringRef> Args) {
232   if (Verbose || DryRun)
233     printCommands(Args);
234 
235   if (!DryRun)
236     if (sys::ExecuteAndWait(ExecutablePath, Args))
237       return createStringError(inconvertibleErrorCode(),
238                                "'" + sys::path::filename(ExecutablePath) + "'" +
239                                    " failed");
240   return Error::success();
241 }
242 
243 Expected<std::string> findProgram(StringRef Name, ArrayRef<StringRef> Paths) {
244 
245   ErrorOr<std::string> Path = sys::findProgramByName(Name, Paths);
246   if (!Path)
247     Path = sys::findProgramByName(Name);
248   if (!Path && DryRun)
249     return Name.str();
250   if (!Path)
251     return createStringError(Path.getError(),
252                              "Unable to find '" + Name + "' in path");
253   return *Path;
254 }
255 
256 /// Runs the wrapped linker job with the newly created input.
257 Error runLinker(ArrayRef<StringRef> Files, const ArgList &Args) {
258   llvm::TimeTraceScope TimeScope("Execute host linker");
259 
260   // Render the linker arguments and add the newly created image. We add it
261   // after the output file to ensure it is linked with the correct libraries.
262   StringRef LinkerPath = Args.getLastArgValue(OPT_linker_path_EQ);
263   ArgStringList NewLinkerArgs;
264   for (const opt::Arg *Arg : Args) {
265     // Do not forward arguments only intended for the linker wrapper.
266     if (Arg->getOption().hasFlag(WrapperOnlyOption))
267       continue;
268 
269     Arg->render(Args, NewLinkerArgs);
270     if (Arg->getOption().matches(OPT_o))
271       llvm::transform(Files, std::back_inserter(NewLinkerArgs),
272                       [&](StringRef Arg) { return Args.MakeArgString(Arg); });
273   }
274 
275   SmallVector<StringRef> LinkerArgs({LinkerPath});
276   for (StringRef Arg : NewLinkerArgs)
277     LinkerArgs.push_back(Arg);
278   if (Error Err = executeCommands(LinkerPath, LinkerArgs))
279     return Err;
280   return Error::success();
281 }
282 
283 void printVersion(raw_ostream &OS) {
284   OS << clang::getClangToolFullVersion("clang-linker-wrapper") << '\n';
285 }
286 
287 /// Attempts to extract all the embedded device images contained inside the
288 /// buffer \p Contents. The buffer is expected to contain a valid offloading
289 /// binary format.
290 Error extractOffloadFiles(MemoryBufferRef Contents,
291                           SmallVectorImpl<OffloadFile> &DeviceFiles) {
292   uint64_t Offset = 0;
293   // There could be multiple offloading binaries stored at this section.
294   while (Offset < Contents.getBuffer().size()) {
295     std::unique_ptr<MemoryBuffer> Buffer =
296         MemoryBuffer::getMemBuffer(Contents.getBuffer().drop_front(Offset), "",
297                                    /*RequiresNullTerminator*/ false);
298     auto BinaryOrErr = OffloadBinary::create(*Buffer);
299     if (!BinaryOrErr)
300       return BinaryOrErr.takeError();
301     OffloadBinary &Binary = **BinaryOrErr;
302 
303     // Create a new owned binary with a copy of the original memory.
304     std::unique_ptr<MemoryBuffer> BufferCopy = MemoryBuffer::getMemBufferCopy(
305         Binary.getData().take_front(Binary.getSize()),
306         Contents.getBufferIdentifier());
307     auto NewBinaryOrErr = OffloadBinary::create(*BufferCopy);
308     if (!NewBinaryOrErr)
309       return NewBinaryOrErr.takeError();
310     DeviceFiles.emplace_back(std::move(*NewBinaryOrErr), std::move(BufferCopy));
311 
312     Offset += Binary.getSize();
313   }
314 
315   return Error::success();
316 }
317 
318 // Extract offloading binaries from an Object file \p Obj.
319 Error extractFromBinary(const ObjectFile &Obj,
320                         SmallVectorImpl<OffloadFile> &DeviceFiles) {
321   for (ELFSectionRef Sec : Obj.sections()) {
322     if (Sec.getType() != ELF::SHT_LLVM_OFFLOADING)
323       continue;
324 
325     Expected<StringRef> Buffer = Sec.getContents();
326     if (!Buffer)
327       return Buffer.takeError();
328 
329     MemoryBufferRef Contents(*Buffer, Obj.getFileName());
330     if (Error Err = extractOffloadFiles(Contents, DeviceFiles))
331       return Err;
332   }
333 
334   return Error::success();
335 }
336 
337 Error extractFromBitcode(std::unique_ptr<MemoryBuffer> Buffer,
338                          SmallVectorImpl<OffloadFile> &DeviceFiles) {
339   LLVMContext Context;
340   SMDiagnostic Err;
341   std::unique_ptr<Module> M = getLazyIRModule(std::move(Buffer), Err, Context);
342   if (!M)
343     return createStringError(inconvertibleErrorCode(),
344                              "Failed to create module");
345 
346   // Extract offloading data from globals referenced by the
347   // `llvm.embedded.object` metadata with the `.llvm.offloading` section.
348   auto *MD = M->getNamedMetadata("llvm.embedded.objects");
349   if (!MD)
350     return Error::success();
351 
352   for (const MDNode *Op : MD->operands()) {
353     if (Op->getNumOperands() < 2)
354       continue;
355 
356     MDString *SectionID = dyn_cast<MDString>(Op->getOperand(1));
357     if (!SectionID || SectionID->getString() != ".llvm.offloading")
358       continue;
359 
360     GlobalVariable *GV =
361         mdconst::dyn_extract_or_null<GlobalVariable>(Op->getOperand(0));
362     if (!GV)
363       continue;
364 
365     auto *CDS = dyn_cast<ConstantDataSequential>(GV->getInitializer());
366     if (!CDS)
367       continue;
368 
369     MemoryBufferRef Contents(CDS->getAsString(), M->getName());
370     if (Error Err = extractOffloadFiles(Contents, DeviceFiles))
371       return Err;
372   }
373 
374   return Error::success();
375 }
376 
377 Error extractFromArchive(const Archive &Library,
378                          SmallVectorImpl<OffloadFile> &DeviceFiles) {
379   // Try to extract device code from each file stored in the static archive.
380   Error Err = Error::success();
381   for (auto Child : Library.children(Err)) {
382     auto ChildBufferOrErr = Child.getMemoryBufferRef();
383     if (!ChildBufferOrErr)
384       return ChildBufferOrErr.takeError();
385     std::unique_ptr<MemoryBuffer> ChildBuffer =
386         MemoryBuffer::getMemBuffer(*ChildBufferOrErr, false);
387 
388     // Check if the buffer has the required alignment.
389     if (!isAddrAligned(Align(OffloadBinary::getAlignment()),
390                        ChildBuffer->getBufferStart()))
391       ChildBuffer = MemoryBuffer::getMemBufferCopy(
392           ChildBufferOrErr->getBuffer(),
393           ChildBufferOrErr->getBufferIdentifier());
394 
395     if (Error Err = extractFromBuffer(std::move(ChildBuffer), DeviceFiles))
396       return Err;
397   }
398 
399   if (Err)
400     return Err;
401   return Error::success();
402 }
403 
404 /// Extracts embedded device offloading code from a memory \p Buffer to a list
405 /// of \p DeviceFiles.
406 Error extractFromBuffer(std::unique_ptr<MemoryBuffer> Buffer,
407                         SmallVectorImpl<OffloadFile> &DeviceFiles) {
408   file_magic Type = identify_magic(Buffer->getBuffer());
409   switch (Type) {
410   case file_magic::bitcode:
411     return extractFromBitcode(std::move(Buffer), DeviceFiles);
412   case file_magic::elf_relocatable: {
413     Expected<std::unique_ptr<ObjectFile>> ObjFile =
414         ObjectFile::createObjectFile(*Buffer, Type);
415     if (!ObjFile)
416       return ObjFile.takeError();
417     return extractFromBinary(*ObjFile->get(), DeviceFiles);
418   }
419   case file_magic::archive: {
420     Expected<std::unique_ptr<llvm::object::Archive>> LibFile =
421         object::Archive::create(*Buffer);
422     if (!LibFile)
423       return LibFile.takeError();
424     return extractFromArchive(*LibFile->get(), DeviceFiles);
425   }
426   default:
427     return Error::success();
428   }
429 }
430 
431 namespace nvptx {
432 Expected<StringRef> assemble(StringRef InputFile, const ArgList &Args,
433                              bool RDC = true) {
434   llvm::TimeTraceScope TimeScope("NVPTX Assembler");
435   // NVPTX uses the ptxas binary to create device object files.
436   Expected<std::string> PtxasPath = findProgram("ptxas", {CudaBinaryPath});
437   if (!PtxasPath)
438     return PtxasPath.takeError();
439 
440   const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
441   StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
442   // Create a new file to write the linked device image to. Assume that the
443   // input filename already has the device and architecture.
444   auto TempFileOrErr = createOutputFile(sys::path::stem(InputFile), "cubin");
445   if (!TempFileOrErr)
446     return TempFileOrErr.takeError();
447 
448   SmallVector<StringRef, 16> CmdArgs;
449   StringRef OptLevel = Args.getLastArgValue(OPT_opt_level, "O2");
450   CmdArgs.push_back(*PtxasPath);
451   CmdArgs.push_back(Triple.isArch64Bit() ? "-m64" : "-m32");
452   if (Verbose)
453     CmdArgs.push_back("-v");
454   for (StringRef Arg : Args.getAllArgValues(OPT_ptxas_arg))
455     CmdArgs.push_back(Args.MakeArgString(Arg));
456   CmdArgs.push_back("-o");
457   CmdArgs.push_back(*TempFileOrErr);
458   CmdArgs.push_back(Args.MakeArgString("-" + OptLevel));
459   CmdArgs.push_back("--gpu-name");
460   CmdArgs.push_back(Arch);
461   if (Args.hasArg(OPT_debug))
462     CmdArgs.push_back("-g");
463   if (RDC)
464     CmdArgs.push_back("-c");
465 
466   CmdArgs.push_back(InputFile);
467 
468   if (Error Err = executeCommands(*PtxasPath, CmdArgs))
469     return std::move(Err);
470 
471   return *TempFileOrErr;
472 }
473 
474 Expected<StringRef> link(ArrayRef<StringRef> InputFiles, const ArgList &Args) {
475   llvm::TimeTraceScope TimeScope("NVPTX linker");
476   // NVPTX uses the nvlink binary to link device object files.
477   Expected<std::string> NvlinkPath = findProgram("nvlink", {CudaBinaryPath});
478   if (!NvlinkPath)
479     return NvlinkPath.takeError();
480 
481   const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
482   StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
483 
484   // Create a new file to write the linked device image to.
485   auto TempFileOrErr =
486       createOutputFile(sys::path::filename(ExecutableName) + "-device-" +
487                            Triple.getArchName() + "-" + Arch,
488                        "out");
489   if (!TempFileOrErr)
490     return TempFileOrErr.takeError();
491 
492   SmallVector<StringRef, 16> CmdArgs;
493   CmdArgs.push_back(*NvlinkPath);
494   CmdArgs.push_back(Triple.isArch64Bit() ? "-m64" : "-m32");
495   if (Args.hasArg(OPT_debug))
496     CmdArgs.push_back("-g");
497   if (Verbose)
498     CmdArgs.push_back("-v");
499   CmdArgs.push_back("-o");
500   CmdArgs.push_back(*TempFileOrErr);
501   CmdArgs.push_back("-arch");
502   CmdArgs.push_back(Arch);
503 
504   // Add extracted input files.
505   for (StringRef Input : InputFiles)
506     CmdArgs.push_back(Input);
507 
508   for (StringRef Arg : Args.getAllArgValues(OPT_linker_arg_EQ))
509     CmdArgs.push_back(Args.MakeArgString(Arg));
510   if (Error Err = executeCommands(*NvlinkPath, CmdArgs))
511     return std::move(Err);
512 
513   return *TempFileOrErr;
514 }
515 
516 Expected<StringRef>
517 fatbinary(ArrayRef<std::pair<StringRef, StringRef>> InputFiles,
518           const ArgList &Args) {
519   llvm::TimeTraceScope TimeScope("NVPTX fatbinary");
520   // NVPTX uses the fatbinary program to bundle the linked images.
521   Expected<std::string> FatBinaryPath =
522       findProgram("fatbinary", {CudaBinaryPath});
523   if (!FatBinaryPath)
524     return FatBinaryPath.takeError();
525 
526   llvm::Triple Triple(
527       Args.getLastArgValue(OPT_host_triple_EQ, sys::getDefaultTargetTriple()));
528 
529   // Create a new file to write the linked device image to.
530   auto TempFileOrErr = createOutputFile(
531       sys::path::filename(ExecutableName) + "-device", "fatbin");
532   if (!TempFileOrErr)
533     return TempFileOrErr.takeError();
534 
535   SmallVector<StringRef, 16> CmdArgs;
536   CmdArgs.push_back(*FatBinaryPath);
537   CmdArgs.push_back(Triple.isArch64Bit() ? "-64" : "-32");
538   CmdArgs.push_back("--create");
539   CmdArgs.push_back(*TempFileOrErr);
540   for (const auto &FileAndArch : InputFiles)
541     CmdArgs.push_back(
542         Args.MakeArgString("--image=profile=" + std::get<1>(FileAndArch) +
543                            ",file=" + std::get<0>(FileAndArch)));
544 
545   if (Error Err = executeCommands(*FatBinaryPath, CmdArgs))
546     return std::move(Err);
547 
548   return *TempFileOrErr;
549 }
550 } // namespace nvptx
551 
552 namespace amdgcn {
553 Expected<StringRef> link(ArrayRef<StringRef> InputFiles, const ArgList &Args) {
554   llvm::TimeTraceScope TimeScope("AMDGPU linker");
555   // AMDGPU uses lld to link device object files.
556   Expected<std::string> LLDPath =
557       findProgram("lld", {getMainExecutable("lld")});
558   if (!LLDPath)
559     return LLDPath.takeError();
560 
561   const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
562   StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
563 
564   // Create a new file to write the linked device image to.
565   auto TempFileOrErr =
566       createOutputFile(sys::path::filename(ExecutableName) + "-" +
567                            Triple.getArchName() + "-" + Arch,
568                        "out");
569   if (!TempFileOrErr)
570     return TempFileOrErr.takeError();
571   std::string ArchArg = ("-plugin-opt=mcpu=" + Arch).str();
572 
573   SmallVector<StringRef, 16> CmdArgs;
574   CmdArgs.push_back(*LLDPath);
575   CmdArgs.push_back("-flavor");
576   CmdArgs.push_back("gnu");
577   CmdArgs.push_back("--no-undefined");
578   CmdArgs.push_back("-shared");
579   CmdArgs.push_back("-plugin-opt=-amdgpu-internalize-symbols");
580   CmdArgs.push_back(ArchArg);
581   CmdArgs.push_back("-o");
582   CmdArgs.push_back(*TempFileOrErr);
583 
584   // Add extracted input files.
585   for (StringRef Input : InputFiles)
586     CmdArgs.push_back(Input);
587 
588   for (StringRef Arg : Args.getAllArgValues(OPT_linker_arg_EQ))
589     CmdArgs.push_back(Args.MakeArgString(Arg));
590   if (Error Err = executeCommands(*LLDPath, CmdArgs))
591     return std::move(Err);
592 
593   return *TempFileOrErr;
594 }
595 
596 Expected<StringRef>
597 fatbinary(ArrayRef<std::pair<StringRef, StringRef>> InputFiles,
598           const ArgList &Args) {
599   llvm::TimeTraceScope TimeScope("AMDGPU Fatbinary");
600 
601   // AMDGPU uses the clang-offload-bundler to bundle the linked images.
602   Expected<std::string> OffloadBundlerPath = findProgram(
603       "clang-offload-bundler", {getMainExecutable("clang-offload-bundler")});
604   if (!OffloadBundlerPath)
605     return OffloadBundlerPath.takeError();
606 
607   llvm::Triple Triple(
608       Args.getLastArgValue(OPT_host_triple_EQ, sys::getDefaultTargetTriple()));
609 
610   // Create a new file to write the linked device image to.
611   auto TempFileOrErr = createOutputFile(sys::path::filename(ExecutableName) +
612                                             "-device-" + Triple.getArchName(),
613                                         "hipfb");
614   if (!TempFileOrErr)
615     return TempFileOrErr.takeError();
616 
617   BumpPtrAllocator Alloc;
618   StringSaver Saver(Alloc);
619 
620   SmallVector<StringRef, 16> CmdArgs;
621   CmdArgs.push_back(*OffloadBundlerPath);
622   CmdArgs.push_back("-type=o");
623   CmdArgs.push_back("-bundle-align=4096");
624 
625   SmallVector<StringRef> Targets = {"-targets=host-x86_64-unknown-linux"};
626   for (const auto &FileAndArch : InputFiles)
627     Targets.push_back(
628         Saver.save("hipv4-amdgcn-amd-amdhsa--" + std::get<1>(FileAndArch)));
629   CmdArgs.push_back(Saver.save(llvm::join(Targets, ",")));
630 
631   CmdArgs.push_back("-input=/dev/null");
632   for (const auto &FileAndArch : InputFiles)
633     CmdArgs.push_back(Saver.save("-input=" + std::get<0>(FileAndArch)));
634 
635   CmdArgs.push_back(Saver.save("-output=" + *TempFileOrErr));
636 
637   if (Error Err = executeCommands(*OffloadBundlerPath, CmdArgs))
638     return std::move(Err);
639 
640   return *TempFileOrErr;
641 }
642 } // namespace amdgcn
643 
644 namespace generic {
645 
646 const char *getLDMOption(const llvm::Triple &T) {
647   switch (T.getArch()) {
648   case llvm::Triple::x86:
649     if (T.isOSIAMCU())
650       return "elf_iamcu";
651     return "elf_i386";
652   case llvm::Triple::aarch64:
653     return "aarch64linux";
654   case llvm::Triple::aarch64_be:
655     return "aarch64linuxb";
656   case llvm::Triple::ppc64:
657     return "elf64ppc";
658   case llvm::Triple::ppc64le:
659     return "elf64lppc";
660   case llvm::Triple::x86_64:
661     if (T.isX32())
662       return "elf32_x86_64";
663     return "elf_x86_64";
664   case llvm::Triple::ve:
665     return "elf64ve";
666   default:
667     return nullptr;
668   }
669 }
670 
671 Expected<StringRef> link(ArrayRef<StringRef> InputFiles, const ArgList &Args) {
672   llvm::TimeTraceScope TimeScope("Generic linker");
673   const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
674   StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
675 
676   // Create a new file to write the linked device image to.
677   auto TempFileOrErr =
678       createOutputFile(sys::path::filename(ExecutableName) + "-" +
679                            Triple.getArchName() + "-" + Arch,
680                        "out");
681   if (!TempFileOrErr)
682     return TempFileOrErr.takeError();
683 
684   // Use the host linker to perform generic offloading. Use the same libraries
685   // and paths as the host application does.
686   SmallVector<StringRef, 16> CmdArgs;
687   CmdArgs.push_back(Args.getLastArgValue(OPT_linker_path_EQ));
688   CmdArgs.push_back("-m");
689   CmdArgs.push_back(getLDMOption(Triple));
690   CmdArgs.push_back("-shared");
691 
692   ArgStringList LinkerArgs;
693   for (const opt::Arg *Arg : Args) {
694     auto Op = Arg->getOption();
695     if (Op.matches(OPT_library) || Op.matches(OPT_library_path) ||
696         Op.matches(OPT_as_needed) || Op.matches(OPT_no_as_needed) ||
697         Op.matches(OPT_rpath) || Op.matches(OPT_dynamic_linker))
698       Arg->render(Args, LinkerArgs);
699   }
700   for (StringRef Arg : LinkerArgs)
701     CmdArgs.push_back(Arg);
702 
703   CmdArgs.push_back("-Bsymbolic");
704   CmdArgs.push_back("-o");
705   CmdArgs.push_back(*TempFileOrErr);
706 
707   // Add extracted input files.
708   for (StringRef Input : InputFiles)
709     CmdArgs.push_back(Input);
710 
711   for (StringRef Arg : Args.getAllArgValues(OPT_linker_arg_EQ))
712     CmdArgs.push_back(Args.MakeArgString(Arg));
713   if (Error Err =
714           executeCommands(Args.getLastArgValue(OPT_linker_path_EQ), CmdArgs))
715     return std::move(Err);
716 
717   return *TempFileOrErr;
718 }
719 } // namespace generic
720 
721 Expected<StringRef> linkDevice(ArrayRef<StringRef> InputFiles,
722                                const ArgList &Args) {
723   const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
724   switch (Triple.getArch()) {
725   case Triple::nvptx:
726   case Triple::nvptx64:
727     return nvptx::link(InputFiles, Args);
728   case Triple::amdgcn:
729     return amdgcn::link(InputFiles, Args);
730   case Triple::x86:
731   case Triple::x86_64:
732   case Triple::aarch64:
733   case Triple::aarch64_be:
734   case Triple::ppc64:
735   case Triple::ppc64le:
736     return generic::link(InputFiles, Args);
737   default:
738     return createStringError(inconvertibleErrorCode(),
739                              Triple.getArchName() +
740                                  " linking is not supported");
741   }
742 }
743 
744 void diagnosticHandler(const DiagnosticInfo &DI) {
745   std::string ErrStorage;
746   raw_string_ostream OS(ErrStorage);
747   DiagnosticPrinterRawOStream DP(OS);
748   DI.print(DP);
749 
750   switch (DI.getSeverity()) {
751   case DS_Error:
752     WithColor::error(errs(), LinkerExecutable) << ErrStorage << "\n";
753     LTOError = true;
754     break;
755   case DS_Warning:
756     WithColor::warning(errs(), LinkerExecutable) << ErrStorage << "\n";
757     break;
758   case DS_Note:
759     WithColor::note(errs(), LinkerExecutable) << ErrStorage << "\n";
760     break;
761   case DS_Remark:
762     WithColor::remark(errs()) << ErrStorage << "\n";
763     break;
764   }
765 }
766 
767 // Get the list of target features from the input file and unify them such that
768 // if there are multiple +xxx or -xxx features we only keep the last one.
769 std::vector<std::string> getTargetFeatures(ArrayRef<OffloadFile> InputFiles) {
770   SmallVector<StringRef> Features;
771   for (const OffloadFile &File : InputFiles) {
772     for (auto Arg : llvm::split(File.getBinary()->getString("feature"), ","))
773       Features.emplace_back(Arg);
774   }
775 
776   // Only add a feature if it hasn't been seen before starting from the end.
777   std::vector<std::string> UnifiedFeatures;
778   DenseSet<StringRef> UsedFeatures;
779   for (StringRef Feature : llvm::reverse(Features)) {
780     if (UsedFeatures.insert(Feature.drop_front()).second)
781       UnifiedFeatures.push_back(Feature.str());
782   }
783 
784   return UnifiedFeatures;
785 }
786 
787 CodeGenOpt::Level getCGOptLevel(unsigned OptLevel) {
788   switch (OptLevel) {
789   case 0:
790     return CodeGenOpt::None;
791   case 1:
792     return CodeGenOpt::Less;
793   case 2:
794     return CodeGenOpt::Default;
795   case 3:
796     return CodeGenOpt::Aggressive;
797   }
798   llvm_unreachable("Invalid optimization level");
799 }
800 
801 template <typename ModuleHook = function_ref<bool(size_t, const Module &)>>
802 std::unique_ptr<lto::LTO> createLTO(
803     const ArgList &Args, const std::vector<std::string> &Features,
804     ModuleHook Hook = [](size_t, const Module &) { return true; }) {
805   const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
806   StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
807   lto::Config Conf;
808   lto::ThinBackend Backend;
809   // TODO: Handle index-only thin-LTO
810   Backend =
811       lto::createInProcessThinBackend(llvm::heavyweight_hardware_concurrency());
812 
813   Conf.CPU = Arch.str();
814   Conf.Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple);
815 
816   StringRef OptLevel = Args.getLastArgValue(OPT_opt_level, "O2");
817   Conf.MAttrs = Features;
818   Conf.CGOptLevel = getCGOptLevel(OptLevel[1] - '0');
819   Conf.OptLevel = OptLevel[1] - '0';
820   if (Conf.OptLevel > 0)
821     Conf.UseDefaultPipeline = true;
822   Conf.DefaultTriple = Triple.getTriple();
823 
824   LTOError = false;
825   Conf.DiagHandler = diagnosticHandler;
826 
827   Conf.PTO.LoopVectorization = Conf.OptLevel > 1;
828   Conf.PTO.SLPVectorization = Conf.OptLevel > 1;
829 
830   if (SaveTemps) {
831     std::string TempName = (sys::path::filename(ExecutableName) + "-device-" +
832                             Triple.getTriple() + "-" + Arch)
833                                .str();
834     Conf.PostInternalizeModuleHook = [=](size_t Task, const Module &M) {
835       std::string File = !Task ? TempName + ".bc"
836                                : TempName + "." + std::to_string(Task) + ".bc";
837       error_code EC;
838       raw_fd_ostream LinkedBitcode(File, EC, sys::fs::OF_None);
839       if (EC)
840         reportError(errorCodeToError(EC));
841       WriteBitcodeToFile(M, LinkedBitcode);
842       return true;
843     };
844   }
845   Conf.PostOptModuleHook = Hook;
846   Conf.CGFileType = Triple.isNVPTX() ? CGFT_AssemblyFile : CGFT_ObjectFile;
847 
848   // TODO: Handle remark files
849   Conf.HasWholeProgramVisibility = Args.hasArg(OPT_whole_program);
850 
851   return std::make_unique<lto::LTO>(std::move(Conf), Backend);
852 }
853 
854 // Returns true if \p S is valid as a C language identifier and will be given
855 // `__start_` and `__stop_` symbols.
856 bool isValidCIdentifier(StringRef S) {
857   return !S.empty() && (isAlpha(S[0]) || S[0] == '_') &&
858          std::all_of(S.begin() + 1, S.end(),
859                      [](char C) { return C == '_' || isAlnum(C); });
860 }
861 
862 Error linkBitcodeFiles(SmallVectorImpl<OffloadFile> &InputFiles,
863                        SmallVectorImpl<StringRef> &OutputFiles,
864                        const ArgList &Args) {
865   llvm::TimeTraceScope TimeScope("Link bitcode files");
866   const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
867 
868   SmallVector<OffloadFile, 4> BitcodeInputFiles;
869   DenseSet<StringRef> UsedInRegularObj;
870   DenseSet<StringRef> UsedInSharedLib;
871   BumpPtrAllocator Alloc;
872   StringSaver Saver(Alloc);
873 
874   // Search for bitcode files in the input and create an LTO input file. If it
875   // is not a bitcode file, scan its symbol table for symbols we need to save.
876   for (OffloadFile &File : InputFiles) {
877     MemoryBufferRef Buffer = MemoryBufferRef(File.getBinary()->getImage(), "");
878 
879     file_magic Type = identify_magic(Buffer.getBuffer());
880     switch (Type) {
881     case file_magic::bitcode: {
882       BitcodeInputFiles.emplace_back(std::move(File));
883       continue;
884     }
885     case file_magic::elf_relocatable:
886     case file_magic::elf_shared_object: {
887       Expected<std::unique_ptr<ObjectFile>> ObjFile =
888           ObjectFile::createObjectFile(Buffer);
889       if (!ObjFile)
890         continue;
891 
892       for (SymbolRef Sym : (*ObjFile)->symbols()) {
893         Expected<StringRef> Name = Sym.getName();
894         if (!Name)
895           return Name.takeError();
896 
897         // Record if we've seen these symbols in any object or shared libraries.
898         if ((*ObjFile)->isRelocatableObject())
899           UsedInRegularObj.insert(Saver.save(*Name));
900         else
901           UsedInSharedLib.insert(Saver.save(*Name));
902       }
903       continue;
904     }
905     default:
906       continue;
907     }
908   }
909 
910   if (BitcodeInputFiles.empty())
911     return Error::success();
912 
913   // Remove all the bitcode files that we moved from the original input.
914   llvm::erase_if(InputFiles, [](OffloadFile &F) { return !F.getBinary(); });
915 
916   // LTO Module hook to output bitcode without running the backend.
917   SmallVector<StringRef, 4> BitcodeOutput;
918   auto OutputBitcode = [&](size_t, const Module &M) {
919     auto TempFileOrErr = createOutputFile(sys::path::filename(ExecutableName) +
920                                               "-jit-" + Triple.getTriple(),
921                                           "bc");
922     if (!TempFileOrErr)
923       reportError(TempFileOrErr.takeError());
924 
925     std::error_code EC;
926     raw_fd_ostream LinkedBitcode(*TempFileOrErr, EC, sys::fs::OF_None);
927     if (EC)
928       reportError(errorCodeToError(EC));
929     WriteBitcodeToFile(M, LinkedBitcode);
930     BitcodeOutput.push_back(*TempFileOrErr);
931     return false;
932   };
933 
934   // We assume visibility of the whole program if every input file was bitcode.
935   auto Features = getTargetFeatures(BitcodeInputFiles);
936   auto LTOBackend = Args.hasArg(OPT_embed_bitcode)
937                         ? createLTO(Args, Features, OutputBitcode)
938                         : createLTO(Args, Features);
939 
940   // We need to resolve the symbols so the LTO backend knows which symbols need
941   // to be kept or can be internalized. This is a simplified symbol resolution
942   // scheme to approximate the full resolution a linker would do.
943   uint64_t Idx = 0;
944   DenseSet<StringRef> PrevailingSymbols;
945   for (auto &BitcodeInput : BitcodeInputFiles) {
946     // Get a semi-unique buffer identifier for Thin-LTO.
947     StringRef Identifier = Saver.save(
948         std::to_string(Idx++) + "." +
949         BitcodeInput.getBinary()->getMemoryBufferRef().getBufferIdentifier());
950     MemoryBufferRef Buffer =
951         MemoryBufferRef(BitcodeInput.getBinary()->getImage(), Identifier);
952     Expected<std::unique_ptr<lto::InputFile>> BitcodeFileOrErr =
953         llvm::lto::InputFile::create(Buffer);
954     if (!BitcodeFileOrErr)
955       return BitcodeFileOrErr.takeError();
956 
957     // Save the input file and the buffer associated with its memory.
958     const auto Symbols = (*BitcodeFileOrErr)->symbols();
959     SmallVector<lto::SymbolResolution, 16> Resolutions(Symbols.size());
960     size_t Idx = 0;
961     for (auto &Sym : Symbols) {
962       lto::SymbolResolution &Res = Resolutions[Idx++];
963 
964       // We will use this as the prevailing symbol definition in LTO unless
965       // it is undefined or another definition has already been used.
966       Res.Prevailing =
967           !Sym.isUndefined() &&
968           PrevailingSymbols.insert(Saver.save(Sym.getName())).second;
969 
970       // We need LTO to preseve the following global symbols:
971       // 1) Symbols used in regular objects.
972       // 2) Sections that will be given a __start/__stop symbol.
973       // 3) Prevailing symbols that are needed visible to external libraries.
974       Res.VisibleToRegularObj =
975           UsedInRegularObj.contains(Sym.getName()) ||
976           isValidCIdentifier(Sym.getSectionName()) ||
977           (Res.Prevailing &&
978            (Sym.getVisibility() != GlobalValue::HiddenVisibility &&
979             !Sym.canBeOmittedFromSymbolTable()));
980 
981       // Identify symbols that must be exported dynamically and can be
982       // referenced by other files.
983       Res.ExportDynamic =
984           Sym.getVisibility() != GlobalValue::HiddenVisibility &&
985           (UsedInSharedLib.contains(Sym.getName()) ||
986            !Sym.canBeOmittedFromSymbolTable());
987 
988       // The final definition will reside in this linkage unit if the symbol is
989       // defined and local to the module. This only checks for bitcode files,
990       // full assertion will require complete symbol resolution.
991       Res.FinalDefinitionInLinkageUnit =
992           Sym.getVisibility() != GlobalValue::DefaultVisibility &&
993           (!Sym.isUndefined() && !Sym.isCommon());
994 
995       // We do not support linker redefined symbols (e.g. --wrap) for device
996       // image linking, so the symbols will not be changed after LTO.
997       Res.LinkerRedefined = false;
998     }
999 
1000     // Add the bitcode file with its resolved symbols to the LTO job.
1001     if (Error Err = LTOBackend->add(std::move(*BitcodeFileOrErr), Resolutions))
1002       return Err;
1003   }
1004 
1005   // Run the LTO job to compile the bitcode.
1006   size_t MaxTasks = LTOBackend->getMaxTasks();
1007   SmallVector<StringRef> Files(MaxTasks);
1008   auto AddStream = [&](size_t Task) -> std::unique_ptr<CachedFileStream> {
1009     int FD = -1;
1010     auto &TempFile = Files[Task];
1011     StringRef Extension = (Triple.isNVPTX()) ? "s" : "o";
1012     std::string TaskStr = Task ? "." + std::to_string(Task) : "";
1013     auto TempFileOrErr =
1014         createOutputFile(sys::path::filename(ExecutableName) + "-device-" +
1015                              Triple.getTriple() + TaskStr,
1016                          Extension);
1017     if (!TempFileOrErr)
1018       reportError(TempFileOrErr.takeError());
1019     TempFile = *TempFileOrErr;
1020     if (std::error_code EC = sys::fs::openFileForWrite(TempFile, FD))
1021       reportError(errorCodeToError(EC));
1022     return std::make_unique<CachedFileStream>(
1023         std::make_unique<llvm::raw_fd_ostream>(FD, true));
1024   };
1025 
1026   if (Error Err = LTOBackend->run(AddStream))
1027     return Err;
1028 
1029   if (LTOError)
1030     return createStringError(inconvertibleErrorCode(),
1031                              "Errors encountered inside the LTO pipeline.");
1032 
1033   // If we are embedding bitcode we only need the intermediate output.
1034   bool SingleOutput = Files.size() == 1;
1035   if (Args.hasArg(OPT_embed_bitcode)) {
1036     if (BitcodeOutput.size() != 1 || !SingleOutput)
1037       return createStringError(inconvertibleErrorCode(),
1038                                "Cannot embed bitcode with multiple files.");
1039     OutputFiles.push_back(static_cast<std::string>(BitcodeOutput.front()));
1040     return Error::success();
1041   }
1042 
1043   // Is we are compiling for NVPTX we need to run the assembler first.
1044   if (Triple.isNVPTX()) {
1045     for (StringRef &File : Files) {
1046       auto FileOrErr = nvptx::assemble(File, Args, !SingleOutput);
1047       if (!FileOrErr)
1048         return FileOrErr.takeError();
1049       File = *FileOrErr;
1050     }
1051   }
1052 
1053   // Append the new inputs to the device linker input.
1054   for (StringRef File : Files)
1055     OutputFiles.push_back(File);
1056 
1057   return Error::success();
1058 }
1059 
1060 Expected<StringRef> writeOffloadFile(const OffloadFile &File) {
1061   const OffloadBinary &Binary = *File.getBinary();
1062 
1063   StringRef Prefix =
1064       sys::path::stem(Binary.getMemoryBufferRef().getBufferIdentifier());
1065   StringRef Suffix = getImageKindName(Binary.getImageKind());
1066 
1067   auto TempFileOrErr = createOutputFile(
1068       Prefix + "-" + Binary.getTriple() + "-" + Binary.getArch(), Suffix);
1069   if (!TempFileOrErr)
1070     return TempFileOrErr.takeError();
1071 
1072   Expected<std::unique_ptr<FileOutputBuffer>> OutputOrErr =
1073       FileOutputBuffer::create(*TempFileOrErr, Binary.getImage().size());
1074   if (!OutputOrErr)
1075     return OutputOrErr.takeError();
1076   std::unique_ptr<FileOutputBuffer> Output = std::move(*OutputOrErr);
1077   std::copy(Binary.getImage().bytes_begin(), Binary.getImage().bytes_end(),
1078             Output->getBufferStart());
1079   if (Error E = Output->commit())
1080     return std::move(E);
1081 
1082   return *TempFileOrErr;
1083 }
1084 
1085 // Compile the module to an object file using the appropriate target machine for
1086 // the host triple.
1087 Expected<StringRef> compileModule(Module &M) {
1088   llvm::TimeTraceScope TimeScope("Compile module");
1089   std::string Msg;
1090   const Target *T = TargetRegistry::lookupTarget(M.getTargetTriple(), Msg);
1091   if (!T)
1092     return createStringError(inconvertibleErrorCode(), Msg);
1093 
1094   auto Options =
1095       codegen::InitTargetOptionsFromCodeGenFlags(Triple(M.getTargetTriple()));
1096   StringRef CPU = "";
1097   StringRef Features = "";
1098   std::unique_ptr<TargetMachine> TM(
1099       T->createTargetMachine(M.getTargetTriple(), CPU, Features, Options,
1100                              Reloc::PIC_, M.getCodeModel()));
1101 
1102   if (M.getDataLayout().isDefault())
1103     M.setDataLayout(TM->createDataLayout());
1104 
1105   int FD = -1;
1106   auto TempFileOrErr =
1107       createOutputFile(sys::path::filename(ExecutableName) + "-wrapper", "o");
1108   if (!TempFileOrErr)
1109     return TempFileOrErr.takeError();
1110   if (std::error_code EC = sys::fs::openFileForWrite(*TempFileOrErr, FD))
1111     return errorCodeToError(EC);
1112 
1113   auto OS = std::make_unique<llvm::raw_fd_ostream>(FD, true);
1114 
1115   legacy::PassManager CodeGenPasses;
1116   TargetLibraryInfoImpl TLII(Triple(M.getTargetTriple()));
1117   CodeGenPasses.add(new TargetLibraryInfoWrapperPass(TLII));
1118   if (TM->addPassesToEmitFile(CodeGenPasses, *OS, nullptr, CGFT_ObjectFile))
1119     return createStringError(inconvertibleErrorCode(),
1120                              "Failed to execute host backend");
1121   CodeGenPasses.run(M);
1122 
1123   return *TempFileOrErr;
1124 }
1125 
1126 /// Creates the object file containing the device image and runtime
1127 /// registration code from the device images stored in \p Images.
1128 Expected<StringRef>
1129 wrapDeviceImages(ArrayRef<std::unique_ptr<MemoryBuffer>> Buffers,
1130                  const ArgList &Args, OffloadKind Kind) {
1131   llvm::TimeTraceScope TimeScope("Wrap bundled images");
1132 
1133   SmallVector<ArrayRef<char>, 4> BuffersToWrap;
1134   for (const auto &Buffer : Buffers)
1135     BuffersToWrap.emplace_back(
1136         ArrayRef<char>(Buffer->getBufferStart(), Buffer->getBufferSize()));
1137 
1138   LLVMContext Context;
1139   Module M("offload.wrapper.module", Context);
1140   M.setTargetTriple(
1141       Args.getLastArgValue(OPT_host_triple_EQ, sys::getDefaultTargetTriple()));
1142 
1143   switch (Kind) {
1144   case OFK_OpenMP:
1145     if (Error Err = wrapOpenMPBinaries(M, BuffersToWrap))
1146       return std::move(Err);
1147     break;
1148   case OFK_Cuda:
1149     if (Error Err = wrapCudaBinary(M, BuffersToWrap.front()))
1150       return std::move(Err);
1151     break;
1152   case OFK_HIP:
1153     if (Error Err = wrapHIPBinary(M, BuffersToWrap.front()))
1154       return std::move(Err);
1155     break;
1156   default:
1157     return createStringError(inconvertibleErrorCode(),
1158                              getOffloadKindName(Kind) +
1159                                  " wrapping is not supported");
1160   }
1161 
1162   if (Args.hasArg(OPT_print_wrapped_module))
1163     errs() << M;
1164 
1165   auto FileOrErr = compileModule(M);
1166   if (!FileOrErr)
1167     return FileOrErr.takeError();
1168   return *FileOrErr;
1169 }
1170 
1171 Expected<SmallVector<std::unique_ptr<MemoryBuffer>>>
1172 bundleOpenMP(ArrayRef<OffloadingImage> Images) {
1173   SmallVector<std::unique_ptr<MemoryBuffer>> Buffers;
1174   for (const OffloadingImage &Image : Images)
1175     Buffers.emplace_back(
1176         MemoryBuffer::getMemBufferCopy(Image.Image->getBuffer()));
1177 
1178   return std::move(Buffers);
1179 }
1180 
1181 Expected<SmallVector<std::unique_ptr<MemoryBuffer>>>
1182 bundleCuda(ArrayRef<OffloadingImage> Images, const ArgList &Args) {
1183   SmallVector<std::pair<StringRef, StringRef>, 4> InputFiles;
1184   for (const OffloadingImage &Image : Images)
1185     InputFiles.emplace_back(std::make_pair(Image.Image->getBufferIdentifier(),
1186                                            Image.StringData.lookup("arch")));
1187 
1188   Triple TheTriple = Triple(Images.front().StringData.lookup("triple"));
1189   auto FileOrErr = nvptx::fatbinary(InputFiles, Args);
1190   if (!FileOrErr)
1191     return FileOrErr.takeError();
1192 
1193   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ImageOrError =
1194       llvm::MemoryBuffer::getFileOrSTDIN(*FileOrErr);
1195 
1196   SmallVector<std::unique_ptr<MemoryBuffer>> Buffers;
1197   if (std::error_code EC = ImageOrError.getError())
1198     return createFileError(*FileOrErr, EC);
1199   Buffers.emplace_back(std::move(*ImageOrError));
1200 
1201   return std::move(Buffers);
1202 }
1203 
1204 Expected<SmallVector<std::unique_ptr<MemoryBuffer>>>
1205 bundleHIP(ArrayRef<OffloadingImage> Images, const ArgList &Args) {
1206   SmallVector<std::pair<StringRef, StringRef>, 4> InputFiles;
1207   for (const OffloadingImage &Image : Images)
1208     InputFiles.emplace_back(std::make_pair(Image.Image->getBufferIdentifier(),
1209                                            Image.StringData.lookup("arch")));
1210 
1211   Triple TheTriple = Triple(Images.front().StringData.lookup("triple"));
1212   auto FileOrErr = amdgcn::fatbinary(InputFiles, Args);
1213   if (!FileOrErr)
1214     return FileOrErr.takeError();
1215 
1216   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ImageOrError =
1217       llvm::MemoryBuffer::getFileOrSTDIN(*FileOrErr);
1218 
1219   SmallVector<std::unique_ptr<MemoryBuffer>> Buffers;
1220   if (std::error_code EC = ImageOrError.getError())
1221     return createFileError(*FileOrErr, EC);
1222   Buffers.emplace_back(std::move(*ImageOrError));
1223 
1224   return std::move(Buffers);
1225 }
1226 
1227 /// Transforms the input \p Images into the binary format the runtime expects
1228 /// for the given \p Kind.
1229 Expected<SmallVector<std::unique_ptr<MemoryBuffer>>>
1230 bundleLinkedOutput(ArrayRef<OffloadingImage> Images, const ArgList &Args,
1231                    OffloadKind Kind) {
1232   llvm::TimeTraceScope TimeScope("Bundle linked output");
1233   switch (Kind) {
1234   case OFK_OpenMP:
1235     return bundleOpenMP(Images);
1236   case OFK_Cuda:
1237     return bundleCuda(Images, Args);
1238   case OFK_HIP:
1239     return bundleHIP(Images, Args);
1240   default:
1241     return createStringError(inconvertibleErrorCode(),
1242                              getOffloadKindName(Kind) +
1243                                  " bundling is not supported");
1244   }
1245 }
1246 
1247 /// Returns a new ArgList containg arguments used for the device linking phase.
1248 DerivedArgList getLinkerArgs(ArrayRef<OffloadFile> Input,
1249                              const InputArgList &Args) {
1250   DerivedArgList DAL = DerivedArgList(DerivedArgList(Args));
1251   for (Arg *A : Args)
1252     DAL.append(A);
1253 
1254   // Set the subarchitecture and target triple for this compilation.
1255   const OptTable &Tbl = getOptTable();
1256   DAL.AddJoinedArg(nullptr, Tbl.getOption(OPT_arch_EQ),
1257                    Args.MakeArgString(Input.front().getBinary()->getArch()));
1258   DAL.AddJoinedArg(nullptr, Tbl.getOption(OPT_triple_EQ),
1259                    Args.MakeArgString(Input.front().getBinary()->getTriple()));
1260 
1261   // If every input file is bitcode we have whole program visibility as we do
1262   // only support static linking with bitcode.
1263   auto ContainsBitcode = [](const OffloadFile &F) {
1264     return identify_magic(F.getBinary()->getImage()) == file_magic::bitcode;
1265   };
1266   if (llvm::all_of(Input, ContainsBitcode))
1267     DAL.AddFlagArg(nullptr, Tbl.getOption(OPT_whole_program));
1268 
1269   // Forward '-Xoffload-linker' options to the appropriate backend.
1270   for (StringRef Arg : Args.getAllArgValues(OPT_device_linker_args_EQ)) {
1271     auto TripleAndValue = Arg.split('=');
1272     if (TripleAndValue.second.empty())
1273       DAL.AddJoinedArg(nullptr, Tbl.getOption(OPT_linker_arg_EQ),
1274                        Args.MakeArgString(TripleAndValue.first));
1275     else if (TripleAndValue.first == DAL.getLastArgValue(OPT_triple_EQ))
1276       DAL.AddJoinedArg(nullptr, Tbl.getOption(OPT_linker_arg_EQ),
1277                        Args.MakeArgString(TripleAndValue.second));
1278   }
1279 
1280   return DAL;
1281 }
1282 
1283 /// Transforms all the extracted offloading input files into an image that can
1284 /// be registered by the runtime.
1285 Expected<SmallVector<StringRef>>
1286 linkAndWrapDeviceFiles(SmallVectorImpl<OffloadFile> &LinkerInputFiles,
1287                        const InputArgList &Args) {
1288   llvm::TimeTraceScope TimeScope("Handle all device input");
1289 
1290   DenseMap<OffloadFile::TargetID, SmallVector<OffloadFile, 4>> InputsForTarget;
1291   for (auto &File : LinkerInputFiles)
1292     InputsForTarget[File].emplace_back(std::move(File));
1293   LinkerInputFiles.clear();
1294 
1295   DenseMap<OffloadKind, SmallVector<OffloadingImage, 2>> Images;
1296   for (auto &InputForTarget : InputsForTarget) {
1297     llvm::TimeTraceScope TimeScope("Link device input");
1298 
1299     SmallVector<OffloadFile, 4> &Input = InputForTarget.getSecond();
1300     auto LinkerArgs = getLinkerArgs(Input, Args);
1301 
1302     DenseSet<OffloadKind> ActiveOffloadKinds;
1303     for (const auto &File : Input)
1304       ActiveOffloadKinds.insert(File.getBinary()->getOffloadKind());
1305 
1306     // First link and remove all the input files containing bitcode.
1307     SmallVector<StringRef> InputFiles;
1308     if (Error Err = linkBitcodeFiles(Input, InputFiles, LinkerArgs))
1309       return std::move(Err);
1310 
1311     // Write any remaining device inputs to an output file for the linker job.
1312     for (const OffloadFile &File : Input) {
1313       auto FileNameOrErr = writeOffloadFile(File);
1314       if (!FileNameOrErr)
1315         return FileNameOrErr.takeError();
1316       InputFiles.emplace_back(*FileNameOrErr);
1317     }
1318 
1319     // Link the remaining device files, if necessary, using the device linker.
1320     llvm::Triple Triple(LinkerArgs.getLastArgValue(OPT_triple_EQ));
1321     bool RequiresLinking =
1322         !Args.hasArg(OPT_embed_bitcode) &&
1323         !(Input.empty() && InputFiles.size() == 1 && Triple.isNVPTX());
1324     auto OutputOrErr = RequiresLinking ? linkDevice(InputFiles, LinkerArgs)
1325                                        : InputFiles.front();
1326     if (!OutputOrErr)
1327       return OutputOrErr.takeError();
1328 
1329     // Store the offloading image for each linked output file.
1330     for (OffloadKind Kind : ActiveOffloadKinds) {
1331       llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileOrErr =
1332           llvm::MemoryBuffer::getFileOrSTDIN(*OutputOrErr);
1333       if (std::error_code EC = FileOrErr.getError())
1334         return createFileError(*OutputOrErr, EC);
1335 
1336       OffloadingImage TheImage{};
1337       TheImage.TheImageKind = IMG_Object;
1338       TheImage.TheOffloadKind = Kind;
1339       TheImage.StringData = {
1340           {"triple", LinkerArgs.getLastArgValue(OPT_triple_EQ)},
1341           {"arch", LinkerArgs.getLastArgValue(OPT_arch_EQ)}};
1342       TheImage.Image = std::move(*FileOrErr);
1343       Images[Kind].emplace_back(std::move(TheImage));
1344     }
1345   }
1346 
1347   // Create a binary image of each offloading image and embed it into a new
1348   // object file.
1349   SmallVector<StringRef> WrappedOutput;
1350   for (const auto &KindAndImages : Images) {
1351     OffloadKind Kind = KindAndImages.first;
1352     auto BundledImagesOrErr =
1353         bundleLinkedOutput(KindAndImages.second, Args, Kind);
1354     if (!BundledImagesOrErr)
1355       return BundledImagesOrErr.takeError();
1356     auto OutputOrErr = wrapDeviceImages(*BundledImagesOrErr, Args, Kind);
1357     if (!OutputOrErr)
1358       return OutputOrErr.takeError();
1359     WrappedOutput.push_back(*OutputOrErr);
1360   }
1361 
1362   return WrappedOutput;
1363 }
1364 
1365 Optional<std::string> findFile(StringRef Dir, StringRef Root,
1366                                const Twine &Name) {
1367   SmallString<128> Path;
1368   if (Dir.startswith("="))
1369     sys::path::append(Path, Root, Dir.substr(1), Name);
1370   else
1371     sys::path::append(Path, Dir, Name);
1372 
1373   if (sys::fs::exists(Path))
1374     return static_cast<std::string>(Path);
1375   return None;
1376 }
1377 
1378 Optional<std::string> findFromSearchPaths(StringRef Name, StringRef Root,
1379                                           ArrayRef<StringRef> SearchPaths) {
1380   for (StringRef Dir : SearchPaths)
1381     if (Optional<std::string> File = findFile(Dir, Root, Name))
1382       return File;
1383   return None;
1384 }
1385 
1386 Optional<std::string> searchLibraryBaseName(StringRef Name, StringRef Root,
1387                                             ArrayRef<StringRef> SearchPaths) {
1388   for (StringRef Dir : SearchPaths) {
1389     if (Optional<std::string> File = findFile(Dir, Root, "lib" + Name + ".so"))
1390       return None;
1391     if (Optional<std::string> File = findFile(Dir, Root, "lib" + Name + ".a"))
1392       return File;
1393   }
1394   return None;
1395 }
1396 
1397 /// Search for static libraries in the linker's library path given input like
1398 /// `-lfoo` or `-l:libfoo.a`.
1399 Optional<std::string> searchLibrary(StringRef Input, StringRef Root,
1400                                     ArrayRef<StringRef> SearchPaths) {
1401   if (Input.startswith(":"))
1402     return findFromSearchPaths(Input.drop_front(), Root, SearchPaths);
1403   return searchLibraryBaseName(Input, Root, SearchPaths);
1404 }
1405 
1406 /// Search the input files and libraries for embedded device offloading code and
1407 /// add it to the list of files to be linked. Files coming from static libraries
1408 /// are only added to the input if they are used by an existing input file.
1409 Expected<SmallVector<OffloadFile>> getDeviceInput(const ArgList &Args) {
1410   llvm::TimeTraceScope TimeScope("ExtractDeviceCode");
1411 
1412   StringRef Root = Args.getLastArgValue(OPT_sysroot_EQ);
1413   SmallVector<StringRef> LibraryPaths;
1414   for (const opt::Arg *Arg : Args.filtered(OPT_library_path))
1415     LibraryPaths.push_back(Arg->getValue());
1416 
1417   // Try to extract device code from the linker input files.
1418   SmallVector<OffloadFile> InputFiles;
1419   SmallVector<OffloadFile> LazyInputFiles;
1420   for (const opt::Arg *Arg : Args.filtered(OPT_INPUT)) {
1421     StringRef Filename = Arg->getValue();
1422     if (!sys::fs::exists(Filename) || sys::fs::is_directory(Filename))
1423       continue;
1424 
1425     ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
1426         MemoryBuffer::getFileOrSTDIN(Filename);
1427     if (std::error_code EC = BufferOrErr.getError())
1428       reportError(createFileError(Filename, EC));
1429 
1430     bool IsLazy =
1431         identify_magic((*BufferOrErr)->getBuffer()) == file_magic::archive;
1432     if (Error Err = extractFromBuffer(std::move(*BufferOrErr),
1433                                       IsLazy ? LazyInputFiles : InputFiles))
1434       reportError(std::move(Err));
1435   }
1436 
1437   // Try to extract input from input libraries.
1438   for (const opt::Arg *Arg : Args.filtered(OPT_library)) {
1439     if (auto Library = searchLibrary(Arg->getValue(), Root, LibraryPaths)) {
1440       ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
1441           MemoryBuffer::getFileOrSTDIN(*Library);
1442       if (std::error_code EC = BufferOrErr.getError())
1443         reportError(createFileError(*Library, EC));
1444 
1445       if (Error Err =
1446               extractFromBuffer(std::move(*BufferOrErr), LazyInputFiles))
1447         reportError(std::move(Err));
1448     }
1449   }
1450 
1451   for (StringRef Library : Args.getAllArgValues(OPT_bitcode_library_EQ)) {
1452     auto FileOrErr = getInputBitcodeLibrary(Library);
1453     if (!FileOrErr)
1454       reportError(FileOrErr.takeError());
1455     InputFiles.push_back(std::move(*FileOrErr));
1456   }
1457 
1458   DenseSet<OffloadFile::TargetID> IsTargetUsed;
1459   for (const auto &File : InputFiles)
1460     IsTargetUsed.insert(File);
1461 
1462   // We should only include input files that are used.
1463   // TODO: Only load a library if it defined undefined symbols in the input.
1464   for (auto &LazyFile : LazyInputFiles)
1465     if (IsTargetUsed.contains(LazyFile))
1466       InputFiles.emplace_back(std::move(LazyFile));
1467 
1468   return std::move(InputFiles);
1469 }
1470 
1471 } // namespace
1472 
1473 int main(int Argc, char **Argv) {
1474   InitLLVM X(Argc, Argv);
1475   InitializeAllTargetInfos();
1476   InitializeAllTargets();
1477   InitializeAllTargetMCs();
1478   InitializeAllAsmParsers();
1479   InitializeAllAsmPrinters();
1480 
1481   LinkerExecutable = Argv[0];
1482   sys::PrintStackTraceOnErrorSignal(Argv[0]);
1483 
1484   const OptTable &Tbl = getOptTable();
1485   BumpPtrAllocator Alloc;
1486   StringSaver Saver(Alloc);
1487   auto Args = Tbl.parseArgs(Argc, Argv, OPT_INVALID, Saver, [&](StringRef Err) {
1488     reportError(createStringError(inconvertibleErrorCode(), Err));
1489   });
1490 
1491   if (Args.hasArg(OPT_help) || Args.hasArg(OPT_help_hidden)) {
1492     Tbl.printHelp(
1493         outs(),
1494         "clang-linker-wrapper [options] -- <options to passed to the linker>",
1495         "\nA wrapper utility over the host linker. It scans the input files\n"
1496         "for sections that require additional processing prior to linking.\n"
1497         "The will then transparently pass all arguments and input to the\n"
1498         "specified host linker to create the final binary.\n",
1499         Args.hasArg(OPT_help_hidden), Args.hasArg(OPT_help_hidden));
1500     return EXIT_SUCCESS;
1501   }
1502   if (Args.hasArg(OPT_v)) {
1503     printVersion(outs());
1504     return EXIT_SUCCESS;
1505   }
1506 
1507   // This forwards '-mllvm' arguments to LLVM if present.
1508   SmallVector<const char *> NewArgv = {Argv[0]};
1509   for (const opt::Arg *Arg : Args.filtered(OPT_mllvm))
1510     NewArgv.push_back(Arg->getValue());
1511   for (const opt::Arg *Arg : Args.filtered(OPT_offload_opt_eq_minus))
1512     NewArgv.push_back(Args.MakeArgString(StringRef("-") + Arg->getValue()));
1513   cl::ParseCommandLineOptions(NewArgv.size(), &NewArgv[0]);
1514 
1515   Verbose = Args.hasArg(OPT_verbose);
1516   DryRun = Args.hasArg(OPT_dry_run);
1517   SaveTemps = Args.hasArg(OPT_save_temps);
1518   ExecutableName = Args.getLastArgValue(OPT_o, "a.out");
1519   CudaBinaryPath = Args.getLastArgValue(OPT_cuda_path_EQ).str();
1520   if (!CudaBinaryPath.empty())
1521     CudaBinaryPath = CudaBinaryPath + "/bin";
1522 
1523   if (Args.hasArg(OPT_wrapper_time_trace_eq)) {
1524     unsigned Granularity;
1525     Args.getLastArgValue(OPT_wrapper_time_trace_granularity, "500")
1526         .getAsInteger(10, Granularity);
1527     timeTraceProfilerInitialize(Granularity, Argv[0]);
1528   }
1529 
1530   {
1531     llvm::TimeTraceScope TimeScope("Execute linker wrapper");
1532 
1533     // Extract the device input files stored in the host fat binary.
1534     auto DeviceInputFiles = getDeviceInput(Args);
1535     if (!DeviceInputFiles)
1536       reportError(DeviceInputFiles.takeError());
1537 
1538     // Link and wrap the device images extracted from the linker input.
1539     auto FilesOrErr = linkAndWrapDeviceFiles(*DeviceInputFiles, Args);
1540     if (!FilesOrErr)
1541       reportError(FilesOrErr.takeError());
1542 
1543     // Run the host linking job with the rendered arguments.
1544     if (Error Err = runLinker(*FilesOrErr, Args))
1545       reportError(std::move(Err));
1546   }
1547 
1548   if (const opt::Arg *Arg = Args.getLastArg(OPT_wrapper_time_trace_eq)) {
1549     if (Error Err = timeTraceProfilerWrite(Arg->getValue(), ExecutableName))
1550       reportError(std::move(Err));
1551     timeTraceProfilerCleanup();
1552   }
1553 
1554   // Remove the temporary files created.
1555   if (!SaveTemps)
1556     for (const auto &TempFile : TempFiles)
1557       if (std::error_code EC = sys::fs::remove(TempFile))
1558         reportError(createFileError(TempFile, EC));
1559 
1560   return EXIT_SUCCESS;
1561 }
1562