ClangOffloadBundler.cpp 51 KB

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