lamb-j created this revision.
lamb-j added reviewers: kzhuravl, scott.linder, yaxunl.
Herald added a reviewer: alexander-shaposhnikov.
Herald added a project: All.
lamb-j requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Lifting the core functionalities of the clang-offload-bundler into a
user-facing library/API.

This patch (2/4) introduces a Config class that locally stores the
previously global cl::opt options and arrays. This localization
will allow users to call the APIs in a multi-threaded context. This
patch also introduces an OffloadBundler class to encapsulate the
top-level API functions.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D129303

Files:
  clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
  clang/tools/clang-offload-bundler/OffloadBundler.cpp
  clang/tools/clang-offload-bundler/OffloadBundler.h

Index: clang/tools/clang-offload-bundler/OffloadBundler.h
===================================================================
--- clang/tools/clang-offload-bundler/OffloadBundler.h
+++ 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<std::string> TargetNames;
+  std::vector<std::string> InputFileNames;
+  std::vector<std::string> 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);
Index: clang/tools/clang-offload-bundler/OffloadBundler.cpp
===================================================================
--- clang/tools/clang-offload-bundler/OffloadBundler.cpp
+++ clang/tools/clang-offload-bundler/OffloadBundler.cpp
@@ -58,28 +58,12 @@
 using namespace llvm;
 using namespace llvm::object;
 
