diff options
Diffstat (limited to 'clang/tools/clang-nvlink-wrapper/ClangNvlinkWrapper.cpp')
-rw-r--r-- | clang/tools/clang-nvlink-wrapper/ClangNvlinkWrapper.cpp | 196 |
1 files changed, 0 insertions, 196 deletions
diff --git a/clang/tools/clang-nvlink-wrapper/ClangNvlinkWrapper.cpp b/clang/tools/clang-nvlink-wrapper/ClangNvlinkWrapper.cpp deleted file mode 100644 index bc5b9a9f1fde..000000000000 --- a/clang/tools/clang-nvlink-wrapper/ClangNvlinkWrapper.cpp +++ /dev/null @@ -1,196 +0,0 @@ -//===-- clang-nvlink-wrapper/ClangNvlinkWrapper.cpp - wrapper over nvlink-===// -// -// 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 -// -//===---------------------------------------------------------------------===// -/// -/// \file -/// This tool works as a wrapper over nvlink program. It transparently passes -/// every input option and objects to nvlink except archive files. It reads -/// each input archive file to extract archived cubin files as temporary files. -/// These temp (*.cubin) files are passed to nvlink, because nvlink does not -/// support linking of archive files implicitly. -/// -/// During linking of heterogeneous device archive libraries, the -/// clang-offload-bundler creates a device specific archive of cubin files. -/// Such an archive is then passed to this tool to extract cubin files before -/// passing to nvlink. -/// -/// Example: -/// clang-nvlink-wrapper -o a.out-openmp-nvptx64 /tmp/libTest-nvptx-sm_50.a -/// -/// 1. Extract (libTest-nvptx-sm_50.a) => /tmp/a.cubin /tmp/b.cubin -/// 2. nvlink -o a.out-openmp-nvptx64 /tmp/a.cubin /tmp/b.cubin -//===---------------------------------------------------------------------===// - -#include "clang/Basic/Version.h" -#include "llvm/Object/Archive.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Errc.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/Program.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/StringSaver.h" -#include "llvm/Support/WithColor.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden); - -// Mark all our options with this category, everything else (except for -help) -// will be hidden. -static cl::OptionCategory - ClangNvlinkWrapperCategory("clang-nvlink-wrapper options"); - -static cl::opt<std::string> NvlinkUserPath("nvlink-path", - cl::desc("Path of nvlink binary"), - cl::cat(ClangNvlinkWrapperCategory)); - -// Do not parse nvlink options -static cl::list<std::string> - NVArgs(cl::Sink, cl::desc("<options to be passed to nvlink>...")); - -static Error runNVLink(std::string NVLinkPath, - SmallVectorImpl<std::string> &Args) { - std::vector<StringRef> NVLArgs; - NVLArgs.push_back(NVLinkPath); - for (auto &Arg : Args) { - NVLArgs.push_back(Arg); - } - - if (sys::ExecuteAndWait(NVLinkPath.c_str(), NVLArgs)) - return createStringError(inconvertibleErrorCode(), "'nvlink' failed"); - return Error::success(); -} - -static Error extractArchiveFiles(StringRef Filename, - SmallVectorImpl<std::string> &Args, - SmallVectorImpl<std::string> &TmpFiles) { - std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers; - - ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = - MemoryBuffer::getFileOrSTDIN(Filename, false, false); - if (std::error_code EC = BufOrErr.getError()) - return createFileError(Filename, EC); - - ArchiveBuffers.push_back(std::move(*BufOrErr)); - Expected<std::unique_ptr<llvm::object::Archive>> LibOrErr = - object::Archive::create(ArchiveBuffers.back()->getMemBufferRef()); - if (!LibOrErr) - return LibOrErr.takeError(); - - auto Archive = std::move(*LibOrErr); - - Error Err = Error::success(); - auto ChildEnd = Archive->child_end(); - for (auto ChildIter = Archive->child_begin(Err); ChildIter != ChildEnd; - ++ChildIter) { - if (Err) - return Err; - auto ChildNameOrErr = (*ChildIter).getName(); - if (!ChildNameOrErr) - return ChildNameOrErr.takeError(); - - StringRef ChildName = sys::path::filename(ChildNameOrErr.get()); - - auto ChildBufferRefOrErr = (*ChildIter).getMemoryBufferRef(); - if (!ChildBufferRefOrErr) - return ChildBufferRefOrErr.takeError(); - - auto ChildBuffer = - MemoryBuffer::getMemBuffer(ChildBufferRefOrErr.get(), false); - auto ChildNameSplit = ChildName.split('.'); - - SmallString<16> Path; - int FileDesc; - if (std::error_code EC = sys::fs::createTemporaryFile( - (ChildNameSplit.first), (ChildNameSplit.second), FileDesc, Path)) - return createFileError(ChildName, EC); - - std::string TmpFileName(Path.str()); - Args.push_back(TmpFileName); - TmpFiles.push_back(TmpFileName); - std::error_code EC; - raw_fd_ostream OS(Path.c_str(), EC, sys::fs::OF_None); - if (EC) - return createFileError(TmpFileName, errc::io_error); - OS << ChildBuffer->getBuffer(); - OS.close(); - } - return Err; -} - -static Error cleanupTmpFiles(SmallVectorImpl<std::string> &TmpFiles) { - for (auto &TmpFile : TmpFiles) { - if (std::error_code EC = sys::fs::remove(TmpFile)) - return createFileError(TmpFile, errc::no_such_file_or_directory); - } - return Error::success(); -} - -static void PrintVersion(raw_ostream &OS) { - OS << clang::getClangToolFullVersion("clang-nvlink-wrapper") << '\n'; -} - -int main(int argc, const char **argv) { - sys::PrintStackTraceOnErrorSignal(argv[0]); - cl::SetVersionPrinter(PrintVersion); - cl::HideUnrelatedOptions(ClangNvlinkWrapperCategory); - cl::ParseCommandLineOptions( - argc, argv, - "A wrapper tool over nvlink program. It transparently passes every \n" - "input option and objects to nvlink except archive files and path of \n" - "nvlink binary. It reads each input archive file to extract archived \n" - "cubin files as temporary files.\n"); - - if (Help) { - cl::PrintHelpMessage(); - return 0; - } - - auto reportError = [argv](Error E) { - logAllUnhandledErrors(std::move(E), WithColor::error(errs(), argv[0])); - exit(1); - }; - - std::string NvlinkPath; - SmallVector<const char *, 0> Argv(argv, argv + argc); - SmallVector<std::string, 0> ArgvSubst; - SmallVector<std::string, 0> TmpFiles; - BumpPtrAllocator Alloc; - StringSaver Saver(Alloc); - cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv); - - for (const std::string &Arg : NVArgs) { - if (sys::path::extension(Arg) == ".a") { - if (Error Err = extractArchiveFiles(Arg, ArgvSubst, TmpFiles)) - reportError(std::move(Err)); - } else { - ArgvSubst.push_back(Arg); - } - } - - NvlinkPath = NvlinkUserPath; - - // If user hasn't specified nvlink binary then search it in PATH - if (NvlinkPath.empty()) { - ErrorOr<std::string> NvlinkPathErr = sys::findProgramByName("nvlink"); - if (!NvlinkPathErr) { - reportError(createStringError(NvlinkPathErr.getError(), - "unable to find 'nvlink' in path")); - } - NvlinkPath = NvlinkPathErr.get(); - } - - if (Error Err = runNVLink(NvlinkPath, ArgvSubst)) - reportError(std::move(Err)); - if (Error Err = cleanupTmpFiles(TmpFiles)) - reportError(std::move(Err)); - - return 0; -} |