llvm::object;
65using namespace clang;
68structCreateClangOffloadBundlerTimerGroup {
70 return newTimerGroup(
"Clang Offload Bundler Timer Group",
71 "Timer group for clang offload bundler");
75staticllvm::ManagedStatic<llvm::TimerGroup,
76CreateClangOffloadBundlerTimerGroup>
80#define OFFLOAD_BUNDLER_MAGIC_STR "__CLANG_OFFLOAD_BUNDLE__" 87 autoTargetFeatures =
Target.split(
':');
88 autoTripleOrGPU = TargetFeatures.first.rsplit(
'-');
92 autoKindTriple = TripleOrGPU.first.split(
'-');
96llvm::Triple t = llvm::Triple(KindTriple.second);
97this->
Triple= llvm::Triple(t.getArchName(), t.getVendorName(),
98t.getOSName(), t.getEnvironmentName());
100this->
TargetID= Target.substr(
Target.find(TripleOrGPU.second));
102 autoKindTriple = TargetFeatures.first.split(
'-');
106llvm::Triple t = llvm::Triple(KindTriple.second);
107this->
Triple= llvm::Triple(t.getArchName(), t.getVendorName(),
108t.getOSName(), t.getEnvironmentName());
124 constStringRef TargetOffloadKind)
const{
126(
OffloadKind==
"hip"&& TargetOffloadKind ==
"hipv4") ||
127(
OffloadKind==
"hipv4"&& TargetOffloadKind ==
"hip"))
131 boolHIPCompatibleWithOpenMP =
OffloadKind.starts_with_insensitive(
"hip") &&
132TargetOffloadKind ==
"openmp";
133 boolOpenMPCompatibleWithHIP =
135TargetOffloadKind.starts_with_insensitive(
"hip");
136 returnHIPCompatibleWithOpenMP || OpenMPCompatibleWithHIP;
142 return!
Triple.str().empty() &&
Triple.getArch() != Triple::UnknownArch;
155StringRef BundleFileName) {
156 if(
Device.contains(
"gfx"))
158 if(
Device.contains(
"sm_"))
160 returnsys::path::extension(BundleFileName);
165StringRef LibName = sys::path::stem(BundleFileName);
184 virtual~FileHandler() {}
188 virtual ErrorReadHeader(MemoryBuffer &Input) = 0;
194ReadBundleStart(MemoryBuffer &Input) = 0;
197 virtual ErrorReadBundleEnd(MemoryBuffer &Input) = 0;
200 virtual ErrorReadBundle(raw_ostream &OS, MemoryBuffer &Input) = 0;
204 virtual ErrorWriteHeader(raw_ostream &OS,
205 ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) = 0;
209 virtual ErrorWriteBundleStart(raw_ostream &OS, StringRef TargetTriple) = 0;
213 virtual ErrorWriteBundleEnd(raw_ostream &OS, StringRef TargetTriple) = 0;
216 virtual ErrorWriteBundle(raw_ostream &OS, MemoryBuffer &Input) = 0;
219 virtual ErrorfinalizeOutputFile() {
returnError::success(); }
222 virtual ErrorlistBundleIDs(MemoryBuffer &Input) {
223 if(Error Err = ReadHeader(Input))
225 returnforEachBundle(Input, [&](
constBundleInfo &Info) -> Error {
226llvm::outs() << Info.BundleID <<
'\n';
227 ErrorErr = listBundleIDsCallback(Input, Info);
230 returnError::success();
235 virtual ErrorgetBundleIDs(MemoryBuffer &Input,
236std::set<StringRef> &BundleIds) {
237 if(Error Err = ReadHeader(Input))
239 returnforEachBundle(Input, [&](
constBundleInfo &Info) -> Error {
240BundleIds.insert(Info.BundleID);
241Error Err = listBundleIDsCallback(Input, Info);
244 returnError::success();
249 ErrorforEachBundle(MemoryBuffer &Input,
250std::function<
Error(
constBundleInfo &)>
Func) {
253ReadBundleStart(Input);
255 returnCurTripleOrErr.takeError();
258 if(!*CurTripleOrErr)
261StringRef CurTriple = **CurTripleOrErr;
262assert(!CurTriple.empty());
264BundleInfo Info{CurTriple};
265 if(Error Err =
Func(Info))
268 returnError::success();
272 virtual ErrorlistBundleIDsCallback(MemoryBuffer &Input,
273 constBundleInfo &Info) {
274 returnError::success();
302static uint64_tRead8byteIntegerFromBuffer(StringRef Buffer,
size_tpos) {
303 returnllvm::support::endian::read64le(Buffer.data() + pos);
307static voidWrite8byteIntegerToBuffer(raw_ostream &OS, uint64_t Val) {
308llvm::support::endian::write(OS, Val, llvm::endianness::little);
311classBinaryFileHandler final :
publicFileHandler {
313 structBinaryBundleInfo final :
publicBundleInfo {
319BinaryBundleInfo() {}
320BinaryBundleInfo(uint64_t Size, uint64_t Offset)
325StringMap<BinaryBundleInfo> BundlesInfo;
328StringMap<BinaryBundleInfo>::iterator CurBundleInfo;
329StringMap<BinaryBundleInfo>::iterator NextBundleInfo;
332std::string CurWriteBundleTarget;
341~BinaryFileHandler() final {}
343 ErrorReadHeader(MemoryBuffer &Input)
final{
344StringRef FC = Input.getBuffer();
347CurBundleInfo = BundlesInfo.end();
351 if(ReadChars > FC.size())
352 returnError::success();
355 if(llvm::identify_magic(FC) != llvm::file_magic::offload_bundle)
356 returnError::success();
359 if(ReadChars + 8 > FC.size())
360 returnError::success();
362 uint64_tNumberOfBundles = Read8byteIntegerFromBuffer(FC, ReadChars);
366 for(uint64_t i = 0; i < NumberOfBundles; ++i) {
369 if(ReadChars + 8 > FC.size())
370 returnError::success();
372 uint64_tOffset = Read8byteIntegerFromBuffer(FC, ReadChars);
376 if(ReadChars + 8 > FC.size())
377 returnError::success();
379 uint64_t Size= Read8byteIntegerFromBuffer(FC, ReadChars);
383 if(ReadChars + 8 > FC.size())
384 returnError::success();
386 uint64_tTripleSize = Read8byteIntegerFromBuffer(FC, ReadChars);
390 if(ReadChars + TripleSize > FC.size())
391 returnError::success();
393StringRef Triple(&FC.data()[ReadChars], TripleSize);
394ReadChars += TripleSize;
397 if(!Offset || Offset + Size > FC.size())
398 returnError::success();
400assert(!BundlesInfo.contains(Triple) &&
"Triple is duplicated??");
401BundlesInfo[Triple] = BinaryBundleInfo(Size, Offset);
404CurBundleInfo = BundlesInfo.end();
405NextBundleInfo = BundlesInfo.begin();
406 returnError::success();
410ReadBundleStart(MemoryBuffer &Input)
final{
411 if(NextBundleInfo == BundlesInfo.end())
413CurBundleInfo = NextBundleInfo++;
414 returnCurBundleInfo->first();
417 ErrorReadBundleEnd(MemoryBuffer &Input)
final{
418assert(CurBundleInfo != BundlesInfo.end() &&
"Invalid reader info!");
419 returnError::success();
422 ErrorReadBundle(raw_ostream &OS, MemoryBuffer &Input)
final{
423assert(CurBundleInfo != BundlesInfo.end() &&
"Invalid reader info!");
424StringRef FC = Input.getBuffer();
425OS.write(FC.data() + CurBundleInfo->second.Offset,
426CurBundleInfo->second.Size);
427 returnError::success();
430 ErrorWriteHeader(raw_ostream &OS,
431 ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs)
final{
441HeaderSize +=
T.size();
447Write8byteIntegerToBuffer(OS, BundlerConfig.
TargetNames.size());
451MemoryBuffer &MB = *Inputs[Idx++];
454Write8byteIntegerToBuffer(OS, HeaderSize);
456Write8byteIntegerToBuffer(OS, MB.getBufferSize());
457BundlesInfo[
T] = BinaryBundleInfo(MB.getBufferSize(), HeaderSize);
458HeaderSize += MB.getBufferSize();
460Write8byteIntegerToBuffer(OS,
T.size());
464 returnError::success();
467 ErrorWriteBundleStart(raw_ostream &OS, StringRef TargetTriple)
final{
468CurWriteBundleTarget = TargetTriple.str();
469 returnError::success();
472 ErrorWriteBundleEnd(raw_ostream &OS, StringRef TargetTriple)
final{
473 returnError::success();
476 ErrorWriteBundle(raw_ostream &OS, MemoryBuffer &Input)
final{
477 autoBI = BundlesInfo[CurWriteBundleTarget];
480 size_tCurrentPos = OS.tell();
481 size_tPaddingSize = BI.Offset > CurrentPos ? BI.Offset - CurrentPos : 0;
482 for(
size_tI = 0; I < PaddingSize; ++I)
484assert(OS.tell() == BI.Offset);
486OS.write(Input.getBufferStart(), Input.getBufferSize());
488 returnError::success();
494classTempFileHandlerRAII {
496~TempFileHandlerRAII() {
497 for(
const auto&
File: Files)
498sys::fs::remove(
File);
504 if(std::error_code EC =
505sys::fs::createTemporaryFile(
"clang-offload-bundler",
"tmp",
File))
506 returncreateFileError(
File, EC);
507Files.push_front(
File);
511raw_fd_ostream OS(
File, EC);
513 returncreateFileError(
File, EC);
514OS.write(Contents->data(), Contents->size());
516 returnFiles.front().str();
520std::forward_list<SmallString<128u>> Files;
527classObjectFileHandler final :
publicFileHandler {
530std::unique_ptr<ObjectFile> Obj;
533StringRef getInputFileContents()
const{
returnObj->getData(); }
538IsOffloadSection(SectionRef CurSection) {
541 returnNameOrErr.takeError();
544 if(llvm::identify_magic(*NameOrErr) != llvm::file_magic::offload_bundle)
552 unsignedNumberOfInputs = 0;
556 unsignedNumberOfProcessedInputs = 0;
559section_iterator CurrentSection;
560section_iterator NextSection;
567ObjectFileHandler(std::unique_ptr<ObjectFile> ObjIn,
569: Obj(
std::move(ObjIn)), CurrentSection(Obj->section_begin()),
570NextSection(Obj->section_begin()), BundlerConfig(BC) {}
572~ObjectFileHandler() final {}
574 ErrorReadHeader(MemoryBuffer &Input)
final{
returnError::success(); }
577ReadBundleStart(MemoryBuffer &Input)
final{
578 while(NextSection != Obj->section_end()) {
579CurrentSection = NextSection;
585IsOffloadSection(*CurrentSection);
587 returnTripleOrErr.takeError();
589 return**TripleOrErr;
594 ErrorReadBundleEnd(MemoryBuffer &Input)
final{
returnError::success(); }
596 ErrorReadBundle(raw_ostream &OS, MemoryBuffer &Input)
final{
599 returnContentOrErr.takeError();
600StringRef Content = *ContentOrErr;
603std::string ModifiedContent;
604 if(Content.size() == 1u && Content.front() == 0) {
605 autoHostBundleOrErr = getHostBundle(
606StringRef(Input.getBufferStart(), Input.getBufferSize()));
607 if(!HostBundleOrErr)
608 returnHostBundleOrErr.takeError();
610ModifiedContent = std::move(*HostBundleOrErr);
611Content = ModifiedContent;
614OS.write(Content.data(), Content.size());
615 returnError::success();
618 ErrorWriteHeader(raw_ostream &OS,
619 ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs)
final{
621 "Host input index not defined.");
624NumberOfInputs = Inputs.size();
625 returnError::success();
628 ErrorWriteBundleStart(raw_ostream &OS, StringRef TargetTriple)
final{
629++NumberOfProcessedInputs;
630 returnError::success();
633 ErrorWriteBundleEnd(raw_ostream &OS, StringRef TargetTriple)
final{
634 returnError::success();
637 ErrorfinalizeOutputFile() final {
638assert(NumberOfProcessedInputs <= NumberOfInputs &&
639 "Processing more inputs that actually exist!");
641 "Host input index not defined.");
644 if(NumberOfProcessedInputs != NumberOfInputs)
645 returnError::success();
653 "llvm-objcopy path not specified");
656TempFileHandlerRAII TempFiles;
660BumpPtrAllocator
Alloc;
661StringSaver SS{
Alloc};
664 for(
unsignedI = 0; I < NumberOfInputs; ++I) {
673 returnTempFileOrErr.takeError();
674InputFile = *TempFileOrErr;
677ObjcopyArgs.push_back(
679BundlerConfig.
TargetNames[I] +
"="+ InputFile));
680ObjcopyArgs.push_back(
682BundlerConfig.
TargetNames[I] +
"=readonly,exclude"));
684ObjcopyArgs.push_back(
"--");
685ObjcopyArgs.push_back(
689 if(Error Err = executeObjcopy(BundlerConfig.
ObjcopyPath, ObjcopyArgs))
692 returnError::success();
695 ErrorWriteBundle(raw_ostream &OS, MemoryBuffer &Input)
final{
696 returnError::success();
704errs() <<
"\""<< Objcopy <<
"\"";
705 for(StringRef Arg : drop_begin(Args, 1))
706errs() <<
" \""<< Arg <<
"\"";
709 if(sys::ExecuteAndWait(Objcopy, Args))
710 returncreateStringError(inconvertibleErrorCode(),
711 "'llvm-objcopy' tool failed");
713 returnError::success();
717TempFileHandlerRAII TempFiles;
719 autoModifiedObjPathOrErr = TempFiles.Create(std::nullopt);
720 if(!ModifiedObjPathOrErr)
721 returnModifiedObjPathOrErr.takeError();
722StringRef ModifiedObjPath = *ModifiedObjPathOrErr;
724BumpPtrAllocator
Alloc;
725StringSaver SS{
Alloc};
728ObjcopyArgs.push_back(
"--regex");
729ObjcopyArgs.push_back(
"--remove-section=__CLANG_OFFLOAD_BUNDLE__.*");
730ObjcopyArgs.push_back(
"--");
732StringRef ObjcopyInputFileName;
739 if(StringRef(BundlerConfig.
FilesType).starts_with(
"a")) {
740 autoInputFileOrErr =
743 returnInputFileOrErr.takeError();
744ObjcopyInputFileName = *InputFileOrErr;
748ObjcopyArgs.push_back(ObjcopyInputFileName);
749ObjcopyArgs.push_back(ModifiedObjPath);
751 if(Error Err = executeObjcopy(BundlerConfig.
ObjcopyPath, ObjcopyArgs))
752 returnstd::move(Err);
754 autoBufOrErr = MemoryBuffer::getFile(ModifiedObjPath);
756 returncreateStringError(BufOrErr.getError(),
757 "Failed to read back the modified object file");
759 returnBufOrErr->get()->getBuffer().str();
772classTextFileHandler final :
publicFileHandler {
777std::string BundleStartString;
780std::string BundleEndString;
783 size_tReadChars = 0u;
786 ErrorReadHeader(MemoryBuffer &Input)
final{
returnError::success(); }
789ReadBundleStart(MemoryBuffer &Input)
final{
790StringRef FC = Input.getBuffer();
793ReadChars = FC.find(BundleStartString, ReadChars);
794 if(ReadChars == FC.npos)
798 size_tTripleStart = ReadChars = ReadChars + BundleStartString.size();
801 size_tTripleEnd = ReadChars = FC.find(
"\n", ReadChars);
802 if(TripleEnd == FC.npos)
808 returnStringRef(&FC.data()[TripleStart], TripleEnd - TripleStart);
811 ErrorReadBundleEnd(MemoryBuffer &Input)
final{
812StringRef FC = Input.getBuffer();
815assert(FC[ReadChars] ==
'\n'&&
"The bundle should end with a new line.");
817 size_tTripleEnd = ReadChars = FC.find(
"\n", ReadChars + 1);
818 if(TripleEnd != FC.npos)
822 returnError::success();
825 ErrorReadBundle(raw_ostream &OS, MemoryBuffer &Input)
final{
826StringRef FC = Input.getBuffer();
827 size_tBundleStart = ReadChars;
830 size_tBundleEnd = ReadChars = FC.find(BundleEndString, ReadChars);
832StringRef Bundle(&FC.data()[BundleStart], BundleEnd - BundleStart);
835 returnError::success();
838 ErrorWriteHeader(raw_ostream &OS,
839 ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs)
final{
840 returnError::success();
843 ErrorWriteBundleStart(raw_ostream &OS, StringRef TargetTriple)
final{
844OS << BundleStartString << TargetTriple <<
"\n";
845 returnError::success();
848 ErrorWriteBundleEnd(raw_ostream &OS, StringRef TargetTriple)
final{
849OS << BundleEndString << TargetTriple <<
"\n";
850 returnError::success();
853 ErrorWriteBundle(raw_ostream &OS, MemoryBuffer &Input)
final{
854OS << Input.getBuffer();
855 returnError::success();
859TextFileHandler(StringRef Comment) : Comment(Comment), ReadChars(0) {
866 ErrorlistBundleIDsCallback(MemoryBuffer &Input,
867 constBundleInfo &Info)
final{
872ReadChars = Input.getBuffer().find(BundleEndString, ReadChars);
873 if(Error Err = ReadBundleEnd(Input))
875 returnError::success();
883staticstd::unique_ptr<FileHandler>
891 if(errorToBool(BinaryOrErr.takeError()) || !isa<ObjectFile>(*BinaryOrErr))
892 returnstd::make_unique<BinaryFileHandler>(BundlerConfig);
896 returnstd::make_unique<ObjectFileHandler>(
897std::unique_ptr<ObjectFile>(cast<ObjectFile>(BinaryOrErr->release())),
905std::string FilesType = BundlerConfig.
FilesType;
907 if(FilesType ==
"i")
908 returnstd::make_unique<TextFileHandler>(
"//");
909 if(FilesType ==
"ii")
910 returnstd::make_unique<TextFileHandler>(
"//");
911 if(FilesType ==
"cui")
912 returnstd::make_unique<TextFileHandler>(
"//");
913 if(FilesType ==
"hipi")
914 returnstd::make_unique<TextFileHandler>(
"//");
917 if(FilesType ==
"d")
918 returnstd::make_unique<TextFileHandler>(
"#");
919 if(FilesType ==
"ll")
920 returnstd::make_unique<TextFileHandler>(
";");
921 if(FilesType ==
"bc")
922 returnstd::make_unique<BinaryFileHandler>(BundlerConfig);
923 if(FilesType ==
"s")
924 returnstd::make_unique<TextFileHandler>(
"#");
925 if(FilesType ==
"o")
927 if(FilesType ==
"a")
929 if(FilesType ==
"gch")
930 returnstd::make_unique<BinaryFileHandler>(BundlerConfig);
931 if(FilesType ==
"ast")
932 returnstd::make_unique<BinaryFileHandler>(BundlerConfig);
934 returncreateStringError(errc::invalid_argument,
935 "'"+ FilesType +
"': invalid file type specified");
940 if(llvm::compression::zstd::isAvailable()) {
945}
else if(llvm::compression::zlib::isAvailable()) {
951 autoIgnoreEnvVarOpt =
952llvm::sys::Process::GetEnv(
"OFFLOAD_BUNDLER_IGNORE_ENV_VAR");
953 if(IgnoreEnvVarOpt.has_value() && IgnoreEnvVarOpt.value() ==
"1")
955 autoVerboseEnvVarOpt = llvm::sys::Process::GetEnv(
"OFFLOAD_BUNDLER_VERBOSE");
956 if(VerboseEnvVarOpt.has_value())
957 Verbose= VerboseEnvVarOpt.value() ==
"1";
958 autoCompressEnvVarOpt =
959llvm::sys::Process::GetEnv(
"OFFLOAD_BUNDLER_COMPRESS");
960 if(CompressEnvVarOpt.has_value())
961 Compress= CompressEnvVarOpt.value() ==
"1";
962 autoCompressionLevelEnvVarOpt =
963llvm::sys::Process::GetEnv(
"OFFLOAD_BUNDLER_COMPRESSION_LEVEL");
964 if(CompressionLevelEnvVarOpt.has_value()) {
965llvm::StringRef CompressionLevelStr = CompressionLevelEnvVarOpt.value();
967 if(!CompressionLevelStr.getAsInteger(10, Level))
971<<
"Warning: Invalid value for OFFLOAD_BUNDLER_COMPRESSION_LEVEL: " 972<< CompressionLevelStr.str() <<
". Ignoring it.\n";
974 autoCompressedBundleFormatVersionOpt =
975llvm::sys::Process::GetEnv(
"COMPRESSED_BUNDLE_FORMAT_VERSION");
976 if(CompressedBundleFormatVersionOpt.has_value()) {
977llvm::StringRef VersionStr = CompressedBundleFormatVersionOpt.value();
979 if(!VersionStr.getAsInteger(10, Version)) {
980 if(Version >= 2 && Version <= 3)
984<<
"Warning: Invalid value for COMPRESSED_BUNDLE_FORMAT_VERSION: " 986<<
". Valid values are 2 or 3. Using default version " 990<<
"Warning: Invalid value for COMPRESSED_BUNDLE_FORMAT_VERSION: " 991<< VersionStr.str() <<
". Using default version " 998std::string
Num= std::to_string(
Value);
999 intInsertPosition =
Num.length() - 3;
1000 while(InsertPosition > 0) {
1001 Num.insert(InsertPosition,
",");
1002InsertPosition -= 3;
1009 constllvm::MemoryBuffer &Input,
1010uint16_t Version,
boolVerbose) {
1011 if(!llvm::compression::zstd::isAvailable() &&
1012!llvm::compression::zlib::isAvailable())
1013 returncreateStringError(llvm::inconvertibleErrorCode(),
1014 "Compression not supported");
1015llvm::Timer HashTimer(
"Hash Calculation Timer",
"Hash calculation time",
1018HashTimer.startTimer();
1020llvm::MD5::MD5Result
Result;
1021Hash.update(Input.getBuffer());
1023uint64_t TruncatedHash =
Result.low();
1025HashTimer.stopTimer();
1029 reinterpret_cast<constuint8_t *
>(Input.getBuffer().data()),
1030Input.getBuffer().size());
1031llvm::Timer CompressTimer(
"Compression Timer",
"Compression time",
1034CompressTimer.startTimer();
1035llvm::compression::compress(
P, BufferUint8, CompressedBuffer);
1037CompressTimer.stopTimer();
1039uint16_t CompressionMethod =
static_cast<uint16_t
>(
P.format);
1042uint64_t UncompressedSize64 = Input.getBuffer().size();
1043uint64_t TotalFileSize64;
1048 if(UncompressedSize64 > std::numeric_limits<uint32_t>::max())
1049 returncreateStringError(llvm::inconvertibleErrorCode(),
1050 "Uncompressed size exceeds version 2 limit");
1051 if((MagicNumber.size() +
sizeof(uint32_t) +
sizeof(Version) +
1052 sizeof(CompressionMethod) +
sizeof(uint32_t) +
sizeof(TruncatedHash) +
1053CompressedBuffer.size()) > std::numeric_limits<uint32_t>::max())
1054 returncreateStringError(llvm::inconvertibleErrorCode(),
1055 "Total file size exceeds version 2 limit");
1057TotalFileSize64 = MagicNumber.size() +
sizeof(uint32_t) +
sizeof(Version) +
1058 sizeof(CompressionMethod) +
sizeof(uint32_t) +
1059 sizeof(TruncatedHash) + CompressedBuffer.size();
1061TotalFileSize64 = MagicNumber.size() +
sizeof(uint64_t) +
sizeof(Version) +
1062 sizeof(CompressionMethod) +
sizeof(uint64_t) +
1063 sizeof(TruncatedHash) + CompressedBuffer.size();
1067llvm::raw_svector_ostream OS(FinalBuffer);
1069OS.write(
reinterpret_cast<const char*
>(&Version),
sizeof(Version));
1070OS.write(
reinterpret_cast<const char*
>(&CompressionMethod),
1071 sizeof(CompressionMethod));
1075uint32_t TotalFileSize32 =
static_cast<uint32_t
>(TotalFileSize64);
1076uint32_t UncompressedSize32 =
static_cast<uint32_t
>(UncompressedSize64);
1077OS.write(
reinterpret_cast<const char*
>(&TotalFileSize32),
1078 sizeof(TotalFileSize32));
1079OS.write(
reinterpret_cast<const char*
>(&UncompressedSize32),
1080 sizeof(UncompressedSize32));
1082OS.write(
reinterpret_cast<const char*
>(&TotalFileSize64),
1083 sizeof(TotalFileSize64));
1084OS.write(
reinterpret_cast<const char*
>(&UncompressedSize64),
1085 sizeof(UncompressedSize64));
1088OS.write(
reinterpret_cast<const char*
>(&TruncatedHash),
1089 sizeof(TruncatedHash));
1090OS.write(
reinterpret_cast<const char*
>(CompressedBuffer.data()),
1091CompressedBuffer.size());
1095 P.format == llvm::compression::Format::Zstd ?
"zstd":
"zlib";
1096 doubleCompressionRate =
1097 static_cast<double>(UncompressedSize64) / CompressedBuffer.size();
1098 doubleCompressionTimeSeconds = CompressTimer.getTotalTime().getWallTime();
1099 doubleCompressionSpeedMBs =
1100(UncompressedSize64 / (1024.0 * 1024.0)) / CompressionTimeSeconds;
1101llvm::errs() <<
"Compressed bundle format version: "<< Version <<
"\n" 1102<<
"Total file size (including headers): " 1104<<
"Compression method used: "<< MethodUsed <<
"\n" 1105<<
"Compression level: "<<
P.level <<
"\n" 1106<<
"Binary size before compression: " 1108<<
"Binary size after compression: " 1110<<
"Compression rate: " 1111<< llvm::format(
"%.2lf", CompressionRate) <<
"\n" 1112<<
"Compression ratio: " 1113<< llvm::format(
"%.2lf%%", 100.0 / CompressionRate) <<
"\n" 1114<<
"Compression speed: " 1115<< llvm::format(
"%.2lf MB/s", CompressionSpeedMBs) <<
"\n" 1116<<
"Truncated MD5 hash: " 1117<< llvm::format_hex(TruncatedHash, 16) <<
"\n";
1120 returnllvm::MemoryBuffer::getMemBufferCopy(
1121llvm::StringRef(FinalBuffer.data(), FinalBuffer.size()));
1127StringRef Blob = Input.getBuffer();
1130 if(Blob.size() < V1HeaderSize)
1131 returnllvm::MemoryBuffer::getMemBufferCopy(Blob);
1133 if(llvm::identify_magic(Blob) !=
1134llvm::file_magic::offload_bundle_compressed) {
1136llvm::errs() <<
"Uncompressed bundle.\n";
1137 returnllvm::MemoryBuffer::getMemBufferCopy(Blob);
1140 size_tCurrentOffset = MagicSize;
1143uint16_t ThisVersion;
1144 memcpy(&ThisVersion, Blob.data() + CurrentOffset,
sizeof(uint16_t));
1145CurrentOffset += VersionFieldSize;
1148 if(ThisVersion >= 2 && ThisVersion <= 3) {
1149 size_tRequiredSize = (ThisVersion == 2) ? V2HeaderSize : V3HeaderSize;
1150 if(Blob.size() < RequiredSize)
1151 returncreateStringError(inconvertibleErrorCode(),
1152 "Compressed bundle header size too small");
1156uint16_t CompressionMethod;
1157 memcpy(&CompressionMethod, Blob.data() + CurrentOffset,
sizeof(uint16_t));
1158CurrentOffset += MethodFieldSize;
1161uint64_t TotalFileSize = 0;
1162 if(ThisVersion >= 2) {
1163 if(ThisVersion == 2) {
1164uint32_t TotalFileSize32;
1165 memcpy(&TotalFileSize32, Blob.data() + CurrentOffset,
sizeof(uint32_t));
1166TotalFileSize = TotalFileSize32;
1167CurrentOffset += FileSizeFieldSizeV2;
1169 memcpy(&TotalFileSize, Blob.data() + CurrentOffset,
sizeof(uint64_t));
1170CurrentOffset += FileSizeFieldSizeV3;
1175uint64_t UncompressedSize = 0;
1176 if(ThisVersion <= 2) {
1177uint32_t UncompressedSize32;
1178 memcpy(&UncompressedSize32, Blob.data() + CurrentOffset,
sizeof(uint32_t));
1179UncompressedSize = UncompressedSize32;
1180CurrentOffset += UncompressedSizeFieldSizeV2;
1182 memcpy(&UncompressedSize, Blob.data() + CurrentOffset,
sizeof(uint64_t));
1183CurrentOffset += UncompressedSizeFieldSizeV3;
1187uint64_t StoredHash;
1188 memcpy(&StoredHash, Blob.data() + CurrentOffset,
sizeof(uint64_t));
1189CurrentOffset += HashFieldSize;
1192llvm::compression::Format CompressionFormat;
1193 if(CompressionMethod ==
1194 static_cast<uint16_t
>(llvm::compression::Format::Zlib))
1195CompressionFormat = llvm::compression::Format::Zlib;
1196 else if(CompressionMethod ==
1197 static_cast<uint16_t
>(llvm::compression::Format::Zstd))
1198CompressionFormat = llvm::compression::Format::Zstd;
1200 returncreateStringError(inconvertibleErrorCode(),
1201 "Unknown compressing method");
1203llvm::Timer DecompressTimer(
"Decompression Timer",
"Decompression time",
1206DecompressTimer.startTimer();
1209StringRef CompressedData = Blob.substr(CurrentOffset);
1210 if(llvm::Error DecompressionError = llvm::compression::decompress(
1211CompressionFormat, llvm::arrayRefFromStringRef(CompressedData),
1212DecompressedData, UncompressedSize))
1213 returncreateStringError(inconvertibleErrorCode(),
1214 "Could not decompress embedded file contents: "+
1215llvm::toString(std::move(DecompressionError)));
1218DecompressTimer.stopTimer();
1220 doubleDecompressionTimeSeconds =
1221DecompressTimer.getTotalTime().getWallTime();
1224llvm::Timer HashRecalcTimer(
"Hash Recalculation Timer",
1225 "Hash recalculation time",
1227HashRecalcTimer.startTimer();
1229llvm::MD5::MD5Result
Result;
1231DecompressedData.size()));
1233uint64_t RecalculatedHash =
Result.low();
1234HashRecalcTimer.stopTimer();
1235 boolHashMatch = (StoredHash == RecalculatedHash);
1237 doubleCompressionRate =
1238 static_cast<double>(UncompressedSize) / CompressedData.size();
1239 doubleDecompressionSpeedMBs =
1240(UncompressedSize / (1024.0 * 1024.0)) / DecompressionTimeSeconds;
1242llvm::errs() <<
"Compressed bundle format version: "<< ThisVersion <<
"\n";
1243 if(ThisVersion >= 2)
1244llvm::errs() <<
"Total file size (from header): " 1246llvm::errs() <<
"Decompression method: " 1247<< (CompressionFormat == llvm::compression::Format::Zlib
1251<<
"Size before decompression: " 1253<<
"Size after decompression: " 1255<<
"Compression rate: " 1256<< llvm::format(
"%.2lf", CompressionRate) <<
"\n" 1257<<
"Compression ratio: " 1258<< llvm::format(
"%.2lf%%", 100.0 / CompressionRate) <<
"\n" 1259<<
"Decompression speed: " 1260<< llvm::format(
"%.2lf MB/s", DecompressionSpeedMBs) <<
"\n" 1261<<
"Stored hash: "<< llvm::format_hex(StoredHash, 16) <<
"\n" 1262<<
"Recalculated hash: " 1263<< llvm::format_hex(RecalculatedHash, 16) <<
"\n" 1264<<
"Hashes match: "<< (HashMatch ?
"Yes":
"No") <<
"\n";
1267 returnllvm::MemoryBuffer::getMemBufferCopy(
1268llvm::toStringRef(DecompressedData));
1275ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
1276MemoryBuffer::getFileOrSTDIN(InputFileName,
true);
1277 if(std::error_code EC = CodeOrErr.getError())
1278 returncreateFileError(InputFileName, EC);
1283 if(!DecompressedBufferOrErr)
1284 returncreateStringError(
1285inconvertibleErrorCode(),
1286 "Failed to decompress input: "+
1287llvm::toString(DecompressedBufferOrErr.takeError()));
1289MemoryBuffer &DecompressedInput = **DecompressedBufferOrErr;
1294 if(!FileHandlerOrErr)
1295 returnFileHandlerOrErr.takeError();
1297std::unique_ptr<FileHandler> &FH = *FileHandlerOrErr;
1299 returnFH->listBundleIDs(DecompressedInput);
1310DEBUG_WITH_TYPE(
"CodeObjectCompatibility",
1311dbgs() <<
"Compatible: Exact match: \t[CodeObject: " 1312<< CodeObjectInfo.
str()
1313<<
"]\t:\t[Target: "<<
TargetInfo.str() <<
"]\n");
1321 "CodeObjectCompatibility",
1322dbgs() <<
"Incompatible: Kind/Triple mismatch \t[CodeObject: " 1323<< CodeObjectInfo.
str() <<
"]\t:\t[Target: "<<
TargetInfo.str()
1329llvm::StringMap<bool> CodeObjectFeatureMap, TargetFeatureMap;
1331CodeObjectInfo.
Triple, CodeObjectInfo.
TargetID, &CodeObjectFeatureMap);
1336 if(!TargetProc || !CodeObjectProc ||
1337CodeObjectProc.value() != TargetProc.value()) {
1338DEBUG_WITH_TYPE(
"CodeObjectCompatibility",
1339dbgs() <<
"Incompatible: Processor mismatch \t[CodeObject: " 1340<< CodeObjectInfo.
str()
1341<<
"]\t:\t[Target: "<<
TargetInfo.str() <<
"]\n");
1347 if(CodeObjectFeatureMap.getNumItems() > TargetFeatureMap.getNumItems()) {
1348DEBUG_WITH_TYPE(
"CodeObjectCompatibility",
1349dbgs() <<
"Incompatible: CodeObject has more features " 1350 "than target \t[CodeObject: " 1351<< CodeObjectInfo.
str()
1352<<
"]\t:\t[Target: "<<
TargetInfo.str() <<
"]\n");
1360 for(
const auto&CodeObjectFeature : CodeObjectFeatureMap) {
1361 autoTargetFeature = TargetFeatureMap.find(CodeObjectFeature.getKey());
1362 if(TargetFeature == TargetFeatureMap.end()) {
1364 "CodeObjectCompatibility",
1366<<
"Incompatible: Value of CodeObject's non-ANY feature is " 1367 "not matching with Target feature's ANY value \t[CodeObject: " 1368<< CodeObjectInfo.
str() <<
"]\t:\t[Target: "<<
TargetInfo.str()
1371}
else if(TargetFeature->getValue() != CodeObjectFeature.getValue()) {
1373 "CodeObjectCompatibility",
1374dbgs() <<
"Incompatible: Value of CodeObject's non-ANY feature is " 1375 "not matching with Target feature's non-ANY value " 1377<< CodeObjectInfo.
str()
1378<<
"]\t:\t[Target: "<<
TargetInfo.str() <<
"]\n");
1388 "CodeObjectCompatibility",
1389dbgs() <<
"Compatible: Target IDs are compatible \t[CodeObject: " 1390<< CodeObjectInfo.
str() <<
"]\t:\t[Target: "<<
TargetInfo.str()
1401llvm::raw_svector_ostream BufferStream(Buffer);
1407ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
1408MemoryBuffer::getFileOrSTDIN(I,
true);
1409 if(std::error_code EC = CodeOrErr.getError())
1410 returncreateFileError(I, EC);
1411InputBuffers.emplace_back(std::move(*CodeOrErr));
1416 "Host input index undefined??");
1421 if(!FileHandlerOrErr)
1422 returnFileHandlerOrErr.takeError();
1424std::unique_ptr<FileHandler> &FH = *FileHandlerOrErr;
1428 if(Error Err = FH->WriteHeader(BufferStream, InputBuffers))
1433 autoInput = InputBuffers.begin();
1435 if(Error Err = FH->WriteBundleStart(BufferStream, Triple))
1437 if(Error Err = FH->WriteBundle(BufferStream, **Input))
1439 if(Error Err = FH->WriteBundleEnd(BufferStream, Triple))
1451std::unique_ptr<llvm::MemoryBuffer> BufferMemory =
1452llvm::MemoryBuffer::getMemBufferCopy(
1453llvm::StringRef(Buffer.data(), Buffer.size()));
1459 if(
autoError = CompressionResult.takeError())
1462 autoCompressedMemBuffer = std::move(CompressionResult.get());
1463CompressedBuffer.assign(CompressedMemBuffer->getBufferStart(),
1464CompressedMemBuffer->getBufferEnd());
1466CompressedBuffer = Buffer;
1468OutputFile.write(CompressedBuffer.data(), CompressedBuffer.size());
1470 returnFH->finalizeOutputFile();
1476ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
1479 if(std::error_code EC = CodeOrErr.getError())
1485 if(!DecompressedBufferOrErr)
1486 returncreateStringError(
1487inconvertibleErrorCode(),
1488 "Failed to decompress input: "+
1489llvm::toString(DecompressedBufferOrErr.takeError()));
1491MemoryBuffer &Input = **DecompressedBufferOrErr;
1496 if(!FileHandlerOrErr)
1497 returnFileHandlerOrErr.takeError();
1499std::unique_ptr<FileHandler> &FH = *FileHandlerOrErr;
1503 if(Error Err = FH->ReadHeader(Input))
1507StringMap<StringRef> Worklist;
1510Worklist[Triple] = *Output;
1516 boolFoundHostBundle =
false;
1517 while(!Worklist.empty()) {
1519FH->ReadBundleStart(Input);
1520 if(!CurTripleOrErr)
1521 returnCurTripleOrErr.takeError();
1524 if(!*CurTripleOrErr)
1527StringRef CurTriple = **CurTripleOrErr;
1528assert(!CurTriple.empty());
1530 autoOutput = Worklist.begin();
1531 for(
auto E= Worklist.end(); Output !=
E; Output++) {
1539 if(Output == Worklist.end())
1543raw_fd_ostream OutputFile((*Output).second, EC, sys::fs::OF_None);
1545 returncreateFileError((*Output).second, EC);
1546 if(Error Err = FH->ReadBundle(OutputFile, Input))
1548 if(Error Err = FH->ReadBundleEnd(Input))
1550Worklist.erase(Output);
1554 if(OffloadInfo.hasHostKind())
1555FoundHostBundle =
true;
1559std::string ErrMsg =
"Can't find bundles for";
1560std::set<StringRef> Sorted;
1561 for(
auto&
E: Worklist)
1562Sorted.insert(
E.first());
1564 unsigned Last= Sorted.size() - 1;
1565 for(
auto&
E: Sorted) {
1566 if(I != 0 &&
Last> 1)
1569 if(I ==
Last&& I != 0)
1574 returncreateStringError(inconvertibleErrorCode(), ErrMsg);
1580 for(
auto&
E: Worklist) {
1582raw_fd_ostream OutputFile(
E.second, EC, sys::fs::OF_None);
1584 returncreateFileError(
E.second, EC);
1588 if(OffloadInfo.hasHostKind())
1589OutputFile.write(Input.getBufferStart(), Input.getBufferSize());
1591 returnError::success();
1598 returncreateStringError(inconvertibleErrorCode(),
1599 "Can't find bundle for the host target");
1602 for(
auto&
E: Worklist) {
1604raw_fd_ostream OutputFile(
E.second, EC, sys::fs::OF_None);
1606 returncreateFileError(
E.second, EC);
1609 returnError::success();
1613 returnTriple(sys::getDefaultTargetTriple()).isOSDarwin() ? Archive::K_DARWIN
1627 if(!CompatibleTargets.empty()) {
1628DEBUG_WITH_TYPE(
"CodeObjectCompatibility",
1629dbgs() <<
"CompatibleTargets list should be empty\n");
1635CompatibleTargets.push_back(
Target);
1637 return!CompatibleTargets.empty();
1647std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;
1648ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
1649MemoryBuffer::getFileOrSTDIN(ArchiveName,
true,
false);
1650 if(std::error_code EC = BufOrErr.getError())
1651 returncreateFileError(ArchiveName, EC);
1653ArchiveBuffers.push_back(std::move(*BufOrErr));
1655Archive::create(ArchiveBuffers.back()->getMemBufferRef());
1657 returnLibOrErr.takeError();
1659 autoArchive = std::move(*LibOrErr);
1661Error ArchiveErr = Error::success();
1662 autoChildEnd = Archive->child_end();
1665 for(
autoArchiveIter = Archive->child_begin(ArchiveErr);
1666ArchiveIter != ChildEnd; ++ArchiveIter) {
1669 autoArchiveChildNameOrErr = (*ArchiveIter).getName();
1670 if(!ArchiveChildNameOrErr)
1671 returnArchiveChildNameOrErr.takeError();
1673 autoCodeObjectBufferRefOrErr = (*ArchiveIter).getMemoryBufferRef();
1674 if(!CodeObjectBufferRefOrErr)
1675 returnCodeObjectBufferRefOrErr.takeError();
1677 autoCodeObjectBuffer =
1678MemoryBuffer::getMemBuffer(*CodeObjectBufferRefOrErr,
false);
1682 if(!FileHandlerOrErr)
1683 returnFileHandlerOrErr.takeError();
1685std::unique_ptr<FileHandler> &FileHandler = *FileHandlerOrErr;
1686assert(FileHandler);
1688std::set<StringRef> BundleIds;
1689 autoCodeObjectFileError =
1690FileHandler->getBundleIDs(*CodeObjectBuffer, BundleIds);
1691 if(CodeObjectFileError)
1692 returnCodeObjectFileError;
1695 if(ConflictingArchs) {
1696std::string ErrMsg =
1697Twine(
"conflicting TargetIDs ["+ ConflictingArchs.value().first +
1698 ", "+ ConflictingArchs.value().second +
"] found in "+
1699ArchiveChildNameOrErr.get() +
" of "+ ArchiveName)
1701 returncreateStringError(inconvertibleErrorCode(), ErrMsg);
1716std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;
1720StringMap<std::vector<NewArchiveMember>> OutputArchivesMap;
1723StringMap<StringRef> TargetOutputFileNameMap;
1727TargetOutputFileNameMap[
Target] = *Output;
1739 returnArchiveError;
1743ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
1744MemoryBuffer::getFileOrSTDIN(IFName,
true,
false);
1745 if(std::error_code EC = BufOrErr.getError())
1748ArchiveBuffers.push_back(std::move(*BufOrErr));
1750Archive::create(ArchiveBuffers.back()->getMemBufferRef());
1752 returnLibOrErr.takeError();
1754 autoArchive = std::move(*LibOrErr);
1756Error ArchiveErr = Error::success();
1757 autoChildEnd = Archive->child_end();
1760 for(
autoArchiveIter = Archive->child_begin(ArchiveErr);
1761ArchiveIter != ChildEnd; ++ArchiveIter) {
1764 autoArchiveChildNameOrErr = (*ArchiveIter).getName();
1765 if(!ArchiveChildNameOrErr)
1766 returnArchiveChildNameOrErr.takeError();
1768StringRef BundledObjectFile = sys::path::filename(*ArchiveChildNameOrErr);
1770 autoCodeObjectBufferRefOrErr = (*ArchiveIter).getMemoryBufferRef();
1771 if(!CodeObjectBufferRefOrErr)
1772 returnCodeObjectBufferRefOrErr.takeError();
1774 autoTempCodeObjectBuffer =
1775MemoryBuffer::getMemBuffer(*CodeObjectBufferRefOrErr,
false);
1781 if(!DecompressedBufferOrErr)
1782 returncreateStringError(
1783inconvertibleErrorCode(),
1784 "Failed to decompress code object: "+
1785llvm::toString(DecompressedBufferOrErr.takeError()));
1787MemoryBuffer &CodeObjectBuffer = **DecompressedBufferOrErr;
1791 if(!FileHandlerOrErr)
1792 returnFileHandlerOrErr.takeError();
1794std::unique_ptr<FileHandler> &FileHandler = *FileHandlerOrErr;
1795assert(FileHandler &&
1796 "FileHandle creation failed for file in the archive!");
1798 if(Error ReadErr = FileHandler->ReadHeader(CodeObjectBuffer))
1802FileHandler->ReadBundleStart(CodeObjectBuffer);
1803 if(!CurBundleIDOrErr)
1804 returnCurBundleIDOrErr.takeError();
1806std::optional<StringRef> OptionalCurBundleID = *CurBundleIDOrErr;
1808 if(!OptionalCurBundleID)
1810StringRef CodeObject = *OptionalCurBundleID;
1814 while(!CodeObject.empty()) {
1819std::string BundleData;
1820raw_string_ostream DataStream(BundleData);
1821 if(Error Err = FileHandler->ReadBundle(DataStream, CodeObjectBuffer))
1824 for(
auto&CompatibleTarget : CompatibleTargets) {
1826BundledObjectFileName.assign(BundledObjectFile);
1827 autoOutputBundleName =
1828Twine(llvm::sys::path::stem(BundledObjectFileName) +
"-"+
1831CodeObjectInfo.TargetID))
1835std::replace(OutputBundleName.begin(), OutputBundleName.end(),
':',
1838std::unique_ptr<MemoryBuffer> MemBuf = MemoryBuffer::getMemBufferCopy(
1839DataStream.str(), OutputBundleName);
1840ArchiveBuffers.push_back(std::move(MemBuf));
1841llvm::MemoryBufferRef MemBufRef =
1842MemoryBufferRef(*(ArchiveBuffers.back()));
1846OutputArchivesMap[CompatibleTarget].push_back(
1847NewArchiveMember(MemBufRef));
1851 if(Error Err = FileHandler->ReadBundleEnd(CodeObjectBuffer))
1855FileHandler->ReadBundleStart(CodeObjectBuffer);
1856 if(!NextTripleOrErr)
1857 returnNextTripleOrErr.takeError();
1859CodeObject = ((*NextTripleOrErr).has_value()) ? **NextTripleOrErr :
"";
1863assert(!ArchiveErr &&
"Error occurred while reading archive!");
1868StringMapIterator<std::vector<llvm::NewArchiveMember>> CurArchiveMembers =
1869OutputArchivesMap.find(
Target);
1870 if(CurArchiveMembers != OutputArchivesMap.end()) {
1871 if(Error WriteErr = writeArchive(
FileName, CurArchiveMembers->getValue(),
1872SymtabWritingMode::NormalSymtab,
1877std::string ErrMsg =
1878Twine(
"no compatible code object found for the target '"+
Target+
1879 "' in heterogeneous archive library: "+ IFName)
1881 returncreateStringError(inconvertibleErrorCode(), ErrMsg);
1886std::vector<llvm::NewArchiveMember> EmptyArchive;
1887EmptyArchive.clear();
1888 if(Error WriteErr = writeArchive(
1889 FileName, EmptyArchive, SymtabWritingMode::NormalSymtab,
1895 returnError::success();
llvm::MachO::Target Target
static std::string getDeviceLibraryFileName(StringRef BundleFileName, StringRef Device)
static llvm::ManagedStatic< llvm::TimerGroup, CreateClangOffloadBundlerTimerGroup > ClangOffloadBundlerTimerGroup
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 Error CheckHeterogeneousArchive(StringRef ArchiveName, const OffloadBundlerConfig &BundlerConfig)
static std::unique_ptr< FileHandler > CreateObjectFileHandler(MemoryBuffer &FirstInput, const OffloadBundlerConfig &BundlerConfig)
Return an appropriate object file handler.
static Archive::Kind getDefaultArchiveKindForHost()
static std::string formatWithCommas(unsigned long long Value)
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...
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
static llvm::Expected< std::unique_ptr< llvm::MemoryBuffer > > decompress(const llvm::MemoryBuffer &Input, bool Verbose=false)
static llvm::Expected< std::unique_ptr< llvm::MemoryBuffer > > compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input, uint16_t Version, bool Verbose=false)
llvm::compression::Format CompressionFormat
std::vector< std::string > OutputFileNames
std::vector< std::string > TargetNames
uint16_t CompressedBundleVersion
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.
bool Alloc(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
The JSON file list parser is used to communicate input to InstallAPI.
std::optional< llvm::StringRef > parseTargetID(const llvm::Triple &T, llvm::StringRef OffloadArch, llvm::StringMap< bool > *FeatureMap)
Parse a target ID to get processor and feature map.
@ Create
'create' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
std::optional< std::pair< llvm::StringRef, llvm::StringRef > > getConflictTargetIDCombination(const std::set< llvm::StringRef > &TargetIDs)
Get the conflicted pair of target IDs for a compilation or a bundled code object, assuming TargetIDs ...
@ Result
The result type of a method or function.
OffloadArch StringToOffloadArch(llvm::StringRef S)
const FunctionProtoType * T
Diagnostic wrappers for TextAPI types for error reporting.
Obtain the offload kind, real machine triple, and an optional TargetID out of the target information ...
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
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4