diff --git a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp index ec6cfb965b4f8..b1bb6d6d3adb0 100644 --- a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp +++ b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp @@ -163,18 +163,6 @@ class FileHandler { /// Read the current bundle and write the result into the stream \a OS. virtual Error ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) = 0; - /// Read the current bundle and write the result into the file \a FileName. - /// The meaning of \a FileName depends on unbundling type - in some - /// cases (type="oo") it will contain a list of actual outputs. - virtual Error ReadBundle(StringRef FileName, MemoryBuffer &Input) { - std::error_code EC; - raw_fd_ostream OS(FileName, EC); - - if (EC) - return createFileError(FileName, EC); - return ReadBundle(OS, Input); - } - /// Write the header of the bundled file to \a OS based on the information /// gathered from \a Inputs. virtual Error WriteHeader(raw_fd_ostream &OS, @@ -354,8 +342,6 @@ class BinaryFileHandler final : public FileHandler { return Error::success(); } - using FileHandler::ReadBundle; // to avoid hiding via the overload below - Error ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final { assert(CurBundleInfo != BundlesInfo.end() && "Invalid reader info!"); StringRef FC = Input.getBuffer(); @@ -638,11 +624,7 @@ class ObjectFileHandler final : public FileHandler { Error ReadBundleEnd(MemoryBuffer &Input) final { return Error::success(); } - Error ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) { - llvm_unreachable("must not be called for the ObjectFileHandler"); - } - - Error ReadBundle(StringRef OutName, MemoryBuffer &Input) final { + Error ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final { assert(CurBundle != TripleToBundleInfo.end() && "all bundles have been read already"); @@ -650,11 +632,6 @@ class ObjectFileHandler final : public FileHandler { // driver is fixed to correctly handle list file for the host bundle in // 'oo' mode. if (FilesType == "oo" && hasHostKind(CurBundle->getKey())) { - std::error_code EC; - raw_fd_ostream OS(OutName, EC); - - if (EC) - return createFileError(OutName, EC); OS.write(Input.getBufferStart(), Input.getBufferSize()); return Error::success(); } @@ -676,35 +653,13 @@ class ObjectFileHandler final : public FileHandler { errc::invalid_argument, "'o' file type is requested, but the fat object contains multiple " "device objects; use 'oo' instead"); - std::string FileList; // Iterate through individual objects and extract them for (size_t I = 0; I < NumObjects; ++I) { uint64_t ObjSize = SizeVec[I]; - // Flag for the special case used to "unbundle" host target object. - bool HostTriple = ObjSize == 1; - - StringRef ObjFileName = OutName; - SmallString<128> Path; - - // If not in file list mode there is no need in a temporary file - output - // goes directly to what was specified in -outputs. The same is true for - // the host triple. - if (FileListMode && !HostTriple) { - std::error_code EC = - sys::fs::createTemporaryFile(TempFileNameBase, "devo", Path); - ObjFileName = Path.data(); - - if (EC) - return createFileError(ObjFileName, EC); - } - std::error_code EC; - raw_fd_ostream OS(ObjFileName, EC); - - if (EC) - return createFileError(ObjFileName, EC); - if (HostTriple) { + // Flag for the special case used to "unbundle" host target object. + if (ObjSize == 1) { // Copy fat object contents to the output when extracting host bundle. // In the partially linked fat object multiple dummy host bundles were @@ -716,26 +671,31 @@ class ObjectFileHandler final : public FileHandler { OS.write(Input.getBufferStart(), Input.getBufferSize()); break; } - OS.write(ObjData, ObjSize); if (FileListMode) { + SmallString<128> ObjFileName; + std::error_code EC = + sys::fs::createTemporaryFile(TempFileNameBase, "devo", ObjFileName); + if (EC) + return createFileError(ObjFileName, EC); + + raw_fd_ostream ObjOS(ObjFileName, EC); + if (EC) + return createFileError(ObjFileName, EC); + + ObjOS.write(ObjData, ObjSize); + if (ObjOS.has_error()) + return createFileError(ObjFileName, ObjOS.error()); + // add the written file name to the output list of files - FileList = (Twine(FileList) + Twine(ObjFileName) + Twine("\n")).str(); - } + OS << ObjFileName << "\n"; + } else + OS.write(ObjData, ObjSize); + // Move "object data" pointer to the next object within the concatenated // bundle. ObjData += ObjSize; } - if (FileListMode) { - // dump the list of files into the file list specified in -outputs for the - // current target - std::error_code EC; - raw_fd_ostream OS1(OutName, EC); - - if (EC) - return createFileError(OutName, EC); - OS1.write(FileList.data(), FileList.size()); - } return Error::success(); } @@ -939,8 +899,6 @@ class TextFileHandler final : public FileHandler { return Error::success(); } - using FileHandler::ReadBundle; // to avoid hiding via the overload below - Error ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final { StringRef FC = Input.getBuffer(); size_t BundleStart = ReadChars; @@ -1056,7 +1014,7 @@ class ArchiveFileHandler final : public FileHandler { Error ReadBundleEnd(MemoryBuffer &Input) override { return Error::success(); } - Error ReadBundle(StringRef OutName, MemoryBuffer &Input) override { + Error ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) override { assert(CurrBundle->second && "attempt to extract nonexistent bundle"); bool FileListMode = FilesType == "aoo"; @@ -1068,11 +1026,6 @@ class ArchiveFileHandler final : public FileHandler { "'ao' file type is requested, but the archive contains multiple " "device objects; use 'aoo' instead"); - // In file-list mode archive unbundling produces multiple files, so output - // file is a file list where we write the unbundled object names. - SmallVector FileListBuf; - raw_svector_ostream FileList{FileListBuf}; - // Read all children. Error Err = Error::success(); for (auto &C : Ar->children(Err)) { @@ -1102,25 +1055,30 @@ class ArchiveFileHandler final : public FileHandler { // This is the bundle we are looking for. Create temporary file where // the device part will be extracted if we are in the file-list mode, // or write directly to the output file otherwise. - SmallString<128u> ChildFileName; if (FileListMode) { + SmallString<128u> ChildFileName; auto EC = sys::fs::createTemporaryFile(TempFileNameBase, "o", ChildFileName); if (EC) return createFileError(ChildFileName, EC); - } else - ChildFileName = OutName; - // And extract the bundle. - if (Error Err = OFH.ReadBundle(ChildFileName, *Buf)) - return Err; - if (Error Err = OFH.ReadBundleEnd(*Buf)) - return Err; + raw_fd_ostream ChildOS(ChildFileName, EC); + if (EC) + return createFileError(ChildFileName, EC); + + if (Error Err = OFH.ReadBundle(ChildOS, *Buf)) + return Err; + + if (ChildOS.has_error()) + return createFileError(ChildFileName, ChildOS.error()); - if (FileListMode) // Add temporary file name with the device part to the output file // list. - FileList << ChildFileName << "\n"; + OS << ChildFileName << "\n"; + } else if (Error Err = OFH.ReadBundle(OS, *Buf)) + return Err; + if (Error Err = OFH.ReadBundleEnd(*Buf)) + return Err; } NameOrErr = OFH.ReadBundleStart(*Buf); if (!NameOrErr) @@ -1129,22 +1087,9 @@ class ArchiveFileHandler final : public FileHandler { } if (Err) return Err; - - if (FileListMode) { - // Dump file list to the output file. - std::error_code EC; - raw_fd_ostream OS(OutName, EC); - if (EC) - return createFileError(OutName, EC); - OS << FileList.str(); - } return Error::success(); } - Error ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) override { - llvm_unreachable("must not be called for the ArchiveFileHandler"); - } - Error WriteHeader(raw_fd_ostream &OS, ArrayRef> Inputs) override { llvm_unreachable("unsupported for the ArchiveFileHandler"); @@ -1323,7 +1268,11 @@ static Error UnbundleFiles() { continue; // Check if the output file can be opened and copy the bundle to it. - if (Error Err = FH->ReadBundle(Output->second, Input)) + std::error_code EC; + raw_fd_ostream OutputFile(Output->second, EC, sys::fs::OF_None); + if (EC) + return createFileError(Output->second, EC); + if (Error Err = FH->ReadBundle(OutputFile, Input)) return Err; if (Error Err = FH->ReadBundleEnd(Input)) return Err;