diff --git a/llvm/test/tools/llvm-orderfile/help.test b/llvm/test/tools/llvm-orderfile/help.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-orderfile/help.test @@ -0,0 +1,3 @@ +RUN: llvm-orderfile --help 2>&1 | FileCheck %s +CHECK: Generic Options: +CHECK: llvm-orderfile Options: diff --git a/llvm/test/tools/llvm-orderfile/mapping.data b/llvm/test/tools/llvm-orderfile/mapping.data new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-orderfile/mapping.data @@ -0,0 +1,6 @@ +MD5 b84cbfeff0d303b4 too +MD5 786da535fe6cbd2 zoo +MD5 db956436e78dd5fa main +MD5 b84cbfeff0d303b4 too +MD5 786da535fe6cbd2 zoo +MD5 db956436e78dd5fa main diff --git a/llvm/test/tools/llvm-orderfile/order.data b/llvm/test/tools/llvm-orderfile/order.data new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@&1 | FileCheck %s +CHECK: main +CHECK-NEXT: zoo +CHECK-NEXT: too diff --git a/llvm/tools/llvm-orderfile/CMakeLists.txt b/llvm/tools/llvm-orderfile/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-orderfile/CMakeLists.txt @@ -0,0 +1,7 @@ +set(LLVM_LINK_COMPONENTS + Support + ) + +add_llvm_tool(llvm-orderfile + llvm-orderfile.cpp + ) diff --git a/llvm/tools/llvm-orderfile/llvm-orderfile.cpp b/llvm/tools/llvm-orderfile/llvm-orderfile.cpp new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-orderfile/llvm-orderfile.cpp @@ -0,0 +1,116 @@ +//===- llvm-cat.cpp - LLVM module concatenation utility -------------------===// +// +// 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 program is for testing features that rely on multi-module bitcode files. +// It takes a list of input modules and uses them to create a multi-module +// bitcode file. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +#include + +using namespace llvm; + +cl::OptionCategory OrderfileCategory("llvm-orderfile Options"); + +static cl::opt OutputFilename("o", + cl::desc("Output filename"), + cl::value_desc("filename"), + cl::cat(OrderfileCategory)); + +static cl::opt BinaryOrderFile(cl::Positional, + cl::desc(""), + cl::cat(OrderfileCategory)); + +static cl::opt MappingFile(cl::Positional, + cl::desc(""), + cl::cat(OrderfileCategory)); + +static cl::opt Verbose("v", cl::desc("verbose output"), + cl::cat(OrderfileCategory)); + + +static void DumpOrderFile(MemoryBuffer& BO, DenseMap const& Mapping, raw_ostream & OS) +{ + StringRef BinaryOrder = BO.getBuffer(); + constexpr size_t BinaryOrderElementSize = 8; + for(size_t i = 0; i < BinaryOrder.size(); i += BinaryOrderElementSize) { + uint64_t Elt; + StringRef HexElt = BinaryOrder.substr(i, BinaryOrderElementSize); + std::memcpy(&Elt, HexElt.data(), sizeof(Elt)); + auto Where = Mapping.find(Elt); + if (Where != Mapping.end()) + OS << Where->second << "\n"; + else if (Verbose && Elt) { + llvm::errs() << "no mapping found for entry "; + llvm::errs().write_hex(Elt); + llvm::errs() << "\n"; + } + } +} + + +int main(int argc, char **argv) { + cl::HideUnrelatedOptions(OrderfileCategory); + cl::ParseCommandLineOptions(argc, argv, "Orderfile manipulation"); + + ExitOnError ExitOnErr("llvm-orderfile: "); + + std::unique_ptr MF = ExitOnErr( + errorOrToExpected(MemoryBuffer::getFileOrSTDIN(MappingFile))); + + StringRef MappingStream(MF->getBuffer()); + SmallVector MappingLines; + MappingStream.split(MappingLines, /*Separator=*/'\n', /*MaxSplit=*/-1, /*KeepEmpty=*/false); + + DenseMap Mapping; + SmallVector Tokens; + for(unsigned LineIndex = 0; LineIndex < MappingLines.size(); ++LineIndex) { + StringRef Line = MappingLines[LineIndex]; + Line.split(Tokens, /*Separator=*/' '); + if (Tokens.size() != 3) { + llvm::errs() << MappingFile << ':' << (1 + LineIndex) << ": has invalid format\n"; + llvm::errs() << "when parsing: " << Line << "\n"; + return 1; + } + uint64_t Val; + Tokens[1].getAsInteger(16, Val); + Mapping[Val] = Tokens[2]; + Tokens.clear(); + } + + if(Verbose) + llvm::errs() << "Found " << Mapping.size() << " mappings.\n"; + + std::unique_ptr BO = ExitOnErr( + errorOrToExpected(MemoryBuffer::getFile(BinaryOrderFile))); + + if (OutputFilename.empty()) { + DumpOrderFile(*BO, Mapping, llvm::outs()); + } + else { + std::error_code EC; + raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::OF_None); + if (EC) { + errs() << argv[0] << ": cannot open " << OutputFilename << " for writing: " + << EC.message(); + return 1; + } + DumpOrderFile(*BO, Mapping, OS); + } + + + return 0; +}