-extern cl::list<std::string> InputFileNames;
-extern cl::list<std::string> OutputFileNames;
-extern cl::list<std::string> TargetNames;
-extern cl::opt<std::string> FilesType;
-extern cl::opt<bool> PrintExternalCommands;
-extern cl::opt<bool> AllowMissingBundles;
-extern cl::opt<unsigned> BundleAlignment;
-extern cl::opt<bool> 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<ObjectFile> ObjIn)
+  // TODO: Add error checking from ClangOffloadBundler.cpp
+  ObjectFileHandler(std::unique_ptr<ObjectFile> 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<std::unique_ptr<MemoryBuffer>> 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<std::string> 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<StringRef, 8u> 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<StringRef> Args) {
+  Error executeObjcopy(StringRef Objcopy, ArrayRef<StringRef> 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<FileHandler>
-CreateObjectFileHandler(MemoryBuffer &FirstInput) {
+CreateObjectFileHandler(MemoryBuffer &FirstInput, Config *BundlerConfig) {
   // Check if the input file format is one that we know how to deal with.
   Expected<std::unique_ptr<Binary>> 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<ObjectFile>(*BinaryOrErr))
-    return std::make_unique<BinaryFileHandler>();
+    return std::make_unique<BinaryFileHandler>(BundlerConfig);
 
   // Otherwise create an object file handler. The handler will be owned by the
   // client of this function.
   return std::make_unique<ObjectFileHandler>(
-      std::unique_ptr<ObjectFile>(cast<ObjectFile>(BinaryOrErr->release())));
+      std::unique_ptr<ObjectFile>(cast<ObjectFile>(BinaryOrErr->release())),
+      BundlerConfig);
 }
 
 /// Return an appropriate handler given the input files and options.
 static Expected<std::unique_ptr<FileHandler>>
-CreateFileHandler(MemoryBuffer &FirstInput) {
+CreateFileHandler(MemoryBuffer &FirstInput, Config *BundlerConfig) {
+  std::string FilesType = BundlerConfig->FilesType;
+
   if (FilesType == "i")
     return std::make_unique<TextFileHandler>(/*Comment=*/"//");
   if (FilesType == "ii")
@@ -818,24 +817,24 @@
   if (FilesType == "ll")
     return std::make_unique<TextFileHandler>(/*Comment=*/";");
   if (FilesType == "bc")
-    return std::make_unique<BinaryFileHandler>();
+    return std::make_unique<BinaryFileHandler>(BundlerConfig);
   if (FilesType == "s")
     return std::make_unique<TextFileHandler>(/*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<BinaryFileHandler>();
+    return std::make_unique<BinaryFileHandler>(BundlerConfig);
   if (FilesType == "ast")
-    return std::make_unique<BinaryFileHandler>();
+    return std::make_unique<BinaryFileHandler>(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<std::unique_ptr<MemoryBuffer>> CodeOrErr =
       MemoryBuffer::getFileOrSTDIN(InputFileName);
@@ -846,7 +845,7 @@
 
   // Select the right files handler.
   Expected<std::unique_ptr<FileHandler>> 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<std::unique_ptr<MemoryBuffer>, 8u> InputBuffers;
-  InputBuffers.reserve(InputFileNames.size());
-  for (auto &I : InputFileNames) {
+  InputBuffers.reserve(BundlerConfig->InputFileNames.size());
+  for (auto &I : BundlerConfig->InputFileNames) {
     ErrorOr<std::unique_ptr<MemoryBuffer>> 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<std::unique_ptr<FileHandler>> 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<std::unique_ptr<MemoryBuffer>> 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<std::unique_ptr<FileHandler>> 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<StringRef> 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<StringRef> 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<StringRef> &CompatibleTargets) {
+                            SmallVectorImpl<StringRef> &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
 /// <<Parent Bundle Name>-<CodeObject's GPUArch>>, with ':' replaced with '_'.
-Error UnbundleArchive() {
+Error OffloadBundler::UnbundleArchive() {
   std::vector<std::unique_ptr<MemoryBuffer>> 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<StringRef> 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<std::unique_ptr<MemoryBuffer>> 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<std::unique_ptr<llvm::object::Archive>> LibOrErr =
@@ -1157,7 +1160,7 @@
         MemoryBuffer::getMemBuffer(*CodeObjectBufferRefOrErr, false);
 
     Expected<std::unique_ptr<FileHandler>> FileHandlerOrErr =
-        CreateFileHandler(*CodeObjectBuffer);
+        CreateFileHandler(*CodeObjectBuffer, BundlerConfig);
     if (!FileHandlerOrErr)
       return FileHandlerOrErr.takeError();
 
@@ -1183,11 +1186,12 @@
     // archive.
     while (!CodeObject.empty()) {
       SmallVector<StringRef> 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<std::vector<llvm::NewArchiveMember>> 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)
Index: clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
===================================================================
--- clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
+++ clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
@@ -57,37 +57,42 @@
 using namespace llvm;
 using namespace llvm::object;
 
-static cl::opt<bool> 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<bool> 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<std::string>
+  cl::list<std::string>
     InputFileNames("input", cl::ZeroOrMore,
                    cl::desc("Input file."
                             " Can be specified multiple times "
                             "for multiple input files."),
                    cl::cat(ClangOffloadBundlerCategory));
-static cl::list<std::string>
+  cl::list<std::string>
     InputFileNamesDeprecatedOpt("inputs", cl::CommaSeparated, cl::ZeroOrMore,
                                 cl::desc("[<input file>,...] (deprecated)"),
                                 cl::cat(ClangOffloadBundlerCategory));
-cl::list<std::string>
+  cl::list<std::string>
     OutputFileNames("output", cl::ZeroOrMore,
                     cl::desc("Output file."
                              " Can be specified multiple times "
                              "for multiple output files."),
                     cl::cat(ClangOffloadBundlerCategory));
-static cl::list<std::string>
+  cl::list<std::string>
     OutputFileNamesDeprecatedOpt("outputs", cl::CommaSeparated, cl::ZeroOrMore,
                                  cl::desc("[<output file>,...] (deprecated)"),
                                  cl::cat(ClangOffloadBundlerCategory));
-cl::list<std::string>
+  cl::list<std::string>
     TargetNames("targets", cl::CommaSeparated,
                 cl::desc("[<offload kind>-<target triple>,...]"),
                 cl::cat(ClangOffloadBundlerCategory));
-cl::opt<std::string>
+  cl::opt<std::string>
     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<bool>
+  cl::opt<bool>
     Unbundle("unbundle",
              cl::desc("Unbundle bundled file into several output files.\n"),
              cl::init(false), cl::cat(ClangOffloadBundlerCategory));
 
-cl::opt<bool>
+  cl::opt<bool>
     ListBundleIDs("list", cl::desc("List bundle IDs in the bundled file.\n"),
                   cl::init(false), cl::cat(ClangOffloadBundlerCategory));
 
-cl::opt<bool> PrintExternalCommands(
+  cl::opt<bool> 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<bool>
+  cl::opt<bool>
     AllowMissingBundles("allow-missing-bundles",
                         cl::desc("Create empty files if bundles are missing "
                                  "when unbundling.\n"),
                         cl::init(false), cl::cat(ClangOffloadBundlerCategory));
 
-cl::opt<unsigned>
+  cl::opt<unsigned>
     BundleAlignment("bundle-align",
                     cl::desc("Alignment of bundle for binary files"),
                     cl::init(1), cl::cat(ClangOffloadBundlerCategory));
 
-cl::opt<bool> HipOpenmpCompatible(
+  cl::opt<bool> 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<llvm::Error()> 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;
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D129303: [clang-offl... Jacob Lambert via Phabricator via cfe-commits

Reply via email to