]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/clang-offload-bundler/ClangOffloadBundler.cpp
Vendor import of clang trunk r338150:
[FreeBSD/FreeBSD.git] / tools / clang-offload-bundler / ClangOffloadBundler.cpp
1 //===-- clang-offload-bundler/ClangOffloadBundler.cpp ---------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// This file implements a clang-offload-bundler that bundles different
12 /// files that relate with the same source code but different targets into a
13 /// single one. Also the implements the opposite functionality, i.e. unbundle
14 /// files previous created by this tool.
15 ///
16 //===----------------------------------------------------------------------===//
17
18 #include "clang/Basic/Version.h"
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/SmallString.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/Bitcode/BitcodeWriter.h"
26 #include "llvm/IR/Constant.h"
27 #include "llvm/IR/Constants.h"
28 #include "llvm/IR/GlobalVariable.h"
29 #include "llvm/IR/LLVMContext.h"
30 #include "llvm/IR/Module.h"
31 #include "llvm/Object/Binary.h"
32 #include "llvm/Object/ObjectFile.h"
33 #include "llvm/Support/Casting.h"
34 #include "llvm/Support/CommandLine.h"
35 #include "llvm/Support/Error.h"
36 #include "llvm/Support/ErrorOr.h"
37 #include "llvm/Support/FileSystem.h"
38 #include "llvm/Support/MemoryBuffer.h"
39 #include "llvm/Support/Path.h"
40 #include "llvm/Support/Program.h"
41 #include "llvm/Support/raw_ostream.h"
42 #include "llvm/Support/Signals.h"
43 #include <algorithm>
44 #include <cassert>
45 #include <cstddef>
46 #include <cstdint>
47 #include <memory>
48 #include <string>
49 #include <system_error>
50 #include <vector>
51
52 using namespace llvm;
53 using namespace llvm::object;
54
55 static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
56
57 // Mark all our options with this category, everything else (except for -version
58 // and -help) will be hidden.
59 static cl::OptionCategory
60     ClangOffloadBundlerCategory("clang-offload-bundler options");
61
62 static cl::list<std::string>
63     InputFileNames("inputs", cl::CommaSeparated, cl::OneOrMore,
64                    cl::desc("[<input file>,...]"),
65                    cl::cat(ClangOffloadBundlerCategory));
66 static cl::list<std::string>
67     OutputFileNames("outputs", cl::CommaSeparated, cl::OneOrMore,
68                     cl::desc("[<output file>,...]"),
69                     cl::cat(ClangOffloadBundlerCategory));
70 static cl::list<std::string>
71     TargetNames("targets", cl::CommaSeparated, cl::OneOrMore,
72                 cl::desc("[<offload kind>-<target triple>,...]"),
73                 cl::cat(ClangOffloadBundlerCategory));
74 static cl::opt<std::string>
75     FilesType("type", cl::Required,
76               cl::desc("Type of the files to be bundled/unbundled.\n"
77                        "Current supported types are:\n"
78                        "  i   - cpp-output\n"
79                        "  ii  - c++-cpp-output\n"
80                        "  ll  - llvm\n"
81                        "  bc  - llvm-bc\n"
82                        "  s   - assembler\n"
83                        "  o   - object\n"
84                        "  gch - precompiled-header\n"
85                        "  ast - clang AST file"),
86               cl::cat(ClangOffloadBundlerCategory));
87 static cl::opt<bool>
88     Unbundle("unbundle",
89              cl::desc("Unbundle bundled file into several output files.\n"),
90              cl::init(false), cl::cat(ClangOffloadBundlerCategory));
91
92 static cl::opt<bool> PrintExternalCommands(
93     "###",
94     cl::desc("Print any external commands that are to be executed "
95              "instead of actually executing them - for testing purposes.\n"),
96     cl::init(false), cl::cat(ClangOffloadBundlerCategory));
97
98 static cl::opt<bool> DumpTemporaryFiles(
99     "dump-temporary-files",
100     cl::desc("Dumps any temporary files created - for testing purposes.\n"),
101     cl::init(false), cl::cat(ClangOffloadBundlerCategory));
102
103 /// Magic string that marks the existence of offloading data.
104 #define OFFLOAD_BUNDLER_MAGIC_STR "__CLANG_OFFLOAD_BUNDLE__"
105
106 /// The index of the host input in the list of inputs.
107 static unsigned HostInputIndex = ~0u;
108
109 /// Path to the current binary.
110 static std::string BundlerExecutable;
111
112 /// Obtain the offload kind and real machine triple out of the target
113 /// information specified by the user.
114 static void getOffloadKindAndTriple(StringRef Target, StringRef &OffloadKind,
115                                     StringRef &Triple) {
116   auto KindTriplePair = Target.split('-');
117   OffloadKind = KindTriplePair.first;
118   Triple = KindTriplePair.second;
119 }
120 static StringRef getTriple(StringRef Target) {
121   StringRef OffloadKind;
122   StringRef Triple;
123   getOffloadKindAndTriple(Target, OffloadKind, Triple);
124   return Triple;
125 }
126 static bool hasHostKind(StringRef Target) {
127   StringRef OffloadKind;
128   StringRef Triple;
129   getOffloadKindAndTriple(Target, OffloadKind, Triple);
130   return OffloadKind == "host";
131 }
132
133 /// Generic file handler interface.
134 class FileHandler {
135 public:
136   FileHandler() {}
137
138   virtual ~FileHandler() {}
139
140   /// Update the file handler with information from the header of the bundled
141   /// file
142   virtual void ReadHeader(MemoryBuffer &Input) = 0;
143
144   /// Read the marker of the next bundled to be read in the file. The triple of
145   /// the target associated with that bundle is returned. An empty string is
146   /// returned if there are no more bundles to be read.
147   virtual StringRef ReadBundleStart(MemoryBuffer &Input) = 0;
148
149   /// Read the marker that closes the current bundle.
150   virtual void ReadBundleEnd(MemoryBuffer &Input) = 0;
151
152   /// Read the current bundle and write the result into the stream \a OS.
153   virtual void ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) = 0;
154
155   /// Write the header of the bundled file to \a OS based on the information
156   /// gathered from \a Inputs.
157   virtual void WriteHeader(raw_fd_ostream &OS,
158                            ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) = 0;
159
160   /// Write the marker that initiates a bundle for the triple \a TargetTriple to
161   /// \a OS.
162   virtual void WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) = 0;
163
164   /// Write the marker that closes a bundle for the triple \a TargetTriple to \a
165   /// OS. Return true if any error was found.
166
167   virtual bool WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) = 0;
168
169   /// Write the bundle from \a Input into \a OS.
170   virtual void WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) = 0;
171 };
172
173 /// Handler for binary files. The bundled file will have the following format
174 /// (all integers are stored in little-endian format):
175 ///
176 /// "OFFLOAD_BUNDLER_MAGIC_STR" (ASCII encoding of the string)
177 ///
178 /// NumberOfOffloadBundles (8-byte integer)
179 ///
180 /// OffsetOfBundle1 (8-byte integer)
181 /// SizeOfBundle1 (8-byte integer)
182 /// NumberOfBytesInTripleOfBundle1 (8-byte integer)
183 /// TripleOfBundle1 (byte length defined before)
184 ///
185 /// ...
186 ///
187 /// OffsetOfBundleN (8-byte integer)
188 /// SizeOfBundleN (8-byte integer)
189 /// NumberOfBytesInTripleOfBundleN (8-byte integer)
190 /// TripleOfBundleN (byte length defined before)
191 ///
192 /// Bundle1
193 /// ...
194 /// BundleN
195
196 /// Read 8-byte integers from a buffer in little-endian format.
197 static uint64_t Read8byteIntegerFromBuffer(StringRef Buffer, size_t pos) {
198   uint64_t Res = 0;
199   const char *Data = Buffer.data();
200
201   for (unsigned i = 0; i < 8; ++i) {
202     Res <<= 8;
203     uint64_t Char = (uint64_t)Data[pos + 7 - i];
204     Res |= 0xffu & Char;
205   }
206   return Res;
207 }
208
209 /// Write 8-byte integers to a buffer in little-endian format.
210 static void Write8byteIntegerToBuffer(raw_fd_ostream &OS, uint64_t Val) {
211   for (unsigned i = 0; i < 8; ++i) {
212     char Char = (char)(Val & 0xffu);
213     OS.write(&Char, 1);
214     Val >>= 8;
215   }
216 }
217
218 class BinaryFileHandler final : public FileHandler {
219   /// Information about the bundles extracted from the header.
220   struct BundleInfo final {
221     /// Size of the bundle.
222     uint64_t Size = 0u;
223     /// Offset at which the bundle starts in the bundled file.
224     uint64_t Offset = 0u;
225
226     BundleInfo() {}
227     BundleInfo(uint64_t Size, uint64_t Offset) : Size(Size), Offset(Offset) {}
228   };
229
230   /// Map between a triple and the corresponding bundle information.
231   StringMap<BundleInfo> BundlesInfo;
232
233   /// Iterator for the bundle information that is being read.
234   StringMap<BundleInfo>::iterator CurBundleInfo;
235
236 public:
237   BinaryFileHandler() : FileHandler() {}
238
239   ~BinaryFileHandler() final {}
240
241   void ReadHeader(MemoryBuffer &Input) final {
242     StringRef FC = Input.getBuffer();
243
244     // Initialize the current bundle with the end of the container.
245     CurBundleInfo = BundlesInfo.end();
246
247     // Check if buffer is smaller than magic string.
248     size_t ReadChars = sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1;
249     if (ReadChars > FC.size())
250       return;
251
252     // Check if no magic was found.
253     StringRef Magic(FC.data(), sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1);
254     if (!Magic.equals(OFFLOAD_BUNDLER_MAGIC_STR))
255       return;
256
257     // Read number of bundles.
258     if (ReadChars + 8 > FC.size())
259       return;
260
261     uint64_t NumberOfBundles = Read8byteIntegerFromBuffer(FC, ReadChars);
262     ReadChars += 8;
263
264     // Read bundle offsets, sizes and triples.
265     for (uint64_t i = 0; i < NumberOfBundles; ++i) {
266
267       // Read offset.
268       if (ReadChars + 8 > FC.size())
269         return;
270
271       uint64_t Offset = Read8byteIntegerFromBuffer(FC, ReadChars);
272       ReadChars += 8;
273
274       // Read size.
275       if (ReadChars + 8 > FC.size())
276         return;
277
278       uint64_t Size = Read8byteIntegerFromBuffer(FC, ReadChars);
279       ReadChars += 8;
280
281       // Read triple size.
282       if (ReadChars + 8 > FC.size())
283         return;
284
285       uint64_t TripleSize = Read8byteIntegerFromBuffer(FC, ReadChars);
286       ReadChars += 8;
287
288       // Read triple.
289       if (ReadChars + TripleSize > FC.size())
290         return;
291
292       StringRef Triple(&FC.data()[ReadChars], TripleSize);
293       ReadChars += TripleSize;
294
295       // Check if the offset and size make sense.
296       if (!Size || !Offset || Offset + Size > FC.size())
297         return;
298
299       assert(BundlesInfo.find(Triple) == BundlesInfo.end() &&
300              "Triple is duplicated??");
301       BundlesInfo[Triple] = BundleInfo(Size, Offset);
302     }
303     // Set the iterator to where we will start to read.
304     CurBundleInfo = BundlesInfo.begin();
305   }
306
307   StringRef ReadBundleStart(MemoryBuffer &Input) final {
308     if (CurBundleInfo == BundlesInfo.end())
309       return StringRef();
310
311     return CurBundleInfo->first();
312   }
313
314   void ReadBundleEnd(MemoryBuffer &Input) final {
315     assert(CurBundleInfo != BundlesInfo.end() && "Invalid reader info!");
316     ++CurBundleInfo;
317   }
318
319   void ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
320     assert(CurBundleInfo != BundlesInfo.end() && "Invalid reader info!");
321     StringRef FC = Input.getBuffer();
322     OS.write(FC.data() + CurBundleInfo->second.Offset,
323              CurBundleInfo->second.Size);
324   }
325
326   void WriteHeader(raw_fd_ostream &OS,
327                    ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) final {
328     // Compute size of the header.
329     uint64_t HeaderSize = 0;
330
331     HeaderSize += sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1;
332     HeaderSize += 8; // Number of Bundles
333
334     for (auto &T : TargetNames) {
335       HeaderSize += 3 * 8; // Bundle offset, Size of bundle and size of triple.
336       HeaderSize += T.size(); // The triple.
337     }
338
339     // Write to the buffer the header.
340     OS << OFFLOAD_BUNDLER_MAGIC_STR;
341
342     Write8byteIntegerToBuffer(OS, TargetNames.size());
343
344     unsigned Idx = 0;
345     for (auto &T : TargetNames) {
346       MemoryBuffer &MB = *Inputs[Idx++].get();
347       // Bundle offset.
348       Write8byteIntegerToBuffer(OS, HeaderSize);
349       // Size of the bundle (adds to the next bundle's offset)
350       Write8byteIntegerToBuffer(OS, MB.getBufferSize());
351       HeaderSize += MB.getBufferSize();
352       // Size of the triple
353       Write8byteIntegerToBuffer(OS, T.size());
354       // Triple
355       OS << T;
356     }
357   }
358
359   void WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) final {}
360
361   bool WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final {
362     return false;
363   }
364
365   void WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
366     OS.write(Input.getBufferStart(), Input.getBufferSize());
367   }
368 };
369
370 /// Handler for object files. The bundles are organized by sections with a
371 /// designated name.
372 ///
373 /// In order to bundle we create an IR file with the content of each section and
374 /// use incremental linking to produce the resulting object. We also add section
375 /// with a single byte to state the name of the component the main object file
376 /// (the one we are bundling into) refers to.
377 ///
378 /// To unbundle, we use just copy the contents of the designated section. If the
379 /// requested bundle refer to the main object file, we just copy it with no
380 /// changes.
381 class ObjectFileHandler final : public FileHandler {
382
383   /// The object file we are currently dealing with.
384   std::unique_ptr<ObjectFile> Obj;
385
386   /// Return the input file contents.
387   StringRef getInputFileContents() const { return Obj->getData(); }
388
389   /// Return true if the provided section is an offload section and return the
390   /// triple by reference.
391   static bool IsOffloadSection(SectionRef CurSection,
392                                StringRef &OffloadTriple) {
393     StringRef SectionName;
394     CurSection.getName(SectionName);
395
396     if (SectionName.empty())
397       return false;
398
399     // If it does not start with the reserved suffix, just skip this section.
400     if (!SectionName.startswith(OFFLOAD_BUNDLER_MAGIC_STR))
401       return false;
402
403     // Return the triple that is right after the reserved prefix.
404     OffloadTriple = SectionName.substr(sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1);
405     return true;
406   }
407
408   /// Total number of inputs.
409   unsigned NumberOfInputs = 0;
410
411   /// Total number of processed inputs, i.e, inputs that were already
412   /// read from the buffers.
413   unsigned NumberOfProcessedInputs = 0;
414
415   /// LLVM context used to create the auxiliary modules.
416   LLVMContext VMContext;
417
418   /// LLVM module used to create an object with all the bundle
419   /// components.
420   std::unique_ptr<Module> AuxModule;
421
422   /// The current triple we are working with.
423   StringRef CurrentTriple;
424
425   /// The name of the main input file.
426   StringRef MainInputFileName;
427
428   /// Iterator of the current and next section.
429   section_iterator CurrentSection;
430   section_iterator NextSection;
431
432 public:
433   ObjectFileHandler(std::unique_ptr<ObjectFile> ObjIn)
434       : FileHandler(), Obj(std::move(ObjIn)),
435         CurrentSection(Obj->section_begin()),
436         NextSection(Obj->section_begin()) {}
437
438   ~ObjectFileHandler() final {}
439
440   void ReadHeader(MemoryBuffer &Input) final {}
441
442   StringRef ReadBundleStart(MemoryBuffer &Input) final {
443     while (NextSection != Obj->section_end()) {
444       CurrentSection = NextSection;
445       ++NextSection;
446
447       StringRef OffloadTriple;
448       // Check if the current section name starts with the reserved prefix. If
449       // so, return the triple.
450       if (IsOffloadSection(*CurrentSection, OffloadTriple))
451         return OffloadTriple;
452     }
453     return StringRef();
454   }
455
456   void ReadBundleEnd(MemoryBuffer &Input) final {}
457
458   void ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
459     // If the current section has size one, that means that the content we are
460     // interested in is the file itself. Otherwise it is the content of the
461     // section.
462     //
463     // TODO: Instead of copying the input file as is, deactivate the section
464     // that is no longer needed.
465
466     StringRef Content;
467     CurrentSection->getContents(Content);
468
469     if (Content.size() < 2)
470       OS.write(Input.getBufferStart(), Input.getBufferSize());
471     else
472       OS.write(Content.data(), Content.size());
473   }
474
475   void WriteHeader(raw_fd_ostream &OS,
476                    ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) final {
477     assert(HostInputIndex != ~0u && "Host input index not defined.");
478
479     // Record number of inputs.
480     NumberOfInputs = Inputs.size();
481
482     // Create an LLVM module to have the content we need to bundle.
483     auto *M = new Module("clang-offload-bundle", VMContext);
484     M->setTargetTriple(getTriple(TargetNames[HostInputIndex]));
485     AuxModule.reset(M);
486   }
487
488   void WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) final {
489     ++NumberOfProcessedInputs;
490
491     // Record the triple we are using, that will be used to name the section we
492     // will create.
493     CurrentTriple = TargetTriple;
494   }
495
496   bool WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final {
497     assert(NumberOfProcessedInputs <= NumberOfInputs &&
498            "Processing more inputs that actually exist!");
499     assert(HostInputIndex != ~0u && "Host input index not defined.");
500
501     // If this is not the last output, we don't have to do anything.
502     if (NumberOfProcessedInputs != NumberOfInputs)
503       return false;
504
505     // Create the bitcode file name to write the resulting code to. Keep it if
506     // save-temps is active.
507     SmallString<128> BitcodeFileName;
508     if (sys::fs::createTemporaryFile("clang-offload-bundler", "bc",
509                                      BitcodeFileName)) {
510       errs() << "error: unable to create temporary file.\n";
511       return true;
512     }
513
514     // Dump the contents of the temporary file if that was requested.
515     if (DumpTemporaryFiles) {
516       errs() << ";\n; Object file bundler IR file.\n;\n";
517       AuxModule.get()->print(errs(), nullptr,
518                              /*ShouldPreserveUseListOrder=*/false,
519                              /*IsForDebug=*/true);
520       errs() << '\n';
521     }
522
523     // Find clang in order to create the bundle binary.
524     StringRef Dir = sys::path::parent_path(BundlerExecutable);
525
526     auto ClangBinary = sys::findProgramByName("clang", Dir);
527     if (ClangBinary.getError()) {
528       // Remove bitcode file.
529       sys::fs::remove(BitcodeFileName);
530
531       errs() << "error: unable to find 'clang' in path.\n";
532       return true;
533     }
534
535     // Do the incremental linking. We write to the output file directly. So, we
536     // close it and use the name to pass down to clang.
537     OS.close();
538     SmallString<128> TargetName = getTriple(TargetNames[HostInputIndex]);
539     std::vector<StringRef> ClangArgs = {"clang",
540                                         "-r",
541                                         "-target",
542                                         TargetName.c_str(),
543                                         "-o",
544                                         OutputFileNames.front().c_str(),
545                                         InputFileNames[HostInputIndex].c_str(),
546                                         BitcodeFileName.c_str(),
547                                         "-nostdlib"};
548
549     // If the user asked for the commands to be printed out, we do that instead
550     // of executing it.
551     if (PrintExternalCommands) {
552       errs() << "\"" << ClangBinary.get() << "\"";
553       for (StringRef Arg : ClangArgs)
554         errs() << " \"" << Arg << "\"";
555       errs() << "\n";
556     } else {
557       // Write the bitcode contents to the temporary file.
558       {
559         std::error_code EC;
560         raw_fd_ostream BitcodeFile(BitcodeFileName, EC, sys::fs::F_None);
561         if (EC) {
562           errs() << "error: unable to open temporary file.\n";
563           return true;
564         }
565         WriteBitcodeToFile(*AuxModule, BitcodeFile);
566       }
567
568       bool Failed = sys::ExecuteAndWait(ClangBinary.get(), ClangArgs);
569
570       // Remove bitcode file.
571       sys::fs::remove(BitcodeFileName);
572
573       if (Failed) {
574         errs() << "error: incremental linking by external tool failed.\n";
575         return true;
576       }
577     }
578
579     return false;
580   }
581
582   void WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
583     Module *M = AuxModule.get();
584
585     // Create the new section name, it will consist of the reserved prefix
586     // concatenated with the triple.
587     std::string SectionName = OFFLOAD_BUNDLER_MAGIC_STR;
588     SectionName += CurrentTriple;
589
590     // Create the constant with the content of the section. For the input we are
591     // bundling into (the host input), this is just a place-holder, so a single
592     // byte is sufficient.
593     assert(HostInputIndex != ~0u && "Host input index undefined??");
594     Constant *Content;
595     if (NumberOfProcessedInputs == HostInputIndex + 1) {
596       uint8_t Byte[] = {0};
597       Content = ConstantDataArray::get(VMContext, Byte);
598     } else
599       Content = ConstantDataArray::get(
600           VMContext, ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(
601                                            Input.getBufferStart()),
602                                        Input.getBufferSize()));
603
604     // Create the global in the desired section. We don't want these globals in
605     // the symbol table, so we mark them private.
606     auto *GV = new GlobalVariable(*M, Content->getType(), /*IsConstant=*/true,
607                                   GlobalVariable::PrivateLinkage, Content);
608     GV->setSection(SectionName);
609   }
610 };
611
612 /// Handler for text files. The bundled file will have the following format.
613 ///
614 /// "Comment OFFLOAD_BUNDLER_MAGIC_STR__START__ triple"
615 /// Bundle 1
616 /// "Comment OFFLOAD_BUNDLER_MAGIC_STR__END__ triple"
617 /// ...
618 /// "Comment OFFLOAD_BUNDLER_MAGIC_STR__START__ triple"
619 /// Bundle N
620 /// "Comment OFFLOAD_BUNDLER_MAGIC_STR__END__ triple"
621 class TextFileHandler final : public FileHandler {
622   /// String that begins a line comment.
623   StringRef Comment;
624
625   /// String that initiates a bundle.
626   std::string BundleStartString;
627
628   /// String that closes a bundle.
629   std::string BundleEndString;
630
631   /// Number of chars read from input.
632   size_t ReadChars = 0u;
633
634 protected:
635   void ReadHeader(MemoryBuffer &Input) final {}
636
637   StringRef ReadBundleStart(MemoryBuffer &Input) final {
638     StringRef FC = Input.getBuffer();
639
640     // Find start of the bundle.
641     ReadChars = FC.find(BundleStartString, ReadChars);
642     if (ReadChars == FC.npos)
643       return StringRef();
644
645     // Get position of the triple.
646     size_t TripleStart = ReadChars = ReadChars + BundleStartString.size();
647
648     // Get position that closes the triple.
649     size_t TripleEnd = ReadChars = FC.find("\n", ReadChars);
650     if (TripleEnd == FC.npos)
651       return StringRef();
652
653     // Next time we read after the new line.
654     ++ReadChars;
655
656     return StringRef(&FC.data()[TripleStart], TripleEnd - TripleStart);
657   }
658
659   void ReadBundleEnd(MemoryBuffer &Input) final {
660     StringRef FC = Input.getBuffer();
661
662     // Read up to the next new line.
663     assert(FC[ReadChars] == '\n' && "The bundle should end with a new line.");
664
665     size_t TripleEnd = ReadChars = FC.find("\n", ReadChars + 1);
666     if (TripleEnd == FC.npos)
667       return;
668
669     // Next time we read after the new line.
670     ++ReadChars;
671   }
672
673   void ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
674     StringRef FC = Input.getBuffer();
675     size_t BundleStart = ReadChars;
676
677     // Find end of the bundle.
678     size_t BundleEnd = ReadChars = FC.find(BundleEndString, ReadChars);
679
680     StringRef Bundle(&FC.data()[BundleStart], BundleEnd - BundleStart);
681     OS << Bundle;
682   }
683
684   void WriteHeader(raw_fd_ostream &OS,
685                    ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) final {}
686
687   void WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) final {
688     OS << BundleStartString << TargetTriple << "\n";
689   }
690
691   bool WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final {
692     OS << BundleEndString << TargetTriple << "\n";
693     return false;
694   }
695
696   void WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
697     OS << Input.getBuffer();
698   }
699
700 public:
701   TextFileHandler(StringRef Comment)
702       : FileHandler(), Comment(Comment), ReadChars(0) {
703     BundleStartString =
704         "\n" + Comment.str() + " " OFFLOAD_BUNDLER_MAGIC_STR "__START__ ";
705     BundleEndString =
706         "\n" + Comment.str() + " " OFFLOAD_BUNDLER_MAGIC_STR "__END__ ";
707   }
708 };
709
710 /// Return an appropriate object file handler. We use the specific object
711 /// handler if we know how to deal with that format, otherwise we use a default
712 /// binary file handler.
713 static FileHandler *CreateObjectFileHandler(MemoryBuffer &FirstInput) {
714   // Check if the input file format is one that we know how to deal with.
715   Expected<std::unique_ptr<Binary>> BinaryOrErr = createBinary(FirstInput);
716
717   // Failed to open the input as a known binary. Use the default binary handler.
718   if (!BinaryOrErr) {
719     // We don't really care about the error (we just consume it), if we could
720     // not get a valid device binary object we use the default binary handler.
721     consumeError(BinaryOrErr.takeError());
722     return new BinaryFileHandler();
723   }
724
725   // We only support regular object files. If this is not an object file,
726   // default to the binary handler. The handler will be owned by the client of
727   // this function.
728   std::unique_ptr<ObjectFile> Obj(
729       dyn_cast<ObjectFile>(BinaryOrErr.get().release()));
730
731   if (!Obj)
732     return new BinaryFileHandler();
733
734   return new ObjectFileHandler(std::move(Obj));
735 }
736
737 /// Return an appropriate handler given the input files and options.
738 static FileHandler *CreateFileHandler(MemoryBuffer &FirstInput) {
739   if (FilesType == "i")
740     return new TextFileHandler(/*Comment=*/"//");
741   if (FilesType == "ii")
742     return new TextFileHandler(/*Comment=*/"//");
743   if (FilesType == "ll")
744     return new TextFileHandler(/*Comment=*/";");
745   if (FilesType == "bc")
746     return new BinaryFileHandler();
747   if (FilesType == "s")
748     return new TextFileHandler(/*Comment=*/"#");
749   if (FilesType == "o")
750     return CreateObjectFileHandler(FirstInput);
751   if (FilesType == "gch")
752     return new BinaryFileHandler();
753   if (FilesType == "ast")
754     return new BinaryFileHandler();
755
756   errs() << "error: invalid file type specified.\n";
757   return nullptr;
758 }
759
760 /// Bundle the files. Return true if an error was found.
761 static bool BundleFiles() {
762   std::error_code EC;
763
764   // Create output file.
765   raw_fd_ostream OutputFile(OutputFileNames.front(), EC, sys::fs::F_None);
766
767   if (EC) {
768     errs() << "error: Can't open file " << OutputFileNames.front() << ".\n";
769     return true;
770   }
771
772   // Open input files.
773   std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers(
774       InputFileNames.size());
775
776   unsigned Idx = 0;
777   for (auto &I : InputFileNames) {
778     ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
779         MemoryBuffer::getFileOrSTDIN(I);
780     if (std::error_code EC = CodeOrErr.getError()) {
781       errs() << "error: Can't open file " << I << ": " << EC.message() << "\n";
782       return true;
783     }
784     InputBuffers[Idx++] = std::move(CodeOrErr.get());
785   }
786
787   // Get the file handler. We use the host buffer as reference.
788   assert(HostInputIndex != ~0u && "Host input index undefined??");
789   std::unique_ptr<FileHandler> FH;
790   FH.reset(CreateFileHandler(*InputBuffers[HostInputIndex].get()));
791
792   // Quit if we don't have a handler.
793   if (!FH.get())
794     return true;
795
796   // Write header.
797   FH.get()->WriteHeader(OutputFile, InputBuffers);
798
799   // Write all bundles along with the start/end markers. If an error was found
800   // writing the end of the bundle component, abort the bundle writing.
801   auto Input = InputBuffers.begin();
802   for (auto &Triple : TargetNames) {
803     FH.get()->WriteBundleStart(OutputFile, Triple);
804     FH.get()->WriteBundle(OutputFile, *Input->get());
805     if (FH.get()->WriteBundleEnd(OutputFile, Triple))
806       return true;
807     ++Input;
808   }
809   return false;
810 }
811
812 // Unbundle the files. Return true if an error was found.
813 static bool UnbundleFiles() {
814   // Open Input file.
815   ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
816       MemoryBuffer::getFileOrSTDIN(InputFileNames.front());
817   if (std::error_code EC = CodeOrErr.getError()) {
818     errs() << "error: Can't open file " << InputFileNames.front() << ": "
819            << EC.message() << "\n";
820     return true;
821   }
822
823   MemoryBuffer &Input = *CodeOrErr.get();
824
825   // Select the right files handler.
826   std::unique_ptr<FileHandler> FH;
827   FH.reset(CreateFileHandler(Input));
828
829   // Quit if we don't have a handler.
830   if (!FH.get())
831     return true;
832
833   // Read the header of the bundled file.
834   FH.get()->ReadHeader(Input);
835
836   // Create a work list that consist of the map triple/output file.
837   StringMap<StringRef> Worklist;
838   auto Output = OutputFileNames.begin();
839   for (auto &Triple : TargetNames) {
840     Worklist[Triple] = *Output;
841     ++Output;
842   }
843
844   // Read all the bundles that are in the work list. If we find no bundles we
845   // assume the file is meant for the host target.
846   bool FoundHostBundle = false;
847   while (!Worklist.empty()) {
848     StringRef CurTriple = FH.get()->ReadBundleStart(Input);
849
850     // We don't have more bundles.
851     if (CurTriple.empty())
852       break;
853
854     auto Output = Worklist.find(CurTriple);
855     // The file may have more bundles for other targets, that we don't care
856     // about. Therefore, move on to the next triple
857     if (Output == Worklist.end()) {
858       continue;
859     }
860
861     // Check if the output file can be opened and copy the bundle to it.
862     std::error_code EC;
863     raw_fd_ostream OutputFile(Output->second, EC, sys::fs::F_None);
864     if (EC) {
865       errs() << "error: Can't open file " << Output->second << ": "
866              << EC.message() << "\n";
867       return true;
868     }
869     FH.get()->ReadBundle(OutputFile, Input);
870     FH.get()->ReadBundleEnd(Input);
871     Worklist.erase(Output);
872
873     // Record if we found the host bundle.
874     if (hasHostKind(CurTriple))
875       FoundHostBundle = true;
876   }
877
878   // If no bundles were found, assume the input file is the host bundle and
879   // create empty files for the remaining targets.
880   if (Worklist.size() == TargetNames.size()) {
881     for (auto &E : Worklist) {
882       std::error_code EC;
883       raw_fd_ostream OutputFile(E.second, EC, sys::fs::F_None);
884       if (EC) {
885         errs() << "error: Can't open file " << E.second << ": " << EC.message()
886                << "\n";
887         return true;
888       }
889
890       // If this entry has a host kind, copy the input file to the output file.
891       if (hasHostKind(E.first()))
892         OutputFile.write(Input.getBufferStart(), Input.getBufferSize());
893     }
894     return false;
895   }
896
897   // If we found elements, we emit an error if none of those were for the host.
898   if (!FoundHostBundle) {
899     errs() << "error: Can't find bundle for the host target\n";
900     return true;
901   }
902
903   // If we still have any elements in the worklist, create empty files for them.
904   for (auto &E : Worklist) {
905     std::error_code EC;
906     raw_fd_ostream OutputFile(E.second, EC, sys::fs::F_None);
907     if (EC) {
908       errs() << "error: Can't open file " << E.second << ": "  << EC.message()
909              << "\n";
910       return true;
911     }
912   }
913
914   return false;
915 }
916
917 static void PrintVersion(raw_ostream &OS) {
918   OS << clang::getClangToolFullVersion("clang-offload-bundler") << '\n';
919 }
920
921 int main(int argc, const char **argv) {
922   sys::PrintStackTraceOnErrorSignal(argv[0]);
923
924   cl::HideUnrelatedOptions(ClangOffloadBundlerCategory);
925   cl::SetVersionPrinter(PrintVersion);
926   cl::ParseCommandLineOptions(
927       argc, argv,
928       "A tool to bundle several input files of the specified type <type> \n"
929       "referring to the same source file but different targets into a single \n"
930       "one. The resulting file can also be unbundled into different files by \n"
931       "this tool if -unbundle is provided.\n");
932
933   if (Help) {
934     cl::PrintHelpMessage();
935     return 0;
936   }
937
938   bool Error = false;
939   if (Unbundle) {
940     if (InputFileNames.size() != 1) {
941       Error = true;
942       errs() << "error: only one input file supported in unbundling mode.\n";
943     }
944     if (OutputFileNames.size() != TargetNames.size()) {
945       Error = true;
946       errs() << "error: number of output files and targets should match in "
947                 "unbundling mode.\n";
948     }
949   } else {
950     if (OutputFileNames.size() != 1) {
951       Error = true;
952       errs() << "error: only one output file supported in bundling mode.\n";
953     }
954     if (InputFileNames.size() != TargetNames.size()) {
955       Error = true;
956       errs() << "error: number of input files and targets should match in "
957                 "bundling mode.\n";
958     }
959   }
960
961   // Verify that the offload kinds and triples are known. We also check that we
962   // have exactly one host target.
963   unsigned Index = 0u;
964   unsigned HostTargetNum = 0u;
965   for (StringRef Target : TargetNames) {
966     StringRef Kind;
967     StringRef Triple;
968     getOffloadKindAndTriple(Target, Kind, Triple);
969
970     bool KindIsValid = !Kind.empty();
971     KindIsValid = KindIsValid && StringSwitch<bool>(Kind)
972                                      .Case("host", true)
973                                      .Case("openmp", true)
974                                      .Case("hip", true)
975                                      .Default(false);
976
977     bool TripleIsValid = !Triple.empty();
978     llvm::Triple T(Triple);
979     TripleIsValid &= T.getArch() != Triple::UnknownArch;
980
981     if (!KindIsValid || !TripleIsValid) {
982       Error = true;
983       errs() << "error: invalid target '" << Target << "'";
984
985       if (!KindIsValid)
986         errs() << ", unknown offloading kind '" << Kind << "'";
987       if (!TripleIsValid)
988         errs() << ", unknown target triple '" << Triple << "'";
989       errs() << ".\n";
990     }
991
992     if (KindIsValid && Kind == "host") {
993       ++HostTargetNum;
994       // Save the index of the input that refers to the host.
995       HostInputIndex = Index;
996     }
997
998     ++Index;
999   }
1000
1001   if (HostTargetNum != 1) {
1002     Error = true;
1003     errs() << "error: expecting exactly one host target but got "
1004            << HostTargetNum << ".\n";
1005   }
1006
1007   if (Error)
1008     return 1;
1009
1010   // Save the current executable directory as it will be useful to find other
1011   // tools.
1012   BundlerExecutable = sys::fs::getMainExecutable(argv[0], &BundlerExecutable);
1013
1014   return Unbundle ? UnbundleFiles() : BundleFiles();
1015 }