diff --git a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp --- a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp +++ b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp @@ -57,37 +57,42 @@ using namespace llvm; using namespace llvm::object; -static cl::opt Help("h", cl::desc("Alias for -help"), cl::Hidden); +static void PrintVersion(raw_ostream &OS) { + OS << clang::getClangToolFullVersion("clang-offload-bundler") << '\n'; +} + +int main(int argc, const char **argv) { + static cl::opt Help("h", cl::desc("Alias for -help"), cl::Hidden); -// Mark all our options with this category, everything else (except for -version -// and -help) will be hidden. -cl::OptionCategory + // Mark all our options with this category, everything else (except for + // -version and -help) will be hidden. + cl::OptionCategory ClangOffloadBundlerCategory("clang-offload-bundler options"); -cl::list + cl::list InputFileNames("input", cl::ZeroOrMore, cl::desc("Input file." " Can be specified multiple times " "for multiple input files."), cl::cat(ClangOffloadBundlerCategory)); -static cl::list + cl::list InputFileNamesDeprecatedOpt("inputs", cl::CommaSeparated, cl::ZeroOrMore, cl::desc("[,...] (deprecated)"), cl::cat(ClangOffloadBundlerCategory)); -cl::list + cl::list OutputFileNames("output", cl::ZeroOrMore, cl::desc("Output file." " Can be specified multiple times " "for multiple output files."), cl::cat(ClangOffloadBundlerCategory)); -static cl::list + cl::list OutputFileNamesDeprecatedOpt("outputs", cl::CommaSeparated, cl::ZeroOrMore, cl::desc("[,...] (deprecated)"), cl::cat(ClangOffloadBundlerCategory)); -cl::list + cl::list TargetNames("targets", cl::CommaSeparated, cl::desc("[-,...]"), cl::cat(ClangOffloadBundlerCategory)); -cl::opt + cl::opt FilesType("type", cl::Required, cl::desc("Type of the files to be bundled/unbundled.\n" "Current supported types are:\n" @@ -103,52 +108,42 @@ " gch - precompiled-header\n" " ast - clang AST file"), cl::cat(ClangOffloadBundlerCategory)); -cl::opt + cl::opt Unbundle("unbundle", cl::desc("Unbundle bundled file into several output files.\n"), cl::init(false), cl::cat(ClangOffloadBundlerCategory)); -cl::opt + cl::opt ListBundleIDs("list", cl::desc("List bundle IDs in the bundled file.\n"), cl::init(false), cl::cat(ClangOffloadBundlerCategory)); -cl::opt PrintExternalCommands( + cl::opt PrintExternalCommands( "###", cl::desc("Print any external commands that are to be executed " "instead of actually executing them - for testing purposes.\n"), cl::init(false), cl::cat(ClangOffloadBundlerCategory)); -cl::opt + cl::opt AllowMissingBundles("allow-missing-bundles", cl::desc("Create empty files if bundles are missing " "when unbundling.\n"), cl::init(false), cl::cat(ClangOffloadBundlerCategory)); -cl::opt + cl::opt BundleAlignment("bundle-align", cl::desc("Alignment of bundle for binary files"), cl::init(1), cl::cat(ClangOffloadBundlerCategory)); -cl::opt HipOpenmpCompatible( + cl::opt HipOpenmpCompatible( "hip-openmp-compatible", cl::desc("Treat hip and hipv4 offload kinds as " "compatible with openmp kind, and vice versa.\n"), cl::init(false), cl::cat(ClangOffloadBundlerCategory)); -/// The index of the host input in the list of inputs. -unsigned HostInputIndex = ~0u; + /// The index of the host input in the list of inputs. + unsigned HostInputIndex = ~0u; -/// Whether not having host target is allowed. -bool AllowNoHost = false; - -/// Path to the current binary. -std::string BundlerExecutable; - -static void PrintVersion(raw_ostream &OS) { - OS << clang::getClangToolFullVersion("clang-offload-bundler") << '\n'; -} - -int main(int argc, const char **argv) { + // Process commandline options and report errors sys::PrintStackTraceOnErrorSignal(argv[0]); cl::HideUnrelatedOptions(ClangOffloadBundlerCategory); @@ -171,13 +166,6 @@ }; auto doWork = [&](std::function Work) { - // Save the current executable directory as it will be useful to find other - // tools. - BundlerExecutable = argv[0]; - if (!llvm::sys::fs::exists(BundlerExecutable)) - BundlerExecutable = - sys::fs::getMainExecutable(argv[0], &BundlerExecutable); - if (llvm::Error Err = Work()) { reportError(std::move(Err)); } @@ -187,6 +175,13 @@ return WithColor::warning(errs(), StringRef(argv[0])); }; + // Save the current executable directory as it will be useful to find other + // tools. + std::string BundlerExecutable = argv[0]; + if (!llvm::sys::fs::exists(BundlerExecutable)) + BundlerExecutable = + sys::fs::getMainExecutable(argv[0], &BundlerExecutable); + if (InputFileNames.getNumOccurrences() != 0 && InputFileNamesDeprecatedOpt.getNumOccurrences() != 0) { reportError(createStringError( @@ -236,7 +231,11 @@ "-targets option is invalid for -list")); } - doWork([]() { return ListBundleIDsInFile(InputFileNames.front()); }); + Config BundlerPrint; + BundlerPrint.PrintExternalCommands = PrintExternalCommands; + BundlerPrint.BundlerExecutable = BundlerExecutable; + doWork([&]() { return ListBundleIDsInFile(InputFileNames.front(), + &BundlerPrint); }); return 0; } @@ -293,7 +292,10 @@ } ParsedTargets.insert(Target); - auto OffloadInfo = OffloadTargetInfo(Target); + Config BundlerOpenmp; + BundlerOpenmp.HipOpenmpCompatible = HipOpenmpCompatible; + BundlerOpenmp.BundlerExecutable = BundlerExecutable; + auto OffloadInfo = OffloadTargetInfo(Target, &BundlerOpenmp); bool KindIsValid = OffloadInfo.isOffloadKindValid(); bool TripleIsValid = OffloadInfo.isTripleValid(); @@ -323,7 +325,7 @@ // HIP uses clang-offload-bundler to bundle device-only compilation results // for multiple GPU archs, therefore allow no host target if all entries // are for HIP. - AllowNoHost = HIPOnly; + bool AllowNoHost = HIPOnly; // Host triple is not really needed for unbundling operation, so do not // treat missing host triple as error if we do unbundling. @@ -334,14 +336,30 @@ Twine(HostTargetNum))); } - doWork([]() { + Config BundlerConfig; + BundlerConfig.AllowNoHost = AllowNoHost; + BundlerConfig.AllowMissingBundles = AllowMissingBundles; + BundlerConfig.PrintExternalCommands = PrintExternalCommands; + BundlerConfig.HipOpenmpCompatible = HipOpenmpCompatible; + BundlerConfig.BundleAlignment = BundleAlignment; + BundlerConfig.HostInputIndex = HostInputIndex; + BundlerConfig.FilesType = FilesType; + BundlerConfig.BundlerExecutable = BundlerExecutable; + + BundlerConfig.TargetNames = TargetNames; + BundlerConfig.InputFileNames = InputFileNames; + BundlerConfig.OutputFileNames = OutputFileNames; + + OffloadBundler Bundler(&BundlerConfig); + + doWork([&]() { if (Unbundle) { if (FilesType == "a") - return UnbundleArchive(); + return Bundler.UnbundleArchive(); else - return UnbundleFiles(); + return Bundler.UnbundleFiles(); } else - return BundleFiles(); + return Bundler.BundleFiles(); }); return 0; } diff --git a/clang/tools/clang-offload-bundler/OffloadBundler.h b/clang/tools/clang-offload-bundler/OffloadBundler.h --- a/clang/tools/clang-offload-bundler/OffloadBundler.h +++ b/clang/tools/clang-offload-bundler/OffloadBundler.h @@ -17,9 +17,37 @@ using namespace llvm; using namespace llvm::object; -Error BundleFiles(); -Error UnbundleFiles(); -Error UnbundleArchive(); +class Config { +public: + bool AllowNoHost = false; + bool AllowMissingBundles = false; + bool CheckInputArchive = false; + bool PrintExternalCommands = false; + bool HipOpenmpCompatible = false; + + unsigned BundleAlignment = 1; + unsigned HostInputIndex = ~0u; + + std::string FilesType; + std::string BundlerExecutable; + + // TODO: Convert these to llvm::SmallVector + std::vector TargetNames; + std::vector InputFileNames; + std::vector OutputFileNames; +}; + +class OffloadBundler { +public: + Config *BundlerConfig; + + // TODO: Add error checking from ClangOffloadBundler.cpp + OffloadBundler(Config *BC) : BundlerConfig(BC) {} + + Error BundleFiles(); + Error UnbundleFiles(); + Error UnbundleArchive(); +}; /// Obtain the offload kind, real machine triple, and an optional GPUArch /// out of the target information specified by the user. @@ -31,8 +59,9 @@ StringRef OffloadKind; llvm::Triple Triple; StringRef GPUArch; + Config *BundlerConfig; - OffloadTargetInfo(const StringRef Target); + OffloadTargetInfo(const StringRef Target, Config *BC); bool hasHostKind() const; bool isOffloadKindValid() const; bool isOffloadKindCompatible(const StringRef TargetOffloadKind) const; @@ -42,4 +71,4 @@ }; // List bundle IDs. Return true if an error was found. -Error ListBundleIDsInFile(StringRef InputFileName); +Error ListBundleIDsInFile(StringRef InputFileName, Config *BundlerConfig); diff --git a/clang/tools/clang-offload-bundler/OffloadBundler.cpp b/clang/tools/clang-offload-bundler/OffloadBundler.cpp --- a/clang/tools/clang-offload-bundler/OffloadBundler.cpp +++ b/clang/tools/clang-offload-bundler/OffloadBundler.cpp @@ -58,28 +58,12 @@ using namespace llvm; using namespace llvm::object; -extern cl::list InputFileNames; -extern cl::list OutputFileNames; -extern cl::list TargetNames; -extern cl::opt FilesType; -extern cl::opt PrintExternalCommands; -extern cl::opt AllowMissingBundles; -extern cl::opt BundleAlignment; -extern cl::opt HipOpenmpCompatible; - /// Magic string that marks the existence of offloading data. #define OFFLOAD_BUNDLER_MAGIC_STR "__CLANG_OFFLOAD_BUNDLE__" -/// The index of the host input in the list of inputs. -extern unsigned HostInputIndex; - -/// Whether not having host target is allowed. -extern bool AllowNoHost; - -/// Path to the current binary. -extern std::string BundlerExecutable; - -OffloadTargetInfo::OffloadTargetInfo(const StringRef Target) { +OffloadTargetInfo::OffloadTargetInfo(const StringRef Target, Config *BC) { + // TODO: Add error checking from ClangOffloadBundler.cpp + BundlerConfig = BC; auto TargetFeatures = Target.split(':'); auto TripleOrGPU = TargetFeatures.first.rsplit('-'); @@ -107,7 +91,7 @@ bool OffloadTargetInfo::isOffloadKindCompatible(const StringRef TargetOffloadKind) const { if (OffloadKind == TargetOffloadKind) return true; - if (HipOpenmpCompatible) { + if (BundlerConfig->HipOpenmpCompatible) { bool HIPCompatibleWithOpenMP = OffloadKind.startswith_insensitive("hip") && TargetOffloadKind == "openmp"; @@ -306,8 +290,12 @@ /// Current bundle target to be written. std::string CurWriteBundleTarget; + /// Configuration options and arrays for this bundler job + Config *BundlerConfig; + public: - BinaryFileHandler() {} + // TODO: Add error checking from ClangOffloadBundler.cpp + BinaryFileHandler(Config *BC) : BundlerConfig(BC) {} ~BinaryFileHandler() final {} @@ -407,7 +395,7 @@ HeaderSize += sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1; HeaderSize += 8; // Number of Bundles - for (auto &T : TargetNames) { + for (auto &T : BundlerConfig->TargetNames) { HeaderSize += 3 * 8; // Bundle offset, Size of bundle and size of triple. HeaderSize += T.size(); // The triple. } @@ -415,12 +403,12 @@ // Write to the buffer the header. OS << OFFLOAD_BUNDLER_MAGIC_STR; - Write8byteIntegerToBuffer(OS, TargetNames.size()); + Write8byteIntegerToBuffer(OS, BundlerConfig->TargetNames.size()); unsigned Idx = 0; - for (auto &T : TargetNames) { + for (auto &T : BundlerConfig->TargetNames) { MemoryBuffer &MB = *Inputs[Idx++]; - HeaderSize = alignTo(HeaderSize, BundleAlignment); + HeaderSize = alignTo(HeaderSize, BundlerConfig->BundleAlignment); // Bundle offset. Write8byteIntegerToBuffer(OS, HeaderSize); // Size of the bundle (adds to the next bundle's offset) @@ -525,10 +513,14 @@ section_iterator CurrentSection; section_iterator NextSection; + /// Configuration options and arrays for this bundler job + Config *BundlerConfig; + public: - ObjectFileHandler(std::unique_ptr ObjIn) + // TODO: Add error checking from ClangOffloadBundler.cpp + ObjectFileHandler(std::unique_ptr ObjIn, Config *BC) : Obj(std::move(ObjIn)), CurrentSection(Obj->section_begin()), - NextSection(Obj->section_begin()) {} + NextSection(Obj->section_begin()), BundlerConfig(BC) {} ~ObjectFileHandler() final {} @@ -569,7 +561,7 @@ Error WriteHeader(raw_fd_ostream &OS, ArrayRef> Inputs) final { - assert(HostInputIndex != ~0u && "Host input index not defined."); + assert(BundlerConfig->HostInputIndex != ~0u && "Host input index not defined."); // Record number of inputs. NumberOfInputs = Inputs.size(); @@ -584,7 +576,7 @@ Error WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final { assert(NumberOfProcessedInputs <= NumberOfInputs && "Processing more inputs that actually exist!"); - assert(HostInputIndex != ~0u && "Host input index not defined."); + assert(BundlerConfig->HostInputIndex != ~0u && "Host input index not defined."); // If this is not the last output, we don't have to do anything. if (NumberOfProcessedInputs != NumberOfInputs) @@ -597,7 +589,8 @@ // Find llvm-objcopy in order to create the bundle binary. ErrorOr Objcopy = sys::findProgramByName( - "llvm-objcopy", sys::path::parent_path(BundlerExecutable)); + "llvm-objcopy", + sys::path::parent_path(BundlerConfig->BundlerExecutable)); if (!Objcopy) Objcopy = sys::findProgramByName("llvm-objcopy"); if (!Objcopy) @@ -617,8 +610,8 @@ StringSaver SS{Alloc}; SmallVector ObjcopyArgs{"llvm-objcopy"}; for (unsigned I = 0; I < NumberOfInputs; ++I) { - StringRef InputFile = InputFileNames[I]; - if (I == HostInputIndex) { + StringRef InputFile = BundlerConfig->InputFileNames[I]; + if (I == BundlerConfig->HostInputIndex) { // Special handling for the host bundle. We do not need to add a // standard bundle for the host object since we are going to use fat // object as a host object. Therefore use dummy contents (one zero byte) @@ -630,15 +623,18 @@ } ObjcopyArgs.push_back(SS.save(Twine("--add-section=") + - OFFLOAD_BUNDLER_MAGIC_STR + TargetNames[I] + + OFFLOAD_BUNDLER_MAGIC_STR + + BundlerConfig->TargetNames[I] + "=" + InputFile)); ObjcopyArgs.push_back(SS.save(Twine("--set-section-flags=") + - OFFLOAD_BUNDLER_MAGIC_STR + TargetNames[I] + + OFFLOAD_BUNDLER_MAGIC_STR + + BundlerConfig->TargetNames[I] + "=readonly,exclude")); } ObjcopyArgs.push_back("--"); - ObjcopyArgs.push_back(InputFileNames[HostInputIndex]); - ObjcopyArgs.push_back(OutputFileNames.front()); + ObjcopyArgs.push_back( + BundlerConfig->InputFileNames[BundlerConfig->HostInputIndex]); + ObjcopyArgs.push_back(BundlerConfig->OutputFileNames.front()); if (Error Err = executeObjcopy(*Objcopy, ObjcopyArgs)) return Err; @@ -651,10 +647,10 @@ } private: - static Error executeObjcopy(StringRef Objcopy, ArrayRef Args) { + Error executeObjcopy(StringRef Objcopy, ArrayRef Args) { // If the user asked for the commands to be printed out, we do that // instead of executing it. - if (PrintExternalCommands) { + if (BundlerConfig->PrintExternalCommands) { errs() << "\"" << Objcopy << "\""; for (StringRef Arg : drop_begin(Args, 1)) errs() << " \"" << Arg << "\""; @@ -787,24 +783,27 @@ /// handler if we know how to deal with that format, otherwise we use a default /// binary file handler. static std::unique_ptr -CreateObjectFileHandler(MemoryBuffer &FirstInput) { +CreateObjectFileHandler(MemoryBuffer &FirstInput, Config *BundlerConfig) { // Check if the input file format is one that we know how to deal with. Expected> BinaryOrErr = createBinary(FirstInput); // We only support regular object files. If failed to open the input as a // known binary or this is not an object file use the default binary handler. if (errorToBool(BinaryOrErr.takeError()) || !isa(*BinaryOrErr)) - return std::make_unique(); + return std::make_unique(BundlerConfig); // Otherwise create an object file handler. The handler will be owned by the // client of this function. return std::make_unique( - std::unique_ptr(cast(BinaryOrErr->release()))); + std::unique_ptr(cast(BinaryOrErr->release())), + BundlerConfig); } /// Return an appropriate handler given the input files and options. static Expected> -CreateFileHandler(MemoryBuffer &FirstInput) { +CreateFileHandler(MemoryBuffer &FirstInput, Config *BundlerConfig) { + std::string FilesType = BundlerConfig->FilesType; + if (FilesType == "i") return std::make_unique(/*Comment=*/"//"); if (FilesType == "ii") @@ -818,24 +817,24 @@ if (FilesType == "ll") return std::make_unique(/*Comment=*/";"); if (FilesType == "bc") - return std::make_unique(); + return std::make_unique(BundlerConfig); if (FilesType == "s") return std::make_unique(/*Comment=*/"#"); if (FilesType == "o") - return CreateObjectFileHandler(FirstInput); + return CreateObjectFileHandler(FirstInput, BundlerConfig); if (FilesType == "a") - return CreateObjectFileHandler(FirstInput); + return CreateObjectFileHandler(FirstInput, BundlerConfig); if (FilesType == "gch") - return std::make_unique(); + return std::make_unique(BundlerConfig); if (FilesType == "ast") - return std::make_unique(); + return std::make_unique(BundlerConfig); return createStringError(errc::invalid_argument, "'" + FilesType + "': invalid file type specified"); } // List bundle IDs. Return true if an error was found. -Error ListBundleIDsInFile(StringRef InputFileName) { +Error ListBundleIDsInFile(StringRef InputFileName, Config *BundlerConfig) { // Open Input file. ErrorOr> CodeOrErr = MemoryBuffer::getFileOrSTDIN(InputFileName); @@ -846,7 +845,7 @@ // Select the right files handler. Expected> FileHandlerOrErr = - CreateFileHandler(Input); + CreateFileHandler(Input, BundlerConfig); if (!FileHandlerOrErr) return FileHandlerOrErr.takeError(); @@ -856,18 +855,19 @@ } /// Bundle the files. Return true if an error was found. -Error BundleFiles() { +Error OffloadBundler::BundleFiles() { std::error_code EC; // Create output file. - raw_fd_ostream OutputFile(OutputFileNames.front(), EC, sys::fs::OF_None); + raw_fd_ostream OutputFile(BundlerConfig->OutputFileNames.front(), + EC, sys::fs::OF_None); if (EC) - return createFileError(OutputFileNames.front(), EC); + return createFileError(BundlerConfig->OutputFileNames.front(), EC); // Open input files. SmallVector, 8u> InputBuffers; - InputBuffers.reserve(InputFileNames.size()); - for (auto &I : InputFileNames) { + InputBuffers.reserve(BundlerConfig->InputFileNames.size()); + for (auto &I : BundlerConfig->InputFileNames) { ErrorOr> CodeOrErr = MemoryBuffer::getFileOrSTDIN(I); if (std::error_code EC = CodeOrErr.getError()) @@ -876,10 +876,12 @@ } // Get the file handler. We use the host buffer as reference. - assert((HostInputIndex != ~0u || AllowNoHost) && + assert((BundlerConfig->HostInputIndex != ~0u || BundlerConfig->AllowNoHost) && "Host input index undefined??"); Expected> FileHandlerOrErr = - CreateFileHandler(*InputBuffers[AllowNoHost ? 0 : HostInputIndex]); + CreateFileHandler(*InputBuffers[BundlerConfig->AllowNoHost ? 0 + : BundlerConfig->HostInputIndex], + BundlerConfig); if (!FileHandlerOrErr) return FileHandlerOrErr.takeError(); @@ -893,7 +895,7 @@ // Write all bundles along with the start/end markers. If an error was found // writing the end of the bundle component, abort the bundle writing. auto Input = InputBuffers.begin(); - for (auto &Triple : TargetNames) { + for (auto &Triple : BundlerConfig->TargetNames) { if (Error Err = FH->WriteBundleStart(OutputFile, Triple)) return Err; if (Error Err = FH->WriteBundle(OutputFile, **Input)) @@ -906,18 +908,18 @@ } // Unbundle the files. Return true if an error was found. -Error UnbundleFiles() { +Error OffloadBundler::UnbundleFiles() { // Open Input file. ErrorOr> CodeOrErr = - MemoryBuffer::getFileOrSTDIN(InputFileNames.front()); + MemoryBuffer::getFileOrSTDIN(BundlerConfig->InputFileNames.front()); if (std::error_code EC = CodeOrErr.getError()) - return createFileError(InputFileNames.front(), EC); + return createFileError(BundlerConfig->InputFileNames.front(), EC); MemoryBuffer &Input = **CodeOrErr; // Select the right files handler. Expected> FileHandlerOrErr = - CreateFileHandler(Input); + CreateFileHandler(Input, BundlerConfig); if (!FileHandlerOrErr) return FileHandlerOrErr.takeError(); @@ -930,8 +932,8 @@ // Create a work list that consist of the map triple/output file. StringMap Worklist; - auto Output = OutputFileNames.begin(); - for (auto &Triple : TargetNames) { + auto Output = BundlerConfig->OutputFileNames.begin(); + for (auto &Triple : BundlerConfig->TargetNames) { Worklist[Triple] = *Output; ++Output; } @@ -969,12 +971,12 @@ Worklist.erase(Output); // Record if we found the host bundle. - auto OffloadInfo = OffloadTargetInfo(CurTriple); + auto OffloadInfo = OffloadTargetInfo(CurTriple, BundlerConfig); if (OffloadInfo.hasHostKind()) FoundHostBundle = true; } - if (!AllowMissingBundles && !Worklist.empty()) { + if (!BundlerConfig->AllowMissingBundles && !Worklist.empty()) { std::string ErrMsg = "Can't find bundles for"; std::set Sorted; for (auto &E : Worklist) @@ -995,7 +997,7 @@ // If no bundles were found, assume the input file is the host bundle and // create empty files for the remaining targets. - if (Worklist.size() == TargetNames.size()) { + if (Worklist.size() == BundlerConfig->TargetNames.size()) { for (auto &E : Worklist) { std::error_code EC; raw_fd_ostream OutputFile(E.second, EC, sys::fs::OF_None); @@ -1003,7 +1005,7 @@ return createFileError(E.second, EC); // If this entry has a host kind, copy the input file to the output file. - auto OffloadInfo = OffloadTargetInfo(E.getKey()); + auto OffloadInfo = OffloadTargetInfo(E.getKey(), BundlerConfig); if (OffloadInfo.hasHostKind()) OutputFile.write(Input.getBufferStart(), Input.getBufferSize()); } @@ -1012,7 +1014,7 @@ // If we found elements, we emit an error if none of those were for the host // in case host bundle name was provided in command line. - if (!FoundHostBundle && HostInputIndex != ~0u) + if (!FoundHostBundle && BundlerConfig->HostInputIndex != ~0u) return createStringError(inconvertibleErrorCode(), "Can't find bundle for the host target"); @@ -1083,14 +1085,15 @@ /// @return false, if no compatible target is found. static bool getCompatibleOffloadTargets(OffloadTargetInfo &CodeObjectInfo, - SmallVectorImpl &CompatibleTargets) { + SmallVectorImpl &CompatibleTargets, + Config *BundlerConfig) { if (!CompatibleTargets.empty()) { DEBUG_WITH_TYPE("CodeObjectCompatibility", dbgs() << "CompatibleTargets list should be empty\n"); return false; } - for (auto &Target : TargetNames) { - auto TargetInfo = OffloadTargetInfo(Target); + for (auto &Target : BundlerConfig->TargetNames) { + auto TargetInfo = OffloadTargetInfo(Target, BundlerConfig); if (isCodeObjectCompatible(CodeObjectInfo, TargetInfo)) CompatibleTargets.push_back(Target); } @@ -1104,7 +1107,7 @@ /// particular offload target. The created archive file does not /// contain an index of the symbols and code object files are named as /// <->, with ':' replaced with '_'. -Error UnbundleArchive() { +Error OffloadBundler::UnbundleArchive() { std::vector> ArchiveBuffers; /// Map of target names with list of object files that will form the device @@ -1114,18 +1117,18 @@ // Map of target names and output archive filenames StringMap TargetOutputFileNameMap; - auto Output = OutputFileNames.begin(); - for (auto &Target : TargetNames) { + auto Output = BundlerConfig->OutputFileNames.begin(); + for (auto &Target : BundlerConfig->TargetNames) { TargetOutputFileNameMap[Target] = *Output; ++Output; } - StringRef IFName = InputFileNames.front(); + StringRef IFName = BundlerConfig->InputFileNames.front(); ErrorOr> BufOrErr = MemoryBuffer::getFileOrSTDIN(IFName, true, false); if (std::error_code EC = BufOrErr.getError()) - return createFileError(InputFileNames.front(), EC); + return createFileError(BundlerConfig->InputFileNames.front(), EC); ArchiveBuffers.push_back(std::move(*BufOrErr)); Expected> LibOrErr = @@ -1157,7 +1160,7 @@ MemoryBuffer::getMemBuffer(*CodeObjectBufferRefOrErr, false); Expected> FileHandlerOrErr = - CreateFileHandler(*CodeObjectBuffer); + CreateFileHandler(*CodeObjectBuffer, BundlerConfig); if (!FileHandlerOrErr) return FileHandlerOrErr.takeError(); @@ -1183,11 +1186,12 @@ // archive. while (!CodeObject.empty()) { SmallVector CompatibleTargets; - auto CodeObjectInfo = OffloadTargetInfo(CodeObject); + auto CodeObjectInfo = OffloadTargetInfo(CodeObject, BundlerConfig); if (CodeObjectInfo.hasHostKind()) { // Do nothing, we don't extract host code yet. } else if (getCompatibleOffloadTargets(CodeObjectInfo, - CompatibleTargets)) { + CompatibleTargets, + BundlerConfig)) { std::string BundleData; raw_string_ostream DataStream(BundleData); if (Error Err = @@ -1245,7 +1249,7 @@ assert(!ArchiveErr && "Error occurred while reading archive!"); /// Write out an archive for each target - for (auto &Target : TargetNames) { + for (auto &Target : BundlerConfig->TargetNames) { StringRef FileName = TargetOutputFileNameMap[Target]; StringMapIterator> CurArchiveMembers = OutputArchivesMap.find(Target); @@ -1254,7 +1258,7 @@ true, getDefaultArchiveKindForHost(), true, false, nullptr)) return WriteErr; - } else if (!AllowMissingBundles) { + } else if (!BundlerConfig->AllowMissingBundles) { std::string ErrMsg = Twine("no compatible code object found for the target '" + Target + "' in heterogeneous archive library: " + IFName)