diff options
Diffstat (limited to 'clang/tools/clang-offload-packager/ClangOffloadPackager.cpp')
-rw-r--r-- | clang/tools/clang-offload-packager/ClangOffloadPackager.cpp | 259 |
1 files changed, 0 insertions, 259 deletions
diff --git a/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp b/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp deleted file mode 100644 index 64b058e..0000000 --- a/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp +++ /dev/null @@ -1,259 +0,0 @@ -//===-- clang-offload-packager/ClangOffloadPackager.cpp - file bundler ---===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===---------------------------------------------------------------------===// -// -// This tool takes several device object files and bundles them into a single -// binary image using a custom binary format. This is intended to be used to -// embed many device files into an application to create a fat binary. -// -//===---------------------------------------------------------------------===// - -#include "clang/Basic/Version.h" - -#include "llvm/ADT/StringExtras.h" -#include "llvm/BinaryFormat/Magic.h" -#include "llvm/Object/ArchiveWriter.h" -#include "llvm/Object/OffloadBinary.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FileOutputBuffer.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/StringSaver.h" -#include "llvm/Support/WithColor.h" - -using namespace llvm; -using namespace llvm::object; - -static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden); - -static cl::OptionCategory - ClangOffloadPackagerCategory("clang-offload-packager options"); - -static cl::opt<std::string> OutputFile("o", cl::desc("Write output to <file>."), - cl::value_desc("file"), - cl::cat(ClangOffloadPackagerCategory)); - -static cl::opt<std::string> InputFile(cl::Positional, - cl::desc("Extract from <file>."), - cl::value_desc("file"), - cl::cat(ClangOffloadPackagerCategory)); - -static cl::list<std::string> - DeviceImages("image", - cl::desc("List of key and value arguments. Required keywords " - "are 'file' and 'triple'."), - cl::value_desc("<key>=<value>,..."), - cl::cat(ClangOffloadPackagerCategory)); - -static cl::opt<bool> - CreateArchive("archive", - cl::desc("Write extracted files to a static archive"), - cl::cat(ClangOffloadPackagerCategory)); - -/// Path of the current binary. -static const char *PackagerExecutable; - -static void PrintVersion(raw_ostream &OS) { - OS << clang::getClangToolFullVersion("clang-offload-packager") << '\n'; -} - -// Get a map containing all the arguments for the image. Repeated arguments will -// be placed in a comma separated list. -static DenseMap<StringRef, StringRef> getImageArguments(StringRef Image, - StringSaver &Saver) { - DenseMap<StringRef, StringRef> Args; - for (StringRef Arg : llvm::split(Image, ",")) { - auto [Key, Value] = Arg.split("="); - auto [It, Inserted] = Args.try_emplace(Key, Value); - if (!Inserted) - It->second = Saver.save(It->second + "," + Value); - } - - return Args; -} - -static Error writeFile(StringRef Filename, StringRef Data) { - Expected<std::unique_ptr<FileOutputBuffer>> OutputOrErr = - FileOutputBuffer::create(Filename, Data.size()); - if (!OutputOrErr) - return OutputOrErr.takeError(); - std::unique_ptr<FileOutputBuffer> Output = std::move(*OutputOrErr); - llvm::copy(Data, Output->getBufferStart()); - if (Error E = Output->commit()) - return E; - return Error::success(); -} - -static Error bundleImages() { - SmallVector<char, 1024> BinaryData; - raw_svector_ostream OS(BinaryData); - for (StringRef Image : DeviceImages) { - BumpPtrAllocator Alloc; - StringSaver Saver(Alloc); - DenseMap<StringRef, StringRef> Args = getImageArguments(Image, Saver); - - if (!Args.count("triple") || !Args.count("file")) - return createStringError( - inconvertibleErrorCode(), - "'file' and 'triple' are required image arguments"); - - // Permit using multiple instances of `file` in a single string. - for (auto &File : llvm::split(Args["file"], ",")) { - OffloadBinary::OffloadingImage ImageBinary{}; - - llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ObjectOrErr = - llvm::MemoryBuffer::getFileOrSTDIN(File); - if (std::error_code EC = ObjectOrErr.getError()) - return errorCodeToError(EC); - - // Clang uses the '.o' suffix for LTO bitcode. - if (identify_magic((*ObjectOrErr)->getBuffer()) == file_magic::bitcode) - ImageBinary.TheImageKind = object::IMG_Bitcode; - else - ImageBinary.TheImageKind = - getImageKind(sys::path::extension(File).drop_front()); - ImageBinary.Image = std::move(*ObjectOrErr); - for (const auto &[Key, Value] : Args) { - if (Key == "kind") { - ImageBinary.TheOffloadKind = getOffloadKind(Value); - } else if (Key != "file") { - ImageBinary.StringData[Key] = Value; - } - } - llvm::SmallString<0> Buffer = OffloadBinary::write(ImageBinary); - if (Buffer.size() % OffloadBinary::getAlignment() != 0) - return createStringError(inconvertibleErrorCode(), - "Offload binary has invalid size alignment"); - OS << Buffer; - } - } - - if (Error E = writeFile(OutputFile, - StringRef(BinaryData.begin(), BinaryData.size()))) - return E; - return Error::success(); -} - -static Error unbundleImages() { - ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = - MemoryBuffer::getFileOrSTDIN(InputFile); - if (std::error_code EC = BufferOrErr.getError()) - return createFileError(InputFile, EC); - std::unique_ptr<MemoryBuffer> Buffer = std::move(*BufferOrErr); - - // This data can be misaligned if extracted from an archive. - if (!isAddrAligned(Align(OffloadBinary::getAlignment()), - Buffer->getBufferStart())) - Buffer = MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), - Buffer->getBufferIdentifier()); - - SmallVector<OffloadFile> Binaries; - if (Error Err = extractOffloadBinaries(*Buffer, Binaries)) - return Err; - - // Try to extract each device image specified by the user from the input file. - for (StringRef Image : DeviceImages) { - BumpPtrAllocator Alloc; - StringSaver Saver(Alloc); - auto Args = getImageArguments(Image, Saver); - - SmallVector<const OffloadBinary *> Extracted; - for (const OffloadFile &File : Binaries) { - const auto *Binary = File.getBinary(); - // We handle the 'file' and 'kind' identifiers differently. - bool Match = llvm::all_of(Args, [&](auto &Arg) { - const auto [Key, Value] = Arg; - if (Key == "file") - return true; - if (Key == "kind") - return Binary->getOffloadKind() == getOffloadKind(Value); - return Binary->getString(Key) == Value; - }); - if (Match) - Extracted.push_back(Binary); - } - - if (Extracted.empty()) - continue; - - if (CreateArchive) { - if (!Args.count("file")) - return createStringError(inconvertibleErrorCode(), - "Image must have a 'file' argument."); - - SmallVector<NewArchiveMember> Members; - for (const OffloadBinary *Binary : Extracted) - Members.emplace_back(MemoryBufferRef( - Binary->getImage(), - Binary->getMemoryBufferRef().getBufferIdentifier())); - - if (Error E = writeArchive( - Args["file"], Members, SymtabWritingMode::NormalSymtab, - Archive::getDefaultKind(), true, false, nullptr)) - return E; - } else if (auto It = Args.find("file"); It != Args.end()) { - if (Extracted.size() > 1) - WithColor::warning(errs(), PackagerExecutable) - << "Multiple inputs match to a single file, '" << It->second - << "'\n"; - if (Error E = writeFile(It->second, Extracted.back()->getImage())) - return E; - } else { - uint64_t Idx = 0; - for (const OffloadBinary *Binary : Extracted) { - StringRef Filename = - Saver.save(sys::path::stem(InputFile) + "-" + Binary->getTriple() + - "-" + Binary->getArch() + "." + std::to_string(Idx++) + - "." + getImageKindName(Binary->getImageKind())); - if (Error E = writeFile(Filename, Binary->getImage())) - return E; - } - } - } - - return Error::success(); -} - -int main(int argc, const char **argv) { - sys::PrintStackTraceOnErrorSignal(argv[0]); - cl::HideUnrelatedOptions(ClangOffloadPackagerCategory); - cl::SetVersionPrinter(PrintVersion); - cl::ParseCommandLineOptions( - argc, argv, - "A utility for bundling several object files into a single binary.\n" - "The output binary can then be embedded into the host section table\n" - "to create a fatbinary containing offloading code.\n"); - - if (Help) { - cl::PrintHelpMessage(); - return EXIT_SUCCESS; - } - - PackagerExecutable = argv[0]; - auto reportError = [argv](Error E) { - logAllUnhandledErrors(std::move(E), WithColor::error(errs(), argv[0])); - return EXIT_FAILURE; - }; - - if (!InputFile.empty() && !OutputFile.empty()) - return reportError( - createStringError(inconvertibleErrorCode(), - "Packaging to an output file and extracting from an " - "input file are mutually exclusive.")); - - if (!OutputFile.empty()) { - if (Error Err = bundleImages()) - return reportError(std::move(Err)); - } else if (!InputFile.empty()) { - if (Error Err = unbundleImages()) - return reportError(std::move(Err)); - } - - return EXIT_SUCCESS; -} |