21#include "llvm/ADT/ArrayRef.h"
22#include "llvm/ADT/SmallString.h"
23#include "llvm/ADT/SmallVector.h"
24#include "llvm/ADT/StringMap.h"
25#include "llvm/ADT/StringRef.h"
26#include "llvm/Object/Archive.h"
27#include "llvm/Object/ArchiveWriter.h"
28#include "llvm/Object/Binary.h"
29#include "llvm/Object/ObjectFile.h"
30#include "llvm/Support/Casting.h"
31#include "llvm/Support/Debug.h"
32#include "llvm/Support/EndianStream.h"
33#include "llvm/Support/Errc.h"
34#include "llvm/Support/Error.h"
35#include "llvm/Support/ErrorOr.h"
36#include "llvm/Support/FileSystem.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 "llvm/TargetParser/Host.h"
45#include "llvm/TargetParser/Triple.h"
50#include <forward_list>
54#include <system_error>
58using namespace llvm::object;
62#define OFFLOAD_BUNDLER_MAGIC_STR "__CLANG_OFFLOAD_BUNDLE__"
69 auto TargetFeatures =
Target.split(
':');
70 auto TripleOrGPU = TargetFeatures.first.rsplit(
'-');
73 auto KindTriple = TripleOrGPU.first.split(
'-');
77 llvm::Triple t = llvm::Triple(KindTriple.second);
78 this->
Triple = llvm::Triple(t.getArchName(), t.getVendorName(),
79 t.getOSName(), t.getEnvironmentName());
83 auto KindTriple = TargetFeatures.first.split(
'-');
87 llvm::Triple t = llvm::Triple(KindTriple.second);
88 this->
Triple = llvm::Triple(t.getArchName(), t.getVendorName(),
89 t.getOSName(), t.getEnvironmentName());
105 const StringRef TargetOffloadKind)
const {
109 bool HIPCompatibleWithOpenMP =
OffloadKind.starts_with_insensitive(
"hip") &&
110 TargetOffloadKind ==
"openmp";
111 bool OpenMPCompatibleWithHIP =
113 TargetOffloadKind.starts_with_insensitive(
"hip");
114 return HIPCompatibleWithOpenMP || OpenMPCompatibleWithHIP;
120 return !
Triple.str().empty() &&
Triple.getArch() != Triple::UnknownArch;
133 StringRef BundleFileName) {
134 if (Device.contains(
"gfx"))
136 if (Device.contains(
"sm_"))
138 return sys::path::extension(BundleFileName);
143 StringRef LibName = sys::path::stem(BundleFileName);
160 DEBUG_WITH_TYPE(
"CodeObjectCompatibility",
161 dbgs() <<
"Compatible: Exact match: \t[CodeObject: "
162 << CodeObjectInfo.
str()
163 <<
"]\t:\t[Target: " <<
TargetInfo.str() <<
"]\n");
171 "CodeObjectCompatibility",
172 dbgs() <<
"Incompatible: Kind/Triple mismatch \t[CodeObject: "
173 << CodeObjectInfo.
str() <<
"]\t:\t[Target: " <<
TargetInfo.str()
182 "CodeObjectCompatibility",
183 dbgs() <<
"Incompatible: target IDs are incompatible \t[CodeObject: "
184 << CodeObjectInfo.
str() <<
"]\t:\t[Target: " <<
TargetInfo.str()
190 "CodeObjectCompatibility",
191 dbgs() <<
"Compatible: Code Objects are compatible \t[CodeObject: "
192 << CodeObjectInfo.
str() <<
"]\t:\t[Target: " <<
TargetInfo.str()
207 virtual ~FileHandler() {}
211 virtual Error ReadHeader(MemoryBuffer &Input) = 0;
217 ReadBundleStart(MemoryBuffer &Input) = 0;
220 virtual Error ReadBundleEnd(MemoryBuffer &Input) = 0;
223 virtual Error ReadBundle(raw_ostream &OS, MemoryBuffer &Input) = 0;
227 virtual Error WriteHeader(raw_fd_ostream &OS,
228 ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) = 0;
232 virtual Error WriteBundleStart(raw_fd_ostream &OS,
233 StringRef TargetTriple) = 0;
237 virtual Error WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) = 0;
240 virtual Error WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) = 0;
243 virtual Error listBundleIDs(MemoryBuffer &Input) {
244 if (Error Err = ReadHeader(Input))
246 return forEachBundle(Input, [&](
const BundleInfo &Info) -> Error {
247 llvm::outs() << Info.BundleID <<
'\n';
248 Error Err = listBundleIDsCallback(Input, Info);
251 return Error::success();
256 Error forEachBundle(MemoryBuffer &Input,
257 std::function<
Error(
const BundleInfo &)> Func) {
260 ReadBundleStart(Input);
262 return CurTripleOrErr.takeError();
265 if (!*CurTripleOrErr)
268 StringRef CurTriple = **CurTripleOrErr;
269 assert(!CurTriple.empty());
271 BundleInfo Info{CurTriple};
272 if (Error Err = Func(Info))
275 return Error::success();
279 virtual Error listBundleIDsCallback(MemoryBuffer &Input,
280 const BundleInfo &Info) {
281 return Error::success();
309static uint64_t Read8byteIntegerFromBuffer(StringRef Buffer,
size_t pos) {
310 return llvm::support::endian::read64le(Buffer.data() + pos);
314static void Write8byteIntegerToBuffer(raw_fd_ostream &OS, uint64_t Val) {
315 llvm::support::endian::write(OS, Val, llvm::support::little);
318class BinaryFileHandler final :
public FileHandler {
320 struct BinaryBundleInfo final :
public BundleInfo {
326 BinaryBundleInfo() {}
327 BinaryBundleInfo(uint64_t Size, uint64_t Offset)
332 StringMap<BinaryBundleInfo> BundlesInfo;
335 StringMap<BinaryBundleInfo>::iterator CurBundleInfo;
336 StringMap<BinaryBundleInfo>::iterator NextBundleInfo;
339 std::string CurWriteBundleTarget;
348 ~BinaryFileHandler() final {}
350 Error ReadHeader(MemoryBuffer &Input)
final {
351 StringRef FC = Input.getBuffer();
354 CurBundleInfo = BundlesInfo.end();
358 if (ReadChars > FC.size())
359 return Error::success();
364 return Error::success();
367 if (ReadChars + 8 > FC.size())
368 return Error::success();
370 uint64_t NumberOfBundles = Read8byteIntegerFromBuffer(FC, ReadChars);
374 for (uint64_t i = 0; i < NumberOfBundles; ++i) {
377 if (ReadChars + 8 > FC.size())
378 return Error::success();
380 uint64_t Offset = Read8byteIntegerFromBuffer(FC, ReadChars);
384 if (ReadChars + 8 > FC.size())
385 return Error::success();
387 uint64_t Size = Read8byteIntegerFromBuffer(FC, ReadChars);
391 if (ReadChars + 8 > FC.size())
392 return Error::success();
394 uint64_t TripleSize = Read8byteIntegerFromBuffer(FC, ReadChars);
398 if (ReadChars + TripleSize > FC.size())
399 return Error::success();
401 StringRef Triple(&FC.data()[ReadChars], TripleSize);
402 ReadChars += TripleSize;
405 if (!Offset || Offset + Size > FC.size())
406 return Error::success();
408 assert(!BundlesInfo.contains(Triple) &&
"Triple is duplicated??");
409 BundlesInfo[Triple] = BinaryBundleInfo(Size, Offset);
412 CurBundleInfo = BundlesInfo.end();
413 NextBundleInfo = BundlesInfo.begin();
414 return Error::success();
418 ReadBundleStart(MemoryBuffer &Input)
final {
419 if (NextBundleInfo == BundlesInfo.end())
421 CurBundleInfo = NextBundleInfo++;
422 return CurBundleInfo->first();
425 Error ReadBundleEnd(MemoryBuffer &Input)
final {
426 assert(CurBundleInfo != BundlesInfo.end() &&
"Invalid reader info!");
427 return Error::success();
430 Error ReadBundle(raw_ostream &OS, MemoryBuffer &Input)
final {
431 assert(CurBundleInfo != BundlesInfo.end() &&
"Invalid reader info!");
432 StringRef FC = Input.getBuffer();
433 OS.write(FC.data() + CurBundleInfo->second.Offset,
434 CurBundleInfo->second.Size);
435 return Error::success();
438 Error WriteHeader(raw_fd_ostream &OS,
439 ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs)
final {
449 HeaderSize += T.size();
455 Write8byteIntegerToBuffer(OS, BundlerConfig.
TargetNames.size());
459 MemoryBuffer &MB = *Inputs[Idx++];
462 Write8byteIntegerToBuffer(OS, HeaderSize);
464 Write8byteIntegerToBuffer(OS, MB.getBufferSize());
465 BundlesInfo[T] = BinaryBundleInfo(MB.getBufferSize(), HeaderSize);
466 HeaderSize += MB.getBufferSize();
468 Write8byteIntegerToBuffer(OS, T.size());
472 return Error::success();
475 Error WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple)
final {
476 CurWriteBundleTarget = TargetTriple.str();
477 return Error::success();
480 Error WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple)
final {
481 return Error::success();
484 Error WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input)
final {
485 auto BI = BundlesInfo[CurWriteBundleTarget];
487 OS.write(Input.getBufferStart(), Input.getBufferSize());
488 return Error::success();
494class TempFileHandlerRAII {
496 ~TempFileHandlerRAII() {
497 for (
const auto &
File : Files)
498 sys::fs::remove(
File);
504 if (std::error_code EC =
505 sys::fs::createTemporaryFile(
"clang-offload-bundler",
"tmp",
File))
506 return createFileError(
File, EC);
507 Files.push_front(
File);
511 raw_fd_ostream OS(
File, EC);
513 return createFileError(
File, EC);
514 OS.write(Contents->data(), Contents->size());
516 return Files.front().str();
520 std::forward_list<SmallString<128u>> Files;
527class ObjectFileHandler final :
public FileHandler {
530 std::unique_ptr<ObjectFile> Obj;
533 StringRef getInputFileContents()
const {
return Obj->getData(); }
538 IsOffloadSection(SectionRef CurSection) {
541 return NameOrErr.takeError();
552 unsigned NumberOfInputs = 0;
556 unsigned NumberOfProcessedInputs = 0;
559 section_iterator CurrentSection;
560 section_iterator NextSection;
567 ObjectFileHandler(std::unique_ptr<ObjectFile> ObjIn,
569 : Obj(
std::move(ObjIn)), CurrentSection(Obj->section_begin()),
570 NextSection(Obj->section_begin()), BundlerConfig(BC) {}
572 ~ObjectFileHandler() final {}
574 Error ReadHeader(MemoryBuffer &Input)
final {
return Error::success(); }
577 ReadBundleStart(MemoryBuffer &Input)
final {
578 while (NextSection != Obj->section_end()) {
579 CurrentSection = NextSection;
585 IsOffloadSection(*CurrentSection);
587 return TripleOrErr.takeError();
589 return **TripleOrErr;
594 Error ReadBundleEnd(MemoryBuffer &Input)
final {
return Error::success(); }
596 Error ReadBundle(raw_ostream &OS, MemoryBuffer &Input)
final {
599 return ContentOrErr.takeError();
600 StringRef Content = *ContentOrErr;
603 if (Content.size() == 1u && Content.front() == 0)
604 Content = StringRef(Input.getBufferStart(), Input.getBufferSize());
606 OS.write(Content.data(), Content.size());
607 return Error::success();
610 Error WriteHeader(raw_fd_ostream &OS,
611 ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs)
final {
613 "Host input index not defined.");
616 NumberOfInputs = Inputs.size();
617 return Error::success();
620 Error WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple)
final {
621 ++NumberOfProcessedInputs;
622 return Error::success();
625 Error WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple)
final {
626 assert(NumberOfProcessedInputs <= NumberOfInputs &&
627 "Processing more inputs that actually exist!");
629 "Host input index not defined.");
632 if (NumberOfProcessedInputs != NumberOfInputs)
633 return Error::success();
641 "llvm-objcopy path not specified");
648 TempFileHandlerRAII TempFiles;
652 BumpPtrAllocator Alloc;
653 StringSaver SS{Alloc};
656 for (
unsigned I = 0; I < NumberOfInputs; ++I) {
665 return TempFileOrErr.takeError();
666 InputFile = *TempFileOrErr;
669 ObjcopyArgs.push_back(
672 ObjcopyArgs.push_back(
674 BundlerConfig.
TargetNames[I] +
"=readonly,exclude"));
676 ObjcopyArgs.push_back(
"--");
677 ObjcopyArgs.push_back(
681 if (Error Err = executeObjcopy(BundlerConfig.
ObjcopyPath, ObjcopyArgs))
684 return Error::success();
687 Error WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input)
final {
688 return Error::success();
696 errs() <<
"\"" << Objcopy <<
"\"";
697 for (StringRef Arg : drop_begin(Args, 1))
698 errs() <<
" \"" << Arg <<
"\"";
701 if (sys::ExecuteAndWait(Objcopy, Args))
702 return createStringError(inconvertibleErrorCode(),
703 "'llvm-objcopy' tool failed");
705 return Error::success();
718class TextFileHandler final :
public FileHandler {
723 std::string BundleStartString;
726 std::string BundleEndString;
729 size_t ReadChars = 0u;
732 Error ReadHeader(MemoryBuffer &Input)
final {
return Error::success(); }
735 ReadBundleStart(MemoryBuffer &Input)
final {
736 StringRef FC = Input.getBuffer();
739 ReadChars = FC.find(BundleStartString, ReadChars);
740 if (ReadChars == FC.npos)
744 size_t TripleStart = ReadChars = ReadChars + BundleStartString.size();
747 size_t TripleEnd = ReadChars = FC.find(
"\n", ReadChars);
748 if (TripleEnd == FC.npos)
754 return StringRef(&FC.data()[TripleStart], TripleEnd - TripleStart);
757 Error ReadBundleEnd(MemoryBuffer &Input)
final {
758 StringRef FC = Input.getBuffer();
761 assert(FC[ReadChars] ==
'\n' &&
"The bundle should end with a new line.");
763 size_t TripleEnd = ReadChars = FC.find(
"\n", ReadChars + 1);
764 if (TripleEnd != FC.npos)
768 return Error::success();
771 Error ReadBundle(raw_ostream &OS, MemoryBuffer &Input)
final {
772 StringRef FC = Input.getBuffer();
773 size_t BundleStart = ReadChars;
776 size_t BundleEnd = ReadChars = FC.find(BundleEndString, ReadChars);
778 StringRef Bundle(&FC.data()[BundleStart], BundleEnd - BundleStart);
781 return Error::success();
784 Error WriteHeader(raw_fd_ostream &OS,
785 ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs)
final {
786 return Error::success();
789 Error WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple)
final {
790 OS << BundleStartString << TargetTriple <<
"\n";
791 return Error::success();
794 Error WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple)
final {
795 OS << BundleEndString << TargetTriple <<
"\n";
796 return Error::success();
799 Error WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input)
final {
800 OS << Input.getBuffer();
801 return Error::success();
805 TextFileHandler(StringRef Comment) : Comment(Comment), ReadChars(0) {
812 Error listBundleIDsCallback(MemoryBuffer &Input,
813 const BundleInfo &Info)
final {
818 ReadChars = Input.getBuffer().find(BundleEndString, ReadChars);
819 if (Error Err = ReadBundleEnd(Input))
821 return Error::success();
829static std::unique_ptr<FileHandler>
837 if (errorToBool(BinaryOrErr.takeError()) || !isa<ObjectFile>(*BinaryOrErr))
838 return std::make_unique<BinaryFileHandler>(BundlerConfig);
842 return std::make_unique<ObjectFileHandler>(
843 std::unique_ptr<ObjectFile>(cast<ObjectFile>(BinaryOrErr->release())),
851 std::string FilesType = BundlerConfig.
FilesType;
853 if (FilesType ==
"i")
854 return std::make_unique<TextFileHandler>(
"//");
855 if (FilesType ==
"ii")
856 return std::make_unique<TextFileHandler>(
"//");
857 if (FilesType ==
"cui")
858 return std::make_unique<TextFileHandler>(
"//");
859 if (FilesType ==
"hipi")
860 return std::make_unique<TextFileHandler>(
"//");
863 if (FilesType ==
"d")
864 return std::make_unique<TextFileHandler>(
"#");
865 if (FilesType ==
"ll")
866 return std::make_unique<TextFileHandler>(
";");
867 if (FilesType ==
"bc")
868 return std::make_unique<BinaryFileHandler>(BundlerConfig);
869 if (FilesType ==
"s")
870 return std::make_unique<TextFileHandler>(
"#");
871 if (FilesType ==
"o")
873 if (FilesType ==
"a")
875 if (FilesType ==
"gch")
876 return std::make_unique<BinaryFileHandler>(BundlerConfig);
877 if (FilesType ==
"ast")
878 return std::make_unique<BinaryFileHandler>(BundlerConfig);
880 return createStringError(errc::invalid_argument,
881 "'" + FilesType +
"': invalid file type specified");
888 ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
889 MemoryBuffer::getFileOrSTDIN(InputFileName);
890 if (std::error_code EC = CodeOrErr.getError())
891 return createFileError(InputFileName, EC);
893 MemoryBuffer &Input = **CodeOrErr;
898 if (!FileHandlerOrErr)
899 return FileHandlerOrErr.takeError();
901 std::unique_ptr<FileHandler> &FH = *FileHandlerOrErr;
903 return FH->listBundleIDs(Input);
920 ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
921 MemoryBuffer::getFileOrSTDIN(I);
922 if (std::error_code EC = CodeOrErr.getError())
923 return createFileError(I, EC);
924 InputBuffers.emplace_back(std::move(*CodeOrErr));
929 "Host input index undefined??");
934 if (!FileHandlerOrErr)
935 return FileHandlerOrErr.takeError();
937 std::unique_ptr<FileHandler> &FH = *FileHandlerOrErr;
941 if (Error Err = FH->WriteHeader(OutputFile, InputBuffers))
946 auto Input = InputBuffers.begin();
948 if (Error Err = FH->WriteBundleStart(OutputFile, Triple))
950 if (Error Err = FH->WriteBundle(OutputFile, **Input))
952 if (Error Err = FH->WriteBundleEnd(OutputFile, Triple))
956 return Error::success();
962 ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
964 if (std::error_code EC = CodeOrErr.getError())
967 MemoryBuffer &Input = **CodeOrErr;
972 if (!FileHandlerOrErr)
973 return FileHandlerOrErr.takeError();
975 std::unique_ptr<FileHandler> &FH = *FileHandlerOrErr;
979 if (Error Err = FH->ReadHeader(Input))
983 StringMap<StringRef> Worklist;
986 Worklist[Triple] = *Output;
992 bool FoundHostBundle =
false;
993 while (!Worklist.empty()) {
995 FH->ReadBundleStart(Input);
997 return CurTripleOrErr.takeError();
1000 if (!*CurTripleOrErr)
1003 StringRef CurTriple = **CurTripleOrErr;
1004 assert(!CurTriple.empty());
1006 auto Output = Worklist.begin();
1007 for (
auto E = Worklist.end(); Output != E; Output++) {
1015 if (Output == Worklist.end())
1019 raw_fd_ostream OutputFile((*Output).second, EC, sys::fs::OF_None);
1021 return createFileError((*Output).second, EC);
1022 if (Error Err = FH->ReadBundle(OutputFile, Input))
1024 if (Error Err = FH->ReadBundleEnd(Input))
1026 Worklist.erase(Output);
1030 if (OffloadInfo.hasHostKind())
1031 FoundHostBundle =
true;
1035 std::string ErrMsg =
"Can't find bundles for";
1036 std::set<StringRef> Sorted;
1037 for (
auto &E : Worklist)
1038 Sorted.insert(E.first());
1040 unsigned Last = Sorted.size() - 1;
1041 for (
auto &E : Sorted) {
1042 if (I != 0 &&
Last > 1)
1045 if (I ==
Last && I != 0)
1050 return createStringError(inconvertibleErrorCode(), ErrMsg);
1056 for (
auto &E : Worklist) {
1058 raw_fd_ostream OutputFile(E.second, EC, sys::fs::OF_None);
1060 return createFileError(E.second, EC);
1064 if (OffloadInfo.hasHostKind())
1065 OutputFile.write(Input.getBufferStart(), Input.getBufferSize());
1067 return Error::success();
1074 return createStringError(inconvertibleErrorCode(),
1075 "Can't find bundle for the host target");
1078 for (
auto &E : Worklist) {
1080 raw_fd_ostream OutputFile(E.second, EC, sys::fs::OF_None);
1082 return createFileError(E.second, EC);
1085 return Error::success();
1089 return Triple(sys::getDefaultTargetTriple()).isOSDarwin() ? Archive::K_DARWIN
1103 if (!CompatibleTargets.empty()) {
1104 DEBUG_WITH_TYPE(
"CodeObjectCompatibility",
1105 dbgs() <<
"CompatibleTargets list should be empty\n");
1111 CompatibleTargets.push_back(
Target);
1113 return !CompatibleTargets.empty();
1124 std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;
1128 StringMap<std::vector<NewArchiveMember>> OutputArchivesMap;
1131 StringMap<StringRef> TargetOutputFileNameMap;
1135 TargetOutputFileNameMap[
Target] = *Output;
1141 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
1142 MemoryBuffer::getFileOrSTDIN(IFName,
true,
false);
1143 if (std::error_code EC = BufOrErr.getError())
1146 ArchiveBuffers.push_back(std::move(*BufOrErr));
1148 Archive::create(ArchiveBuffers.back()->getMemBufferRef());
1150 return LibOrErr.takeError();
1152 auto Archive = std::move(*LibOrErr);
1154 Error ArchiveErr = Error::success();
1155 auto ChildEnd = Archive->child_end();
1158 for (
auto ArchiveIter = Archive->child_begin(ArchiveErr);
1159 ArchiveIter != ChildEnd; ++ArchiveIter) {
1162 auto ArchiveChildNameOrErr = (*ArchiveIter).getName();
1163 if (!ArchiveChildNameOrErr)
1164 return ArchiveChildNameOrErr.takeError();
1166 StringRef BundledObjectFile = sys::path::filename(*ArchiveChildNameOrErr);
1168 auto CodeObjectBufferRefOrErr = (*ArchiveIter).getMemoryBufferRef();
1169 if (!CodeObjectBufferRefOrErr)
1170 return CodeObjectBufferRefOrErr.takeError();
1172 auto CodeObjectBuffer =
1173 MemoryBuffer::getMemBuffer(*CodeObjectBufferRefOrErr,
false);
1177 if (!FileHandlerOrErr)
1178 return FileHandlerOrErr.takeError();
1180 std::unique_ptr<FileHandler> &FileHandler = *FileHandlerOrErr;
1181 assert(FileHandler &&
1182 "FileHandle creation failed for file in the archive!");
1184 if (Error ReadErr = FileHandler->ReadHeader(*CodeObjectBuffer))
1188 FileHandler->ReadBundleStart(*CodeObjectBuffer);
1189 if (!CurBundleIDOrErr)
1190 return CurBundleIDOrErr.takeError();
1192 std::optional<StringRef> OptionalCurBundleID = *CurBundleIDOrErr;
1194 if (!OptionalCurBundleID)
1196 StringRef CodeObject = *OptionalCurBundleID;
1200 while (!CodeObject.empty()) {
1203 if (CodeObjectInfo.hasHostKind()) {
1207 std::string BundleData;
1208 raw_string_ostream DataStream(BundleData);
1209 if (Error Err = FileHandler->ReadBundle(DataStream, *CodeObjectBuffer))
1212 for (
auto &CompatibleTarget : CompatibleTargets) {
1214 BundledObjectFileName.assign(BundledObjectFile);
1215 auto OutputBundleName =
1216 Twine(llvm::sys::path::stem(BundledObjectFileName) +
"-" +
1219 CodeObjectInfo.TargetID))
1223 std::replace(OutputBundleName.begin(), OutputBundleName.end(),
':',
1226 std::unique_ptr<MemoryBuffer> MemBuf = MemoryBuffer::getMemBufferCopy(
1227 DataStream.str(), OutputBundleName);
1228 ArchiveBuffers.push_back(std::move(MemBuf));
1229 llvm::MemoryBufferRef MemBufRef =
1230 MemoryBufferRef(*(ArchiveBuffers.back()));
1234 if (!OutputArchivesMap.contains(CompatibleTarget)) {
1236 std::vector<NewArchiveMember> ArchiveMembers;
1237 ArchiveMembers.push_back(NewArchiveMember(MemBufRef));
1238 OutputArchivesMap.insert_or_assign(CompatibleTarget,
1239 std::move(ArchiveMembers));
1241 OutputArchivesMap[CompatibleTarget].push_back(
1242 NewArchiveMember(MemBufRef));
1247 if (Error Err = FileHandler->ReadBundleEnd(*CodeObjectBuffer))
1251 FileHandler->ReadBundleStart(*CodeObjectBuffer);
1252 if (!NextTripleOrErr)
1253 return NextTripleOrErr.takeError();
1255 CodeObject = ((*NextTripleOrErr).has_value()) ? **NextTripleOrErr :
"";
1259 assert(!ArchiveErr &&
"Error occurred while reading archive!");
1263 StringRef FileName = TargetOutputFileNameMap[
Target];
1264 StringMapIterator<std::vector<llvm::NewArchiveMember>> CurArchiveMembers =
1265 OutputArchivesMap.find(
Target);
1266 if (CurArchiveMembers != OutputArchivesMap.end()) {
1267 if (Error WriteErr = writeArchive(FileName, CurArchiveMembers->getValue(),
1268 SymtabWritingMode::NormalSymtab,
1273 std::string ErrMsg =
1274 Twine(
"no compatible code object found for the target '" +
Target +
1275 "' in heterogeneous archive library: " + IFName)
1277 return createStringError(inconvertibleErrorCode(), ErrMsg);
1282 std::vector<llvm::NewArchiveMember> EmptyArchive;
1283 EmptyArchive.clear();
1284 if (Error WriteErr = writeArchive(
1285 FileName, EmptyArchive, SymtabWritingMode::NormalSymtab,
1291 return Error::success();
static std::string getDeviceLibraryFileName(StringRef BundleFileName, StringRef Device)
static StringRef getDeviceFileExtension(StringRef Device, StringRef BundleFileName)
static Expected< std::unique_ptr< FileHandler > > CreateFileHandler(MemoryBuffer &FirstInput, const OffloadBundlerConfig &BundlerConfig)
Return an appropriate handler given the input files and options.
#define OFFLOAD_BUNDLER_MAGIC_STR
Magic string that marks the existence of offloading data.
bool isCodeObjectCompatible(const OffloadTargetInfo &CodeObjectInfo, const OffloadTargetInfo &TargetInfo)
Checks if a code object CodeObjectInfo is compatible with a given target TargetInfo.
static std::unique_ptr< FileHandler > CreateObjectFileHandler(MemoryBuffer &FirstInput, const OffloadBundlerConfig &BundlerConfig)
Return an appropriate object file handler.
static Archive::Kind getDefaultArchiveKindForHost()
static bool getCompatibleOffloadTargets(OffloadTargetInfo &CodeObjectInfo, SmallVectorImpl< StringRef > &CompatibleTargets, const OffloadBundlerConfig &BundlerConfig)
Computes a list of targets among all given targets which are compatible with this code object.
This file defines an offload bundling API that bundles different files that relate with the same sour...
Defines version macros and version-related utility functions for Clang.
std::vector< std::string > OutputFileNames
std::vector< std::string > TargetNames
std::vector< std::string > InputFileNames
bool PrintExternalCommands
llvm::Error BundleFiles()
Bundle the files. Return true if an error was found.
llvm::Error UnbundleFiles()
llvm::Error UnbundleArchive()
UnbundleArchive takes an archive file (".a") as input containing bundled code object files,...
static llvm::Error ListBundleIDsInFile(llvm::StringRef InputFileName, const OffloadBundlerConfig &BundlerConfig)
const OffloadBundlerConfig & BundlerConfig
Exposes information about the current target.
CudaArch StringToCudaArch(llvm::StringRef S)
bool isCompatibleTargetID(llvm::StringRef Provided, llvm::StringRef Requested)
Check whether the provided target ID is compatible with the requested target ID.
@ Result
The result type of a method or function.
YAML serialization mapping.
Obtain the offload kind, real machine triple, and an optional GPUArch out of the target information s...
bool operator==(const OffloadTargetInfo &Target) const
bool isOffloadKindCompatible(const llvm::StringRef TargetOffloadKind) const
bool isTripleValid() const
OffloadTargetInfo(const llvm::StringRef Target, const OffloadBundlerConfig &BC)
llvm::StringRef OffloadKind
bool isOffloadKindValid() const
const OffloadBundlerConfig & BundlerConfig