xref: /openbsd-src/gnu/llvm/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp (revision c1a45aed656e7d5627c30c92421893a76f370ccb)
1 //===-- clang-offload-bundler/ClangOffloadBundler.cpp ---------------------===//
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 /// \file
10 /// This file implements a clang-offload-bundler that bundles different
11 /// files that relate with the same source code but different targets into a
12 /// single one. Also the implements the opposite functionality, i.e. unbundle
13 /// files previous created by this tool.
14 ///
15 //===----------------------------------------------------------------------===//
16 
17 #include "clang/Basic/Version.h"
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/SmallString.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringMap.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/ADT/StringSwitch.h"
24 #include "llvm/ADT/Triple.h"
25 #include "llvm/Object/Archive.h"
26 #include "llvm/Object/ArchiveWriter.h"
27 #include "llvm/Object/Binary.h"
28 #include "llvm/Object/ObjectFile.h"
29 #include "llvm/Support/Casting.h"
30 #include "llvm/Support/CommandLine.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/Errc.h"
33 #include "llvm/Support/Error.h"
34 #include "llvm/Support/ErrorOr.h"
35 #include "llvm/Support/FileSystem.h"
36 #include "llvm/Support/Host.h"
37 #include "llvm/Support/MemoryBuffer.h"
38 #include "llvm/Support/Path.h"
39 #include "llvm/Support/Program.h"
40 #include "llvm/Support/Signals.h"
41 #include "llvm/Support/StringSaver.h"
42 #include "llvm/Support/WithColor.h"
43 #include "llvm/Support/raw_ostream.h"
44 #include <algorithm>
45 #include <cassert>
46 #include <cstddef>
47 #include <cstdint>
48 #include <forward_list>
49 #include <memory>
50 #include <set>
51 #include <string>
52 #include <system_error>
53 #include <utility>
54 
55 using namespace llvm;
56 using namespace llvm::object;
57 
58 static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
59 
60 // Mark all our options with this category, everything else (except for -version
61 // and -help) will be hidden.
62 static cl::OptionCategory
63     ClangOffloadBundlerCategory("clang-offload-bundler options");
64 
65 static cl::list<std::string>
66     InputFileNames("inputs", cl::CommaSeparated, cl::OneOrMore,
67                    cl::desc("[<input file>,...]"),
68                    cl::cat(ClangOffloadBundlerCategory));
69 static cl::list<std::string>
70     OutputFileNames("outputs", cl::CommaSeparated,
71                     cl::desc("[<output file>,...]"),
72                     cl::cat(ClangOffloadBundlerCategory));
73 static cl::list<std::string>
74     TargetNames("targets", cl::CommaSeparated,
75                 cl::desc("[<offload kind>-<target triple>,...]"),
76                 cl::cat(ClangOffloadBundlerCategory));
77 static cl::opt<std::string>
78     FilesType("type", cl::Required,
79               cl::desc("Type of the files to be bundled/unbundled.\n"
80                        "Current supported types are:\n"
81                        "  i   - cpp-output\n"
82                        "  ii  - c++-cpp-output\n"
83                        "  cui - cuda/hip-output\n"
84                        "  d   - dependency\n"
85                        "  ll  - llvm\n"
86                        "  bc  - llvm-bc\n"
87                        "  s   - assembler\n"
88                        "  o   - object\n"
89                        "  a   - archive of objects\n"
90                        "  gch - precompiled-header\n"
91                        "  ast - clang AST file"),
92               cl::cat(ClangOffloadBundlerCategory));
93 static cl::opt<bool>
94     Unbundle("unbundle",
95              cl::desc("Unbundle bundled file into several output files.\n"),
96              cl::init(false), cl::cat(ClangOffloadBundlerCategory));
97 
98 static cl::opt<bool>
99     ListBundleIDs("list", cl::desc("List bundle IDs in the bundled file.\n"),
100                   cl::init(false), cl::cat(ClangOffloadBundlerCategory));
101 
102 static cl::opt<bool> PrintExternalCommands(
103     "###",
104     cl::desc("Print any external commands that are to be executed "
105              "instead of actually executing them - for testing purposes.\n"),
106     cl::init(false), cl::cat(ClangOffloadBundlerCategory));
107 
108 static cl::opt<bool>
109     AllowMissingBundles("allow-missing-bundles",
110                         cl::desc("Create empty files if bundles are missing "
111                                  "when unbundling.\n"),
112                         cl::init(false), cl::cat(ClangOffloadBundlerCategory));
113 
114 static cl::opt<unsigned>
115     BundleAlignment("bundle-align",
116                     cl::desc("Alignment of bundle for binary files"),
117                     cl::init(1), cl::cat(ClangOffloadBundlerCategory));
118 
119 /// Magic string that marks the existence of offloading data.
120 #define OFFLOAD_BUNDLER_MAGIC_STR "__CLANG_OFFLOAD_BUNDLE__"
121 
122 /// The index of the host input in the list of inputs.
123 static unsigned HostInputIndex = ~0u;
124 
125 /// Whether not having host target is allowed.
126 static bool AllowNoHost = false;
127 
128 /// Path to the current binary.
129 static std::string BundlerExecutable;
130 
131 /// Obtain the offload kind, real machine triple, and an optional GPUArch
132 /// out of the target information specified by the user.
133 /// Bundle Entry ID (or, Offload Target String) has following components:
134 ///  * Offload Kind - Host, OpenMP, or HIP
135 ///  * Triple - Standard LLVM Triple
136 ///  * GPUArch (Optional) - Processor name, like gfx906 or sm_30
137 /// In presence of Proc, the Triple should contain separator "-" for all
138 /// standard four components, even if they are empty.
139 struct OffloadTargetInfo {
140   StringRef OffloadKind;
141   llvm::Triple Triple;
142   StringRef GPUArch;
143 
144   OffloadTargetInfo(const StringRef Target) {
145     SmallVector<StringRef, 6> Components;
146     Target.split(Components, '-', 5);
147     Components.resize(6);
148     this->OffloadKind = Components[0];
149     this->Triple = llvm::Triple(Components[1], Components[2], Components[3],
150                                 Components[4]);
151     this->GPUArch = Components[5];
152   }
153 
154   bool hasHostKind() const { return this->OffloadKind == "host"; }
155 
156   bool isOffloadKindValid() const {
157     return OffloadKind == "host" || OffloadKind == "openmp" ||
158            OffloadKind == "hip" || OffloadKind == "hipv4";
159   }
160 
161   bool isTripleValid() const {
162     return !Triple.str().empty() && Triple.getArch() != Triple::UnknownArch;
163   }
164 
165   bool operator==(const OffloadTargetInfo &Target) const {
166     return OffloadKind == Target.OffloadKind &&
167            Triple.isCompatibleWith(Target.Triple) && GPUArch == Target.GPUArch;
168   }
169 
170   std::string str() {
171     return Twine(OffloadKind + "-" + Triple.str() + "-" + GPUArch).str();
172   }
173 };
174 
175 /// Generic file handler interface.
176 class FileHandler {
177 public:
178   struct BundleInfo {
179     StringRef BundleID;
180   };
181 
182   FileHandler() {}
183 
184   virtual ~FileHandler() {}
185 
186   /// Update the file handler with information from the header of the bundled
187   /// file.
188   virtual Error ReadHeader(MemoryBuffer &Input) = 0;
189 
190   /// Read the marker of the next bundled to be read in the file. The bundle
191   /// name is returned if there is one in the file, or `None` if there are no
192   /// more bundles to be read.
193   virtual Expected<Optional<StringRef>>
194   ReadBundleStart(MemoryBuffer &Input) = 0;
195 
196   /// Read the marker that closes the current bundle.
197   virtual Error ReadBundleEnd(MemoryBuffer &Input) = 0;
198 
199   /// Read the current bundle and write the result into the stream \a OS.
200   virtual Error ReadBundle(raw_ostream &OS, MemoryBuffer &Input) = 0;
201 
202   /// Write the header of the bundled file to \a OS based on the information
203   /// gathered from \a Inputs.
204   virtual Error WriteHeader(raw_fd_ostream &OS,
205                             ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) = 0;
206 
207   /// Write the marker that initiates a bundle for the triple \a TargetTriple to
208   /// \a OS.
209   virtual Error WriteBundleStart(raw_fd_ostream &OS,
210                                  StringRef TargetTriple) = 0;
211 
212   /// Write the marker that closes a bundle for the triple \a TargetTriple to \a
213   /// OS.
214   virtual Error WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) = 0;
215 
216   /// Write the bundle from \a Input into \a OS.
217   virtual Error WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) = 0;
218 
219   /// List bundle IDs in \a Input.
220   virtual Error listBundleIDs(MemoryBuffer &Input) {
221     if (Error Err = ReadHeader(Input))
222       return Err;
223 
224     return forEachBundle(Input, [&](const BundleInfo &Info) -> Error {
225       llvm::outs() << Info.BundleID << '\n';
226       Error Err = listBundleIDsCallback(Input, Info);
227       if (Err)
228         return Err;
229       return Error::success();
230     });
231   }
232 
233   /// For each bundle in \a Input, do \a Func.
234   Error forEachBundle(MemoryBuffer &Input,
235                       std::function<Error(const BundleInfo &)> Func) {
236     while (true) {
237       Expected<Optional<StringRef>> CurTripleOrErr = ReadBundleStart(Input);
238       if (!CurTripleOrErr)
239         return CurTripleOrErr.takeError();
240 
241       // No more bundles.
242       if (!*CurTripleOrErr)
243         break;
244 
245       StringRef CurTriple = **CurTripleOrErr;
246       assert(!CurTriple.empty());
247 
248       BundleInfo Info{CurTriple};
249       if (Error Err = Func(Info))
250         return Err;
251     }
252     return Error::success();
253   }
254 
255 protected:
256   virtual Error listBundleIDsCallback(MemoryBuffer &Input,
257                                       const BundleInfo &Info) {
258     return Error::success();
259   }
260 };
261 
262 /// Handler for binary files. The bundled file will have the following format
263 /// (all integers are stored in little-endian format):
264 ///
265 /// "OFFLOAD_BUNDLER_MAGIC_STR" (ASCII encoding of the string)
266 ///
267 /// NumberOfOffloadBundles (8-byte integer)
268 ///
269 /// OffsetOfBundle1 (8-byte integer)
270 /// SizeOfBundle1 (8-byte integer)
271 /// NumberOfBytesInTripleOfBundle1 (8-byte integer)
272 /// TripleOfBundle1 (byte length defined before)
273 ///
274 /// ...
275 ///
276 /// OffsetOfBundleN (8-byte integer)
277 /// SizeOfBundleN (8-byte integer)
278 /// NumberOfBytesInTripleOfBundleN (8-byte integer)
279 /// TripleOfBundleN (byte length defined before)
280 ///
281 /// Bundle1
282 /// ...
283 /// BundleN
284 
285 /// Read 8-byte integers from a buffer in little-endian format.
286 static uint64_t Read8byteIntegerFromBuffer(StringRef Buffer, size_t pos) {
287   uint64_t Res = 0;
288   const char *Data = Buffer.data();
289 
290   for (unsigned i = 0; i < 8; ++i) {
291     Res <<= 8;
292     uint64_t Char = (uint64_t)Data[pos + 7 - i];
293     Res |= 0xffu & Char;
294   }
295   return Res;
296 }
297 
298 /// Write 8-byte integers to a buffer in little-endian format.
299 static void Write8byteIntegerToBuffer(raw_fd_ostream &OS, uint64_t Val) {
300   for (unsigned i = 0; i < 8; ++i) {
301     char Char = (char)(Val & 0xffu);
302     OS.write(&Char, 1);
303     Val >>= 8;
304   }
305 }
306 
307 class BinaryFileHandler final : public FileHandler {
308   /// Information about the bundles extracted from the header.
309   struct BinaryBundleInfo final : public BundleInfo {
310     /// Size of the bundle.
311     uint64_t Size = 0u;
312     /// Offset at which the bundle starts in the bundled file.
313     uint64_t Offset = 0u;
314 
315     BinaryBundleInfo() {}
316     BinaryBundleInfo(uint64_t Size, uint64_t Offset)
317         : Size(Size), Offset(Offset) {}
318   };
319 
320   /// Map between a triple and the corresponding bundle information.
321   StringMap<BinaryBundleInfo> BundlesInfo;
322 
323   /// Iterator for the bundle information that is being read.
324   StringMap<BinaryBundleInfo>::iterator CurBundleInfo;
325   StringMap<BinaryBundleInfo>::iterator NextBundleInfo;
326 
327   /// Current bundle target to be written.
328   std::string CurWriteBundleTarget;
329 
330 public:
331   BinaryFileHandler() : FileHandler() {}
332 
333   ~BinaryFileHandler() final {}
334 
335   Error ReadHeader(MemoryBuffer &Input) final {
336     StringRef FC = Input.getBuffer();
337 
338     // Initialize the current bundle with the end of the container.
339     CurBundleInfo = BundlesInfo.end();
340 
341     // Check if buffer is smaller than magic string.
342     size_t ReadChars = sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1;
343     if (ReadChars > FC.size())
344       return Error::success();
345 
346     // Check if no magic was found.
347     StringRef Magic(FC.data(), sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1);
348     if (!Magic.equals(OFFLOAD_BUNDLER_MAGIC_STR))
349       return Error::success();
350 
351     // Read number of bundles.
352     if (ReadChars + 8 > FC.size())
353       return Error::success();
354 
355     uint64_t NumberOfBundles = Read8byteIntegerFromBuffer(FC, ReadChars);
356     ReadChars += 8;
357 
358     // Read bundle offsets, sizes and triples.
359     for (uint64_t i = 0; i < NumberOfBundles; ++i) {
360 
361       // Read offset.
362       if (ReadChars + 8 > FC.size())
363         return Error::success();
364 
365       uint64_t Offset = Read8byteIntegerFromBuffer(FC, ReadChars);
366       ReadChars += 8;
367 
368       // Read size.
369       if (ReadChars + 8 > FC.size())
370         return Error::success();
371 
372       uint64_t Size = Read8byteIntegerFromBuffer(FC, ReadChars);
373       ReadChars += 8;
374 
375       // Read triple size.
376       if (ReadChars + 8 > FC.size())
377         return Error::success();
378 
379       uint64_t TripleSize = Read8byteIntegerFromBuffer(FC, ReadChars);
380       ReadChars += 8;
381 
382       // Read triple.
383       if (ReadChars + TripleSize > FC.size())
384         return Error::success();
385 
386       StringRef Triple(&FC.data()[ReadChars], TripleSize);
387       ReadChars += TripleSize;
388 
389       // Check if the offset and size make sense.
390       if (!Offset || Offset + Size > FC.size())
391         return Error::success();
392 
393       assert(BundlesInfo.find(Triple) == BundlesInfo.end() &&
394              "Triple is duplicated??");
395       BundlesInfo[Triple] = BinaryBundleInfo(Size, Offset);
396     }
397     // Set the iterator to where we will start to read.
398     CurBundleInfo = BundlesInfo.end();
399     NextBundleInfo = BundlesInfo.begin();
400     return Error::success();
401   }
402 
403   Expected<Optional<StringRef>> ReadBundleStart(MemoryBuffer &Input) final {
404     if (NextBundleInfo == BundlesInfo.end())
405       return None;
406     CurBundleInfo = NextBundleInfo++;
407     return CurBundleInfo->first();
408   }
409 
410   Error ReadBundleEnd(MemoryBuffer &Input) final {
411     assert(CurBundleInfo != BundlesInfo.end() && "Invalid reader info!");
412     return Error::success();
413   }
414 
415   Error ReadBundle(raw_ostream &OS, MemoryBuffer &Input) final {
416     assert(CurBundleInfo != BundlesInfo.end() && "Invalid reader info!");
417     StringRef FC = Input.getBuffer();
418     OS.write(FC.data() + CurBundleInfo->second.Offset,
419              CurBundleInfo->second.Size);
420     return Error::success();
421   }
422 
423   Error WriteHeader(raw_fd_ostream &OS,
424                     ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) final {
425     // Compute size of the header.
426     uint64_t HeaderSize = 0;
427 
428     HeaderSize += sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1;
429     HeaderSize += 8; // Number of Bundles
430 
431     for (auto &T : TargetNames) {
432       HeaderSize += 3 * 8; // Bundle offset, Size of bundle and size of triple.
433       HeaderSize += T.size(); // The triple.
434     }
435 
436     // Write to the buffer the header.
437     OS << OFFLOAD_BUNDLER_MAGIC_STR;
438 
439     Write8byteIntegerToBuffer(OS, TargetNames.size());
440 
441     unsigned Idx = 0;
442     for (auto &T : TargetNames) {
443       MemoryBuffer &MB = *Inputs[Idx++];
444       HeaderSize = alignTo(HeaderSize, BundleAlignment);
445       // Bundle offset.
446       Write8byteIntegerToBuffer(OS, HeaderSize);
447       // Size of the bundle (adds to the next bundle's offset)
448       Write8byteIntegerToBuffer(OS, MB.getBufferSize());
449       BundlesInfo[T] = BinaryBundleInfo(MB.getBufferSize(), HeaderSize);
450       HeaderSize += MB.getBufferSize();
451       // Size of the triple
452       Write8byteIntegerToBuffer(OS, T.size());
453       // Triple
454       OS << T;
455     }
456     return Error::success();
457   }
458 
459   Error WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) final {
460     CurWriteBundleTarget = TargetTriple.str();
461     return Error::success();
462   }
463 
464   Error WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final {
465     return Error::success();
466   }
467 
468   Error WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
469     auto BI = BundlesInfo[CurWriteBundleTarget];
470     OS.seek(BI.Offset);
471     OS.write(Input.getBufferStart(), Input.getBufferSize());
472     return Error::success();
473   }
474 };
475 
476 namespace {
477 
478 // This class implements a list of temporary files that are removed upon
479 // object destruction.
480 class TempFileHandlerRAII {
481 public:
482   ~TempFileHandlerRAII() {
483     for (const auto &File : Files)
484       sys::fs::remove(File);
485   }
486 
487   // Creates temporary file with given contents.
488   Expected<StringRef> Create(Optional<ArrayRef<char>> Contents) {
489     SmallString<128u> File;
490     if (std::error_code EC =
491             sys::fs::createTemporaryFile("clang-offload-bundler", "tmp", File))
492       return createFileError(File, EC);
493     Files.push_front(File);
494 
495     if (Contents) {
496       std::error_code EC;
497       raw_fd_ostream OS(File, EC);
498       if (EC)
499         return createFileError(File, EC);
500       OS.write(Contents->data(), Contents->size());
501     }
502     return Files.front().str();
503   }
504 
505 private:
506   std::forward_list<SmallString<128u>> Files;
507 };
508 
509 } // end anonymous namespace
510 
511 /// Handler for object files. The bundles are organized by sections with a
512 /// designated name.
513 ///
514 /// To unbundle, we just copy the contents of the designated section.
515 class ObjectFileHandler final : public FileHandler {
516 
517   /// The object file we are currently dealing with.
518   std::unique_ptr<ObjectFile> Obj;
519 
520   /// Return the input file contents.
521   StringRef getInputFileContents() const { return Obj->getData(); }
522 
523   /// Return bundle name (<kind>-<triple>) if the provided section is an offload
524   /// section.
525   static Expected<Optional<StringRef>> IsOffloadSection(SectionRef CurSection) {
526     Expected<StringRef> NameOrErr = CurSection.getName();
527     if (!NameOrErr)
528       return NameOrErr.takeError();
529 
530     // If it does not start with the reserved suffix, just skip this section.
531     if (!NameOrErr->startswith(OFFLOAD_BUNDLER_MAGIC_STR))
532       return None;
533 
534     // Return the triple that is right after the reserved prefix.
535     return NameOrErr->substr(sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1);
536   }
537 
538   /// Total number of inputs.
539   unsigned NumberOfInputs = 0;
540 
541   /// Total number of processed inputs, i.e, inputs that were already
542   /// read from the buffers.
543   unsigned NumberOfProcessedInputs = 0;
544 
545   /// Iterator of the current and next section.
546   section_iterator CurrentSection;
547   section_iterator NextSection;
548 
549 public:
550   ObjectFileHandler(std::unique_ptr<ObjectFile> ObjIn)
551       : FileHandler(), Obj(std::move(ObjIn)),
552         CurrentSection(Obj->section_begin()),
553         NextSection(Obj->section_begin()) {}
554 
555   ~ObjectFileHandler() final {}
556 
557   Error ReadHeader(MemoryBuffer &Input) final { return Error::success(); }
558 
559   Expected<Optional<StringRef>> ReadBundleStart(MemoryBuffer &Input) final {
560     while (NextSection != Obj->section_end()) {
561       CurrentSection = NextSection;
562       ++NextSection;
563 
564       // Check if the current section name starts with the reserved prefix. If
565       // so, return the triple.
566       Expected<Optional<StringRef>> TripleOrErr =
567           IsOffloadSection(*CurrentSection);
568       if (!TripleOrErr)
569         return TripleOrErr.takeError();
570       if (*TripleOrErr)
571         return **TripleOrErr;
572     }
573     return None;
574   }
575 
576   Error ReadBundleEnd(MemoryBuffer &Input) final { return Error::success(); }
577 
578   Error ReadBundle(raw_ostream &OS, MemoryBuffer &Input) final {
579     Expected<StringRef> ContentOrErr = CurrentSection->getContents();
580     if (!ContentOrErr)
581       return ContentOrErr.takeError();
582     StringRef Content = *ContentOrErr;
583 
584     // Copy fat object contents to the output when extracting host bundle.
585     if (Content.size() == 1u && Content.front() == 0)
586       Content = StringRef(Input.getBufferStart(), Input.getBufferSize());
587 
588     OS.write(Content.data(), Content.size());
589     return Error::success();
590   }
591 
592   Error WriteHeader(raw_fd_ostream &OS,
593                     ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) final {
594     assert(HostInputIndex != ~0u && "Host input index not defined.");
595 
596     // Record number of inputs.
597     NumberOfInputs = Inputs.size();
598     return Error::success();
599   }
600 
601   Error WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) final {
602     ++NumberOfProcessedInputs;
603     return Error::success();
604   }
605 
606   Error WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final {
607     assert(NumberOfProcessedInputs <= NumberOfInputs &&
608            "Processing more inputs that actually exist!");
609     assert(HostInputIndex != ~0u && "Host input index not defined.");
610 
611     // If this is not the last output, we don't have to do anything.
612     if (NumberOfProcessedInputs != NumberOfInputs)
613       return Error::success();
614 
615     // We will use llvm-objcopy to add target objects sections to the output
616     // fat object. These sections should have 'exclude' flag set which tells
617     // link editor to remove them from linker inputs when linking executable or
618     // shared library.
619 
620     // Find llvm-objcopy in order to create the bundle binary.
621     ErrorOr<std::string> Objcopy = sys::findProgramByName(
622         "llvm-objcopy", sys::path::parent_path(BundlerExecutable));
623     if (!Objcopy)
624       Objcopy = sys::findProgramByName("llvm-objcopy");
625     if (!Objcopy)
626       return createStringError(Objcopy.getError(),
627                                "unable to find 'llvm-objcopy' in path");
628 
629     // We write to the output file directly. So, we close it and use the name
630     // to pass down to llvm-objcopy.
631     OS.close();
632 
633     // Temporary files that need to be removed.
634     TempFileHandlerRAII TempFiles;
635 
636     // Compose llvm-objcopy command line for add target objects' sections with
637     // appropriate flags.
638     BumpPtrAllocator Alloc;
639     StringSaver SS{Alloc};
640     SmallVector<StringRef, 8u> ObjcopyArgs{"llvm-objcopy"};
641     for (unsigned I = 0; I < NumberOfInputs; ++I) {
642       StringRef InputFile = InputFileNames[I];
643       if (I == HostInputIndex) {
644         // Special handling for the host bundle. We do not need to add a
645         // standard bundle for the host object since we are going to use fat
646         // object as a host object. Therefore use dummy contents (one zero byte)
647         // when creating section for the host bundle.
648         Expected<StringRef> TempFileOrErr = TempFiles.Create(ArrayRef<char>(0));
649         if (!TempFileOrErr)
650           return TempFileOrErr.takeError();
651         InputFile = *TempFileOrErr;
652       }
653 
654       ObjcopyArgs.push_back(SS.save(Twine("--add-section=") +
655                                     OFFLOAD_BUNDLER_MAGIC_STR + TargetNames[I] +
656                                     "=" + InputFile));
657       ObjcopyArgs.push_back(SS.save(Twine("--set-section-flags=") +
658                                     OFFLOAD_BUNDLER_MAGIC_STR + TargetNames[I] +
659                                     "=readonly,exclude"));
660     }
661     ObjcopyArgs.push_back("--");
662     ObjcopyArgs.push_back(InputFileNames[HostInputIndex]);
663     ObjcopyArgs.push_back(OutputFileNames.front());
664 
665     if (Error Err = executeObjcopy(*Objcopy, ObjcopyArgs))
666       return Err;
667 
668     return Error::success();
669   }
670 
671   Error WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
672     return Error::success();
673   }
674 
675 private:
676   static Error executeObjcopy(StringRef Objcopy, ArrayRef<StringRef> Args) {
677     // If the user asked for the commands to be printed out, we do that
678     // instead of executing it.
679     if (PrintExternalCommands) {
680       errs() << "\"" << Objcopy << "\"";
681       for (StringRef Arg : drop_begin(Args, 1))
682         errs() << " \"" << Arg << "\"";
683       errs() << "\n";
684     } else {
685       if (sys::ExecuteAndWait(Objcopy, Args))
686         return createStringError(inconvertibleErrorCode(),
687                                  "'llvm-objcopy' tool failed");
688     }
689     return Error::success();
690   }
691 };
692 
693 /// Handler for text files. The bundled file will have the following format.
694 ///
695 /// "Comment OFFLOAD_BUNDLER_MAGIC_STR__START__ triple"
696 /// Bundle 1
697 /// "Comment OFFLOAD_BUNDLER_MAGIC_STR__END__ triple"
698 /// ...
699 /// "Comment OFFLOAD_BUNDLER_MAGIC_STR__START__ triple"
700 /// Bundle N
701 /// "Comment OFFLOAD_BUNDLER_MAGIC_STR__END__ triple"
702 class TextFileHandler final : public FileHandler {
703   /// String that begins a line comment.
704   StringRef Comment;
705 
706   /// String that initiates a bundle.
707   std::string BundleStartString;
708 
709   /// String that closes a bundle.
710   std::string BundleEndString;
711 
712   /// Number of chars read from input.
713   size_t ReadChars = 0u;
714 
715 protected:
716   Error ReadHeader(MemoryBuffer &Input) final { return Error::success(); }
717 
718   Expected<Optional<StringRef>> ReadBundleStart(MemoryBuffer &Input) final {
719     StringRef FC = Input.getBuffer();
720 
721     // Find start of the bundle.
722     ReadChars = FC.find(BundleStartString, ReadChars);
723     if (ReadChars == FC.npos)
724       return None;
725 
726     // Get position of the triple.
727     size_t TripleStart = ReadChars = ReadChars + BundleStartString.size();
728 
729     // Get position that closes the triple.
730     size_t TripleEnd = ReadChars = FC.find("\n", ReadChars);
731     if (TripleEnd == FC.npos)
732       return None;
733 
734     // Next time we read after the new line.
735     ++ReadChars;
736 
737     return StringRef(&FC.data()[TripleStart], TripleEnd - TripleStart);
738   }
739 
740   Error ReadBundleEnd(MemoryBuffer &Input) final {
741     StringRef FC = Input.getBuffer();
742 
743     // Read up to the next new line.
744     assert(FC[ReadChars] == '\n' && "The bundle should end with a new line.");
745 
746     size_t TripleEnd = ReadChars = FC.find("\n", ReadChars + 1);
747     if (TripleEnd != FC.npos)
748       // Next time we read after the new line.
749       ++ReadChars;
750 
751     return Error::success();
752   }
753 
754   Error ReadBundle(raw_ostream &OS, MemoryBuffer &Input) final {
755     StringRef FC = Input.getBuffer();
756     size_t BundleStart = ReadChars;
757 
758     // Find end of the bundle.
759     size_t BundleEnd = ReadChars = FC.find(BundleEndString, ReadChars);
760 
761     StringRef Bundle(&FC.data()[BundleStart], BundleEnd - BundleStart);
762     OS << Bundle;
763 
764     return Error::success();
765   }
766 
767   Error WriteHeader(raw_fd_ostream &OS,
768                     ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) final {
769     return Error::success();
770   }
771 
772   Error WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) final {
773     OS << BundleStartString << TargetTriple << "\n";
774     return Error::success();
775   }
776 
777   Error WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final {
778     OS << BundleEndString << TargetTriple << "\n";
779     return Error::success();
780   }
781 
782   Error WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
783     OS << Input.getBuffer();
784     return Error::success();
785   }
786 
787 public:
788   TextFileHandler(StringRef Comment)
789       : FileHandler(), Comment(Comment), ReadChars(0) {
790     BundleStartString =
791         "\n" + Comment.str() + " " OFFLOAD_BUNDLER_MAGIC_STR "__START__ ";
792     BundleEndString =
793         "\n" + Comment.str() + " " OFFLOAD_BUNDLER_MAGIC_STR "__END__ ";
794   }
795 
796   Error listBundleIDsCallback(MemoryBuffer &Input,
797                               const BundleInfo &Info) final {
798     // TODO: To list bundle IDs in a bundled text file we need to go through
799     // all bundles. The format of bundled text file may need to include a
800     // header if the performance of listing bundle IDs of bundled text file is
801     // important.
802     ReadChars = Input.getBuffer().find(BundleEndString, ReadChars);
803     if (Error Err = ReadBundleEnd(Input))
804       return Err;
805     return Error::success();
806   }
807 };
808 
809 /// Return an appropriate object file handler. We use the specific object
810 /// handler if we know how to deal with that format, otherwise we use a default
811 /// binary file handler.
812 static std::unique_ptr<FileHandler>
813 CreateObjectFileHandler(MemoryBuffer &FirstInput) {
814   // Check if the input file format is one that we know how to deal with.
815   Expected<std::unique_ptr<Binary>> BinaryOrErr = createBinary(FirstInput);
816 
817   // We only support regular object files. If failed to open the input as a
818   // known binary or this is not an object file use the default binary handler.
819   if (errorToBool(BinaryOrErr.takeError()) || !isa<ObjectFile>(*BinaryOrErr))
820     return std::make_unique<BinaryFileHandler>();
821 
822   // Otherwise create an object file handler. The handler will be owned by the
823   // client of this function.
824   return std::make_unique<ObjectFileHandler>(
825       std::unique_ptr<ObjectFile>(cast<ObjectFile>(BinaryOrErr->release())));
826 }
827 
828 /// Return an appropriate handler given the input files and options.
829 static Expected<std::unique_ptr<FileHandler>>
830 CreateFileHandler(MemoryBuffer &FirstInput) {
831   if (FilesType == "i")
832     return std::make_unique<TextFileHandler>(/*Comment=*/"//");
833   if (FilesType == "ii")
834     return std::make_unique<TextFileHandler>(/*Comment=*/"//");
835   if (FilesType == "cui")
836     return std::make_unique<TextFileHandler>(/*Comment=*/"//");
837   // TODO: `.d` should be eventually removed once `-M` and its variants are
838   // handled properly in offload compilation.
839   if (FilesType == "d")
840     return std::make_unique<TextFileHandler>(/*Comment=*/"#");
841   if (FilesType == "ll")
842     return std::make_unique<TextFileHandler>(/*Comment=*/";");
843   if (FilesType == "bc")
844     return std::make_unique<BinaryFileHandler>();
845   if (FilesType == "s")
846     return std::make_unique<TextFileHandler>(/*Comment=*/"#");
847   if (FilesType == "o")
848     return CreateObjectFileHandler(FirstInput);
849   if (FilesType == "a")
850     return CreateObjectFileHandler(FirstInput);
851   if (FilesType == "gch")
852     return std::make_unique<BinaryFileHandler>();
853   if (FilesType == "ast")
854     return std::make_unique<BinaryFileHandler>();
855 
856   return createStringError(errc::invalid_argument,
857                            "'" + FilesType + "': invalid file type specified");
858 }
859 
860 /// Bundle the files. Return true if an error was found.
861 static Error BundleFiles() {
862   std::error_code EC;
863 
864   // Create output file.
865   raw_fd_ostream OutputFile(OutputFileNames.front(), EC, sys::fs::OF_None);
866   if (EC)
867     return createFileError(OutputFileNames.front(), EC);
868 
869   // Open input files.
870   SmallVector<std::unique_ptr<MemoryBuffer>, 8u> InputBuffers;
871   InputBuffers.reserve(InputFileNames.size());
872   for (auto &I : InputFileNames) {
873     ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
874         MemoryBuffer::getFileOrSTDIN(I);
875     if (std::error_code EC = CodeOrErr.getError())
876       return createFileError(I, EC);
877     InputBuffers.emplace_back(std::move(*CodeOrErr));
878   }
879 
880   // Get the file handler. We use the host buffer as reference.
881   assert((HostInputIndex != ~0u || AllowNoHost) &&
882          "Host input index undefined??");
883   Expected<std::unique_ptr<FileHandler>> FileHandlerOrErr =
884       CreateFileHandler(*InputBuffers[AllowNoHost ? 0 : HostInputIndex]);
885   if (!FileHandlerOrErr)
886     return FileHandlerOrErr.takeError();
887 
888   std::unique_ptr<FileHandler> &FH = *FileHandlerOrErr;
889   assert(FH);
890 
891   // Write header.
892   if (Error Err = FH->WriteHeader(OutputFile, InputBuffers))
893     return Err;
894 
895   // Write all bundles along with the start/end markers. If an error was found
896   // writing the end of the bundle component, abort the bundle writing.
897   auto Input = InputBuffers.begin();
898   for (auto &Triple : TargetNames) {
899     if (Error Err = FH->WriteBundleStart(OutputFile, Triple))
900       return Err;
901     if (Error Err = FH->WriteBundle(OutputFile, **Input))
902       return Err;
903     if (Error Err = FH->WriteBundleEnd(OutputFile, Triple))
904       return Err;
905     ++Input;
906   }
907   return Error::success();
908 }
909 
910 // List bundle IDs. Return true if an error was found.
911 static Error ListBundleIDsInFile(StringRef InputFileName) {
912   // Open Input file.
913   ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
914       MemoryBuffer::getFileOrSTDIN(InputFileName);
915   if (std::error_code EC = CodeOrErr.getError())
916     return createFileError(InputFileName, EC);
917 
918   MemoryBuffer &Input = **CodeOrErr;
919 
920   // Select the right files handler.
921   Expected<std::unique_ptr<FileHandler>> FileHandlerOrErr =
922       CreateFileHandler(Input);
923   if (!FileHandlerOrErr)
924     return FileHandlerOrErr.takeError();
925 
926   std::unique_ptr<FileHandler> &FH = *FileHandlerOrErr;
927   assert(FH);
928   return FH->listBundleIDs(Input);
929 }
930 
931 // Unbundle the files. Return true if an error was found.
932 static Error UnbundleFiles() {
933   // Open Input file.
934   ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
935       MemoryBuffer::getFileOrSTDIN(InputFileNames.front());
936   if (std::error_code EC = CodeOrErr.getError())
937     return createFileError(InputFileNames.front(), EC);
938 
939   MemoryBuffer &Input = **CodeOrErr;
940 
941   // Select the right files handler.
942   Expected<std::unique_ptr<FileHandler>> FileHandlerOrErr =
943       CreateFileHandler(Input);
944   if (!FileHandlerOrErr)
945     return FileHandlerOrErr.takeError();
946 
947   std::unique_ptr<FileHandler> &FH = *FileHandlerOrErr;
948   assert(FH);
949 
950   // Read the header of the bundled file.
951   if (Error Err = FH->ReadHeader(Input))
952     return Err;
953 
954   // Create a work list that consist of the map triple/output file.
955   StringMap<StringRef> Worklist;
956   auto Output = OutputFileNames.begin();
957   for (auto &Triple : TargetNames) {
958     Worklist[Triple] = *Output;
959     ++Output;
960   }
961 
962   // Read all the bundles that are in the work list. If we find no bundles we
963   // assume the file is meant for the host target.
964   bool FoundHostBundle = false;
965   while (!Worklist.empty()) {
966     Expected<Optional<StringRef>> CurTripleOrErr = FH->ReadBundleStart(Input);
967     if (!CurTripleOrErr)
968       return CurTripleOrErr.takeError();
969 
970     // We don't have more bundles.
971     if (!*CurTripleOrErr)
972       break;
973 
974     StringRef CurTriple = **CurTripleOrErr;
975     assert(!CurTriple.empty());
976 
977     auto Output = Worklist.find(CurTriple);
978     // The file may have more bundles for other targets, that we don't care
979     // about. Therefore, move on to the next triple
980     if (Output == Worklist.end())
981       continue;
982 
983     // Check if the output file can be opened and copy the bundle to it.
984     std::error_code EC;
985     raw_fd_ostream OutputFile(Output->second, EC, sys::fs::OF_None);
986     if (EC)
987       return createFileError(Output->second, EC);
988     if (Error Err = FH->ReadBundle(OutputFile, Input))
989       return Err;
990     if (Error Err = FH->ReadBundleEnd(Input))
991       return Err;
992     Worklist.erase(Output);
993 
994     // Record if we found the host bundle.
995     auto OffloadInfo = OffloadTargetInfo(CurTriple);
996     if (OffloadInfo.hasHostKind())
997       FoundHostBundle = true;
998   }
999 
1000   if (!AllowMissingBundles && !Worklist.empty()) {
1001     std::string ErrMsg = "Can't find bundles for";
1002     std::set<StringRef> Sorted;
1003     for (auto &E : Worklist)
1004       Sorted.insert(E.first());
1005     unsigned I = 0;
1006     unsigned Last = Sorted.size() - 1;
1007     for (auto &E : Sorted) {
1008       if (I != 0 && Last > 1)
1009         ErrMsg += ",";
1010       ErrMsg += " ";
1011       if (I == Last && I != 0)
1012         ErrMsg += "and ";
1013       ErrMsg += E.str();
1014       ++I;
1015     }
1016     return createStringError(inconvertibleErrorCode(), ErrMsg);
1017   }
1018 
1019   // If no bundles were found, assume the input file is the host bundle and
1020   // create empty files for the remaining targets.
1021   if (Worklist.size() == TargetNames.size()) {
1022     for (auto &E : Worklist) {
1023       std::error_code EC;
1024       raw_fd_ostream OutputFile(E.second, EC, sys::fs::OF_None);
1025       if (EC)
1026         return createFileError(E.second, EC);
1027 
1028       // If this entry has a host kind, copy the input file to the output file.
1029       auto OffloadInfo = OffloadTargetInfo(E.getKey());
1030       if (OffloadInfo.hasHostKind())
1031         OutputFile.write(Input.getBufferStart(), Input.getBufferSize());
1032     }
1033     return Error::success();
1034   }
1035 
1036   // If we found elements, we emit an error if none of those were for the host
1037   // in case host bundle name was provided in command line.
1038   if (!FoundHostBundle && HostInputIndex != ~0u)
1039     return createStringError(inconvertibleErrorCode(),
1040                              "Can't find bundle for the host target");
1041 
1042   // If we still have any elements in the worklist, create empty files for them.
1043   for (auto &E : Worklist) {
1044     std::error_code EC;
1045     raw_fd_ostream OutputFile(E.second, EC, sys::fs::OF_None);
1046     if (EC)
1047       return createFileError(E.second, EC);
1048   }
1049 
1050   return Error::success();
1051 }
1052 
1053 static Archive::Kind getDefaultArchiveKindForHost() {
1054   return Triple(sys::getDefaultTargetTriple()).isOSDarwin() ? Archive::K_DARWIN
1055                                                             : Archive::K_GNU;
1056 }
1057 
1058 /// @brief Checks if a code object \p CodeObjectInfo is compatible with a given
1059 /// target \p TargetInfo.
1060 /// @link https://clang.llvm.org/docs/ClangOffloadBundler.html#bundle-entry-id
1061 bool isCodeObjectCompatible(OffloadTargetInfo &CodeObjectInfo,
1062                             OffloadTargetInfo &TargetInfo) {
1063 
1064   // Compatible in case of exact match.
1065   if (CodeObjectInfo == TargetInfo) {
1066     DEBUG_WITH_TYPE(
1067         "CodeObjectCompatibility",
1068         dbgs() << "Compatible: Exact match: " << CodeObjectInfo.str() << "\n");
1069     return true;
1070   }
1071 
1072   // Incompatible if Kinds or Triples mismatch.
1073   if (CodeObjectInfo.OffloadKind != TargetInfo.OffloadKind ||
1074       !CodeObjectInfo.Triple.isCompatibleWith(TargetInfo.Triple)) {
1075     DEBUG_WITH_TYPE(
1076         "CodeObjectCompatibility",
1077         dbgs() << "Incompatible: Kind/Triple mismatch \t[CodeObject: "
1078                << CodeObjectInfo.str() << "]\t:\t[Target: " << TargetInfo.str()
1079                << "]\n");
1080     return false;
1081   }
1082 
1083   // Incompatible if GPUArch mismatch.
1084   if (CodeObjectInfo.GPUArch != TargetInfo.GPUArch) {
1085     DEBUG_WITH_TYPE("CodeObjectCompatibility",
1086                     dbgs() << "Incompatible: GPU Arch mismatch \t[CodeObject: "
1087                            << CodeObjectInfo.str()
1088                            << "]\t:\t[Target: " << TargetInfo.str() << "]\n");
1089     return false;
1090   }
1091 
1092   DEBUG_WITH_TYPE(
1093       "CodeObjectCompatibility",
1094       dbgs() << "Compatible: Code Objects are compatible \t[CodeObject: "
1095              << CodeObjectInfo.str() << "]\t:\t[Target: " << TargetInfo.str()
1096              << "]\n");
1097   return true;
1098 }
1099 
1100 /// @brief Computes a list of targets among all given targets which are
1101 /// compatible with this code object
1102 /// @param [in] Code Object \p CodeObject
1103 /// @param [out] List of all compatible targets \p CompatibleTargets among all
1104 /// given targets
1105 /// @return false, if no compatible target is found.
1106 static bool
1107 getCompatibleOffloadTargets(OffloadTargetInfo &CodeObjectInfo,
1108                             SmallVectorImpl<StringRef> &CompatibleTargets) {
1109   if (!CompatibleTargets.empty()) {
1110     DEBUG_WITH_TYPE("CodeObjectCompatibility",
1111                     dbgs() << "CompatibleTargets list should be empty\n");
1112     return false;
1113   }
1114   for (auto &Target : TargetNames) {
1115     auto TargetInfo = OffloadTargetInfo(Target);
1116     if (isCodeObjectCompatible(CodeObjectInfo, TargetInfo))
1117       CompatibleTargets.push_back(Target);
1118   }
1119   return !CompatibleTargets.empty();
1120 }
1121 
1122 /// UnbundleArchive takes an archive file (".a") as input containing bundled
1123 /// code object files, and a list of offload targets (not host), and extracts
1124 /// the code objects into a new archive file for each offload target. Each
1125 /// resulting archive file contains all code object files corresponding to that
1126 /// particular offload target. The created archive file does not
1127 /// contain an index of the symbols and code object files are named as
1128 /// <<Parent Bundle Name>-<CodeObject's GPUArch>>, with ':' replaced with '_'.
1129 static Error UnbundleArchive() {
1130   std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;
1131 
1132   /// Map of target names with list of object files that will form the device
1133   /// specific archive for that target
1134   StringMap<std::vector<NewArchiveMember>> OutputArchivesMap;
1135 
1136   // Map of target names and output archive filenames
1137   StringMap<StringRef> TargetOutputFileNameMap;
1138 
1139   auto Output = OutputFileNames.begin();
1140   for (auto &Target : TargetNames) {
1141     TargetOutputFileNameMap[Target] = *Output;
1142     ++Output;
1143   }
1144 
1145   StringRef IFName = InputFileNames.front();
1146   ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
1147       MemoryBuffer::getFileOrSTDIN(IFName, true, false);
1148   if (std::error_code EC = BufOrErr.getError())
1149     return createFileError(InputFileNames.front(), EC);
1150 
1151   ArchiveBuffers.push_back(std::move(*BufOrErr));
1152   Expected<std::unique_ptr<llvm::object::Archive>> LibOrErr =
1153       Archive::create(ArchiveBuffers.back()->getMemBufferRef());
1154   if (!LibOrErr)
1155     return LibOrErr.takeError();
1156 
1157   auto Archive = std::move(*LibOrErr);
1158 
1159   Error ArchiveErr = Error::success();
1160   auto ChildEnd = Archive->child_end();
1161 
1162   /// Iterate over all bundled code object files in the input archive.
1163   for (auto ArchiveIter = Archive->child_begin(ArchiveErr);
1164        ArchiveIter != ChildEnd; ++ArchiveIter) {
1165     if (ArchiveErr)
1166       return ArchiveErr;
1167     auto ArchiveChildNameOrErr = (*ArchiveIter).getName();
1168     if (!ArchiveChildNameOrErr)
1169       return ArchiveChildNameOrErr.takeError();
1170 
1171     StringRef BundledObjectFile = sys::path::filename(*ArchiveChildNameOrErr);
1172 
1173     auto CodeObjectBufferRefOrErr = (*ArchiveIter).getMemoryBufferRef();
1174     if (!CodeObjectBufferRefOrErr)
1175       return CodeObjectBufferRefOrErr.takeError();
1176 
1177     auto CodeObjectBuffer =
1178         MemoryBuffer::getMemBuffer(*CodeObjectBufferRefOrErr, false);
1179 
1180     Expected<std::unique_ptr<FileHandler>> FileHandlerOrErr =
1181         CreateFileHandler(*CodeObjectBuffer);
1182     if (!FileHandlerOrErr)
1183       return FileHandlerOrErr.takeError();
1184 
1185     std::unique_ptr<FileHandler> &FileHandler = *FileHandlerOrErr;
1186     assert(FileHandler &&
1187            "FileHandle creation failed for file in the archive!");
1188 
1189     if (Error ReadErr = FileHandler.get()->ReadHeader(*CodeObjectBuffer))
1190       return ReadErr;
1191 
1192     Expected<Optional<StringRef>> CurBundleIDOrErr =
1193         FileHandler->ReadBundleStart(*CodeObjectBuffer);
1194     if (!CurBundleIDOrErr)
1195       return CurBundleIDOrErr.takeError();
1196 
1197     Optional<StringRef> OptionalCurBundleID = *CurBundleIDOrErr;
1198     // No device code in this child, skip.
1199     if (!OptionalCurBundleID.hasValue())
1200       continue;
1201     StringRef CodeObject = *OptionalCurBundleID;
1202 
1203     // Process all bundle entries (CodeObjects) found in this child of input
1204     // archive.
1205     while (!CodeObject.empty()) {
1206       SmallVector<StringRef> CompatibleTargets;
1207       auto CodeObjectInfo = OffloadTargetInfo(CodeObject);
1208       if (CodeObjectInfo.hasHostKind()) {
1209         // Do nothing, we don't extract host code yet.
1210       } else if (getCompatibleOffloadTargets(CodeObjectInfo,
1211                                              CompatibleTargets)) {
1212         std::string BundleData;
1213         raw_string_ostream DataStream(BundleData);
1214         if (Error Err =
1215                 FileHandler.get()->ReadBundle(DataStream, *CodeObjectBuffer))
1216           return Err;
1217 
1218         for (auto &CompatibleTarget : CompatibleTargets) {
1219           SmallString<128> BundledObjectFileName;
1220           BundledObjectFileName.assign(BundledObjectFile);
1221           auto OutputBundleName =
1222               Twine(llvm::sys::path::stem(BundledObjectFileName) + "-" +
1223                     CodeObject)
1224                   .str();
1225           // Replace ':' in optional target feature list with '_' to ensure
1226           // cross-platform validity.
1227           std::replace(OutputBundleName.begin(), OutputBundleName.end(), ':',
1228                        '_');
1229 
1230           std::unique_ptr<MemoryBuffer> MemBuf = MemoryBuffer::getMemBufferCopy(
1231               DataStream.str(), OutputBundleName);
1232           ArchiveBuffers.push_back(std::move(MemBuf));
1233           llvm::MemoryBufferRef MemBufRef =
1234               MemoryBufferRef(*(ArchiveBuffers.back()));
1235 
1236           // For inserting <CompatibleTarget, list<CodeObject>> entry in
1237           // OutputArchivesMap.
1238           if (OutputArchivesMap.find(CompatibleTarget) ==
1239               OutputArchivesMap.end()) {
1240 
1241             std::vector<NewArchiveMember> ArchiveMembers;
1242             ArchiveMembers.push_back(NewArchiveMember(MemBufRef));
1243             OutputArchivesMap.insert_or_assign(CompatibleTarget,
1244                                                std::move(ArchiveMembers));
1245           } else {
1246             OutputArchivesMap[CompatibleTarget].push_back(
1247                 NewArchiveMember(MemBufRef));
1248           }
1249         }
1250       }
1251 
1252       if (Error Err = FileHandler.get()->ReadBundleEnd(*CodeObjectBuffer))
1253         return Err;
1254 
1255       Expected<Optional<StringRef>> NextTripleOrErr =
1256           FileHandler->ReadBundleStart(*CodeObjectBuffer);
1257       if (!NextTripleOrErr)
1258         return NextTripleOrErr.takeError();
1259 
1260       CodeObject = ((*NextTripleOrErr).hasValue()) ? **NextTripleOrErr : "";
1261     } // End of processing of all bundle entries of this child of input archive.
1262   }   // End of while over children of input archive.
1263 
1264   assert(!ArchiveErr && "Error occured while reading archive!");
1265 
1266   /// Write out an archive for each target
1267   for (auto &Target : TargetNames) {
1268     StringRef FileName = TargetOutputFileNameMap[Target];
1269     StringMapIterator<std::vector<llvm::NewArchiveMember>> CurArchiveMembers =
1270         OutputArchivesMap.find(Target);
1271     if (CurArchiveMembers != OutputArchivesMap.end()) {
1272       if (Error WriteErr = writeArchive(FileName, CurArchiveMembers->getValue(),
1273                                         true, getDefaultArchiveKindForHost(),
1274                                         true, false, nullptr))
1275         return WriteErr;
1276     } else if (!AllowMissingBundles) {
1277       std::string ErrMsg =
1278           Twine("no compatible code object found for the target '" + Target +
1279                 "' in heterogenous archive library: " + IFName)
1280               .str();
1281       return createStringError(inconvertibleErrorCode(), ErrMsg);
1282     }
1283   }
1284 
1285   return Error::success();
1286 }
1287 
1288 static void PrintVersion(raw_ostream &OS) {
1289   OS << clang::getClangToolFullVersion("clang-offload-bundler") << '\n';
1290 }
1291 
1292 int main(int argc, const char **argv) {
1293   sys::PrintStackTraceOnErrorSignal(argv[0]);
1294 
1295   cl::HideUnrelatedOptions(ClangOffloadBundlerCategory);
1296   cl::SetVersionPrinter(PrintVersion);
1297   cl::ParseCommandLineOptions(
1298       argc, argv,
1299       "A tool to bundle several input files of the specified type <type> \n"
1300       "referring to the same source file but different targets into a single \n"
1301       "one. The resulting file can also be unbundled into different files by \n"
1302       "this tool if -unbundle is provided.\n");
1303 
1304   if (Help) {
1305     cl::PrintHelpMessage();
1306     return 0;
1307   }
1308 
1309   auto reportError = [argv](Error E) {
1310     logAllUnhandledErrors(std::move(E), WithColor::error(errs(), argv[0]));
1311     exit(1);
1312   };
1313 
1314   auto doWork = [&](std::function<llvm::Error()> Work) {
1315     // Save the current executable directory as it will be useful to find other
1316     // tools.
1317     BundlerExecutable = argv[0];
1318     if (!llvm::sys::fs::exists(BundlerExecutable))
1319       BundlerExecutable =
1320           sys::fs::getMainExecutable(argv[0], &BundlerExecutable);
1321 
1322     if (llvm::Error Err = Work()) {
1323       reportError(std::move(Err));
1324     }
1325   };
1326 
1327   if (ListBundleIDs) {
1328     if (Unbundle) {
1329       reportError(
1330           createStringError(errc::invalid_argument,
1331                             "-unbundle and -list cannot be used together"));
1332     }
1333     if (InputFileNames.size() != 1) {
1334       reportError(createStringError(errc::invalid_argument,
1335                                     "only one input file supported for -list"));
1336     }
1337     if (OutputFileNames.size()) {
1338       reportError(createStringError(errc::invalid_argument,
1339                                     "-outputs option is invalid for -list"));
1340     }
1341     if (TargetNames.size()) {
1342       reportError(createStringError(errc::invalid_argument,
1343                                     "-targets option is invalid for -list"));
1344     }
1345 
1346     doWork([]() { return ListBundleIDsInFile(InputFileNames.front()); });
1347     return 0;
1348   }
1349 
1350   if (OutputFileNames.getNumOccurrences() == 0) {
1351     reportError(createStringError(
1352         errc::invalid_argument,
1353         "for the --outputs option: must be specified at least once!"));
1354   }
1355   if (TargetNames.getNumOccurrences() == 0) {
1356     reportError(createStringError(
1357         errc::invalid_argument,
1358         "for the --targets option: must be specified at least once!"));
1359   }
1360   if (Unbundle) {
1361     if (InputFileNames.size() != 1) {
1362       reportError(createStringError(
1363           errc::invalid_argument,
1364           "only one input file supported in unbundling mode"));
1365     }
1366     if (OutputFileNames.size() != TargetNames.size()) {
1367       reportError(createStringError(errc::invalid_argument,
1368                                     "number of output files and targets should "
1369                                     "match in unbundling mode"));
1370     }
1371   } else {
1372     if (FilesType == "a") {
1373       reportError(createStringError(errc::invalid_argument,
1374                                     "Archive files are only supported "
1375                                     "for unbundling"));
1376     }
1377     if (OutputFileNames.size() != 1) {
1378       reportError(createStringError(
1379           errc::invalid_argument,
1380           "only one output file supported in bundling mode"));
1381     }
1382     if (InputFileNames.size() != TargetNames.size()) {
1383       reportError(createStringError(
1384           errc::invalid_argument,
1385           "number of input files and targets should match in bundling mode"));
1386     }
1387   }
1388 
1389   // Verify that the offload kinds and triples are known. We also check that we
1390   // have exactly one host target.
1391   unsigned Index = 0u;
1392   unsigned HostTargetNum = 0u;
1393   bool HIPOnly = true;
1394   llvm::DenseSet<StringRef> ParsedTargets;
1395   for (StringRef Target : TargetNames) {
1396     if (ParsedTargets.contains(Target)) {
1397       reportError(createStringError(errc::invalid_argument,
1398                                     "Duplicate targets are not allowed"));
1399     }
1400     ParsedTargets.insert(Target);
1401 
1402     auto OffloadInfo = OffloadTargetInfo(Target);
1403     bool KindIsValid = OffloadInfo.isOffloadKindValid();
1404     bool TripleIsValid = OffloadInfo.isTripleValid();
1405 
1406     if (!KindIsValid || !TripleIsValid) {
1407       SmallVector<char, 128u> Buf;
1408       raw_svector_ostream Msg(Buf);
1409       Msg << "invalid target '" << Target << "'";
1410       if (!KindIsValid)
1411         Msg << ", unknown offloading kind '" << OffloadInfo.OffloadKind << "'";
1412       if (!TripleIsValid)
1413         Msg << ", unknown target triple '" << OffloadInfo.Triple.str() << "'";
1414       reportError(createStringError(errc::invalid_argument, Msg.str()));
1415     }
1416 
1417     if (KindIsValid && OffloadInfo.hasHostKind()) {
1418       ++HostTargetNum;
1419       // Save the index of the input that refers to the host.
1420       HostInputIndex = Index;
1421     }
1422 
1423     if (OffloadInfo.OffloadKind != "hip" && OffloadInfo.OffloadKind != "hipv4")
1424       HIPOnly = false;
1425 
1426     ++Index;
1427   }
1428 
1429   // HIP uses clang-offload-bundler to bundle device-only compilation results
1430   // for multiple GPU archs, therefore allow no host target if all entries
1431   // are for HIP.
1432   AllowNoHost = HIPOnly;
1433 
1434   // Host triple is not really needed for unbundling operation, so do not
1435   // treat missing host triple as error if we do unbundling.
1436   if ((Unbundle && HostTargetNum > 1) ||
1437       (!Unbundle && HostTargetNum != 1 && !AllowNoHost)) {
1438     reportError(createStringError(errc::invalid_argument,
1439                                   "expecting exactly one host target but got " +
1440                                       Twine(HostTargetNum)));
1441   }
1442 
1443   doWork([]() {
1444     if (Unbundle) {
1445       if (FilesType == "a")
1446         return UnbundleArchive();
1447       else
1448         return UnbundleFiles();
1449     } else
1450       return BundleFiles();
1451   });
1452   return 0;
1453 }
1454