aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/CodeGenData
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2024-08-25 11:12:58 +0000
committerDimitry Andric <dim@FreeBSD.org>2024-10-23 18:27:07 +0000
commit62987288060ff68c817b7056815aa9fb8ba8ecd7 (patch)
treed7953c9488f71e79d26c924169988f16e9ba9cee /contrib/llvm-project/llvm/lib/CodeGenData
parent52418fc2be8efa5172b90a3a9e617017173612c4 (diff)
parentadf62863f35c84e4c5708f3dc5a1589ce958a238 (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGenData')
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGenData/CodeGenData.cpp196
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGenData/CodeGenDataReader.cpp175
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGenData/CodeGenDataWriter.cpp162
3 files changed, 0 insertions, 533 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGenData/CodeGenData.cpp b/contrib/llvm-project/llvm/lib/CodeGenData/CodeGenData.cpp
deleted file mode 100644
index 49b744744095..000000000000
--- a/contrib/llvm-project/llvm/lib/CodeGenData/CodeGenData.cpp
+++ /dev/null
@@ -1,196 +0,0 @@
-//===-- CodeGenData.cpp ---------------------------------------------------===//
-//
-// 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 file contains support for codegen data that has stable summary which
-// can be used to optimize the code in the subsequent codegen.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Bitcode/BitcodeWriter.h"
-#include "llvm/CodeGenData/CodeGenDataReader.h"
-#include "llvm/CodeGenData/OutlinedHashTreeRecord.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/WithColor.h"
-
-#define DEBUG_TYPE "cg-data"
-
-using namespace llvm;
-using namespace cgdata;
-
-static std::string getCGDataErrString(cgdata_error Err,
- const std::string &ErrMsg = "") {
- std::string Msg;
- raw_string_ostream OS(Msg);
-
- switch (Err) {
- case cgdata_error::success:
- OS << "success";
- break;
- case cgdata_error::eof:
- OS << "end of File";
- break;
- case cgdata_error::bad_magic:
- OS << "invalid codegen data (bad magic)";
- break;
- case cgdata_error::bad_header:
- OS << "invalid codegen data (file header is corrupt)";
- break;
- case cgdata_error::empty_cgdata:
- OS << "empty codegen data";
- break;
- case cgdata_error::malformed:
- OS << "malformed codegen data";
- break;
- case cgdata_error::unsupported_version:
- OS << "unsupported codegen data version";
- break;
- }
-
- // If optional error message is not empty, append it to the message.
- if (!ErrMsg.empty())
- OS << ": " << ErrMsg;
-
- return OS.str();
-}
-
-namespace {
-
-// FIXME: This class is only here to support the transition to llvm::Error. It
-// will be removed once this transition is complete. Clients should prefer to
-// deal with the Error value directly, rather than converting to error_code.
-class CGDataErrorCategoryType : public std::error_category {
- const char *name() const noexcept override { return "llvm.cgdata"; }
-
- std::string message(int IE) const override {
- return getCGDataErrString(static_cast<cgdata_error>(IE));
- }
-};
-
-} // end anonymous namespace
-
-const std::error_category &llvm::cgdata_category() {
- static CGDataErrorCategoryType ErrorCategory;
- return ErrorCategory;
-}
-
-std::string CGDataError::message() const {
- return getCGDataErrString(Err, Msg);
-}
-
-char CGDataError::ID = 0;
-
-namespace {
-
-const char *CodeGenDataSectNameCommon[] = {
-#define CG_DATA_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \
- SectNameCommon,
-#include "llvm/CodeGenData/CodeGenData.inc"
-};
-
-const char *CodeGenDataSectNameCoff[] = {
-#define CG_DATA_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \
- SectNameCoff,
-#include "llvm/CodeGenData/CodeGenData.inc"
-};
-
-const char *CodeGenDataSectNamePrefix[] = {
-#define CG_DATA_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) Prefix,
-#include "llvm/CodeGenData/CodeGenData.inc"
-};
-
-} // namespace
-
-namespace llvm {
-
-std::string getCodeGenDataSectionName(CGDataSectKind CGSK,
- Triple::ObjectFormatType OF,
- bool AddSegmentInfo) {
- std::string SectName;
-
- if (OF == Triple::MachO && AddSegmentInfo)
- SectName = CodeGenDataSectNamePrefix[CGSK];
-
- if (OF == Triple::COFF)
- SectName += CodeGenDataSectNameCoff[CGSK];
- else
- SectName += CodeGenDataSectNameCommon[CGSK];
-
- return SectName;
-}
-
-std::unique_ptr<CodeGenData> CodeGenData::Instance = nullptr;
-std::once_flag CodeGenData::OnceFlag;
-
-CodeGenData &CodeGenData::getInstance() {
- std::call_once(CodeGenData::OnceFlag, []() {
- Instance = std::unique_ptr<CodeGenData>(new CodeGenData());
-
- // TODO: Initialize writer or reader mode for the client optimization.
- });
- return *(Instance.get());
-}
-
-namespace IndexedCGData {
-
-Expected<Header> Header::readFromBuffer(const unsigned char *Curr) {
- using namespace support;
-
- static_assert(std::is_standard_layout_v<llvm::IndexedCGData::Header>,
- "The header should be standard layout type since we use offset "
- "of fields to read.");
- Header H;
- H.Magic = endian::readNext<uint64_t, endianness::little, unaligned>(Curr);
- if (H.Magic != IndexedCGData::Magic)
- return make_error<CGDataError>(cgdata_error::bad_magic);
- H.Version = endian::readNext<uint32_t, endianness::little, unaligned>(Curr);
- if (H.Version > IndexedCGData::CGDataVersion::CurrentVersion)
- return make_error<CGDataError>(cgdata_error::unsupported_version);
- H.DataKind = endian::readNext<uint32_t, endianness::little, unaligned>(Curr);
-
- switch (H.Version) {
- // When a new field is added to the header add a case statement here to
- // compute the size as offset of the new field + size of the new field. This
- // relies on the field being added to the end of the list.
- static_assert(IndexedCGData::CGDataVersion::CurrentVersion == Version1,
- "Please update the size computation below if a new field has "
- "been added to the header, if not add a case statement to "
- "fall through to the latest version.");
- case 1ull:
- H.OutlinedHashTreeOffset =
- endian::readNext<uint64_t, endianness::little, unaligned>(Curr);
- }
-
- return H;
-}
-
-} // end namespace IndexedCGData
-
-namespace cgdata {
-
-void warn(Twine Message, std::string Whence, std::string Hint) {
- WithColor::warning();
- if (!Whence.empty())
- errs() << Whence << ": ";
- errs() << Message << "\n";
- if (!Hint.empty())
- WithColor::note() << Hint << "\n";
-}
-
-void warn(Error E, StringRef Whence) {
- if (E.isA<CGDataError>()) {
- handleAllErrors(std::move(E), [&](const CGDataError &IPE) {
- warn(IPE.message(), Whence.str(), "");
- });
- }
-}
-
-} // end namespace cgdata
-
-} // end namespace llvm
diff --git a/contrib/llvm-project/llvm/lib/CodeGenData/CodeGenDataReader.cpp b/contrib/llvm-project/llvm/lib/CodeGenData/CodeGenDataReader.cpp
deleted file mode 100644
index bcd61047079f..000000000000
--- a/contrib/llvm-project/llvm/lib/CodeGenData/CodeGenDataReader.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-//===- CodeGenDataReader.cpp ----------------------------------------------===//
-//
-// 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 file contains support for reading codegen data.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CodeGenData/CodeGenDataReader.h"
-#include "llvm/CodeGenData/OutlinedHashTreeRecord.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/MemoryBuffer.h"
-
-#define DEBUG_TYPE "cg-data-reader"
-
-using namespace llvm;
-
-namespace llvm {
-
-static Expected<std::unique_ptr<MemoryBuffer>>
-setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS) {
- auto BufferOrErr = Filename.str() == "-" ? MemoryBuffer::getSTDIN()
- : FS.getBufferForFile(Filename);
- if (std::error_code EC = BufferOrErr.getError())
- return errorCodeToError(EC);
- return std::move(BufferOrErr.get());
-}
-
-Error CodeGenDataReader::mergeFromObjectFile(
- const object::ObjectFile *Obj,
- OutlinedHashTreeRecord &GlobalOutlineRecord) {
- Triple TT = Obj->makeTriple();
- auto CGOutLineName =
- getCodeGenDataSectionName(CG_outline, TT.getObjectFormat(), false);
-
- for (auto &Section : Obj->sections()) {
- Expected<StringRef> NameOrErr = Section.getName();
- if (!NameOrErr)
- return NameOrErr.takeError();
- Expected<StringRef> ContentsOrErr = Section.getContents();
- if (!ContentsOrErr)
- return ContentsOrErr.takeError();
- auto *Data = reinterpret_cast<const unsigned char *>(ContentsOrErr->data());
- auto *EndData = Data + ContentsOrErr->size();
-
- if (*NameOrErr == CGOutLineName) {
- // In case dealing with an executable that has concatenated cgdata,
- // we want to merge them into a single cgdata.
- // Although it's not a typical workflow, we support this scenario.
- while (Data != EndData) {
- OutlinedHashTreeRecord LocalOutlineRecord;
- LocalOutlineRecord.deserialize(Data);
- GlobalOutlineRecord.merge(LocalOutlineRecord);
- }
- }
- // TODO: Add support for other cgdata sections.
- }
-
- return Error::success();
-}
-
-Error IndexedCodeGenDataReader::read() {
- using namespace support;
-
- // The smallest header with the version 1 is 24 bytes
- const unsigned MinHeaderSize = 24;
- if (DataBuffer->getBufferSize() < MinHeaderSize)
- return error(cgdata_error::bad_header);
-
- auto *Start =
- reinterpret_cast<const unsigned char *>(DataBuffer->getBufferStart());
- auto *End =
- reinterpret_cast<const unsigned char *>(DataBuffer->getBufferEnd());
- if (auto E = IndexedCGData::Header::readFromBuffer(Start).moveInto(Header))
- return E;
-
- if (hasOutlinedHashTree()) {
- const unsigned char *Ptr = Start + Header.OutlinedHashTreeOffset;
- if (Ptr >= End)
- return error(cgdata_error::eof);
- HashTreeRecord.deserialize(Ptr);
- }
-
- return success();
-}
-
-Expected<std::unique_ptr<CodeGenDataReader>>
-CodeGenDataReader::create(const Twine &Path, vfs::FileSystem &FS) {
- // Set up the buffer to read.
- auto BufferOrError = setupMemoryBuffer(Path, FS);
- if (Error E = BufferOrError.takeError())
- return std::move(E);
- return CodeGenDataReader::create(std::move(BufferOrError.get()));
-}
-
-Expected<std::unique_ptr<CodeGenDataReader>>
-CodeGenDataReader::create(std::unique_ptr<MemoryBuffer> Buffer) {
- if (Buffer->getBufferSize() == 0)
- return make_error<CGDataError>(cgdata_error::empty_cgdata);
-
- std::unique_ptr<CodeGenDataReader> Reader;
- // Create the reader.
- if (IndexedCodeGenDataReader::hasFormat(*Buffer))
- Reader = std::make_unique<IndexedCodeGenDataReader>(std::move(Buffer));
- else if (TextCodeGenDataReader::hasFormat(*Buffer))
- Reader = std::make_unique<TextCodeGenDataReader>(std::move(Buffer));
- else
- return make_error<CGDataError>(cgdata_error::malformed);
-
- // Initialize the reader and return the result.
- if (Error E = Reader->read())
- return std::move(E);
-
- return std::move(Reader);
-}
-
-bool IndexedCodeGenDataReader::hasFormat(const MemoryBuffer &DataBuffer) {
- using namespace support;
- if (DataBuffer.getBufferSize() < sizeof(IndexedCGData::Magic))
- return false;
-
- uint64_t Magic = endian::read<uint64_t, llvm::endianness::little, aligned>(
- DataBuffer.getBufferStart());
- // Verify that it's magical.
- return Magic == IndexedCGData::Magic;
-}
-
-bool TextCodeGenDataReader::hasFormat(const MemoryBuffer &Buffer) {
- // Verify that this really looks like plain ASCII text by checking a
- // 'reasonable' number of characters (up to the magic size).
- StringRef Prefix = Buffer.getBuffer().take_front(sizeof(uint64_t));
- return llvm::all_of(Prefix, [](char c) { return isPrint(c) || isSpace(c); });
-}
-Error TextCodeGenDataReader::read() {
- using namespace support;
-
- // Parse the custom header line by line.
- for (; !Line.is_at_eof(); ++Line) {
- // Skip empty or whitespace-only lines
- if (Line->trim().empty())
- continue;
-
- if (!Line->starts_with(":"))
- break;
- StringRef Str = Line->drop_front().rtrim();
- if (Str.equals_insensitive("outlined_hash_tree"))
- DataKind |= CGDataKind::FunctionOutlinedHashTree;
- else
- return error(cgdata_error::bad_header);
- }
-
- // We treat an empty header (that is a comment # only) as a valid header.
- if (Line.is_at_eof()) {
- if (DataKind == CGDataKind::Unknown)
- return Error::success();
- return error(cgdata_error::bad_header);
- }
-
- // The YAML docs follow after the header.
- const char *Pos = Line->data();
- size_t Size = reinterpret_cast<size_t>(DataBuffer->getBufferEnd()) -
- reinterpret_cast<size_t>(Pos);
- yaml::Input YOS(StringRef(Pos, Size));
- if (hasOutlinedHashTree())
- HashTreeRecord.deserializeYAML(YOS);
-
- // TODO: Add more yaml cgdata in order
-
- return Error::success();
-}
-} // end namespace llvm
diff --git a/contrib/llvm-project/llvm/lib/CodeGenData/CodeGenDataWriter.cpp b/contrib/llvm-project/llvm/lib/CodeGenData/CodeGenDataWriter.cpp
deleted file mode 100644
index 3c91a1b30345..000000000000
--- a/contrib/llvm-project/llvm/lib/CodeGenData/CodeGenDataWriter.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-//===- CodeGenDataWriter.cpp ----------------------------------------------===//
-//
-// 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 file contains support for writing codegen data.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CodeGenData/CodeGenDataWriter.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/EndianStream.h"
-
-#define DEBUG_TYPE "cg-data-writer"
-
-using namespace llvm;
-
-namespace llvm {
-
-/// A struct to define how the data stream should be patched.
-struct CGDataPatchItem {
- uint64_t Pos; // Where to patch.
- uint64_t *D; // Pointer to an array of source data.
- int N; // Number of elements in \c D array.
-};
-
-// A wrapper class to abstract writer stream with support of bytes
-// back patching.
-class CGDataOStream {
-public:
- CGDataOStream(raw_fd_ostream &FD)
- : IsFDOStream(true), OS(FD), LE(FD, llvm::endianness::little) {}
- CGDataOStream(raw_string_ostream &STR)
- : IsFDOStream(false), OS(STR), LE(STR, llvm::endianness::little) {}
-
- uint64_t tell() { return OS.tell(); }
- void write(uint64_t V) { LE.write<uint64_t>(V); }
- void write32(uint32_t V) { LE.write<uint32_t>(V); }
- void write8(uint8_t V) { LE.write<uint8_t>(V); }
-
- // \c patch can only be called when all data is written and flushed.
- // For raw_string_ostream, the patch is done on the target string
- // directly and it won't be reflected in the stream's internal buffer.
- void patch(ArrayRef<CGDataPatchItem> P) {
- using namespace support;
-
- if (IsFDOStream) {
- raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS);
- const uint64_t LastPos = FDOStream.tell();
- for (const auto &K : P) {
- FDOStream.seek(K.Pos);
- for (int I = 0; I < K.N; I++)
- write(K.D[I]);
- }
- // Reset the stream to the last position after patching so that users
- // don't accidentally overwrite data. This makes it consistent with
- // the string stream below which replaces the data directly.
- FDOStream.seek(LastPos);
- } else {
- raw_string_ostream &SOStream = static_cast<raw_string_ostream &>(OS);
- std::string &Data = SOStream.str(); // with flush
- for (const auto &K : P) {
- for (int I = 0; I < K.N; I++) {
- uint64_t Bytes =
- endian::byte_swap<uint64_t, llvm::endianness::little>(K.D[I]);
- Data.replace(K.Pos + I * sizeof(uint64_t), sizeof(uint64_t),
- (const char *)&Bytes, sizeof(uint64_t));
- }
- }
- }
- }
-
- // If \c OS is an instance of \c raw_fd_ostream, this field will be
- // true. Otherwise, \c OS will be an raw_string_ostream.
- bool IsFDOStream;
- raw_ostream &OS;
- support::endian::Writer LE;
-};
-
-} // end namespace llvm
-
-void CodeGenDataWriter::addRecord(OutlinedHashTreeRecord &Record) {
- assert(Record.HashTree && "empty hash tree in the record");
- HashTreeRecord.HashTree = std::move(Record.HashTree);
-
- DataKind |= CGDataKind::FunctionOutlinedHashTree;
-}
-
-Error CodeGenDataWriter::write(raw_fd_ostream &OS) {
- CGDataOStream COS(OS);
- return writeImpl(COS);
-}
-
-Error CodeGenDataWriter::writeHeader(CGDataOStream &COS) {
- using namespace support;
- IndexedCGData::Header Header;
- Header.Magic = IndexedCGData::Magic;
- Header.Version = IndexedCGData::Version;
-
- // Set the CGDataKind depending on the kind.
- Header.DataKind = 0;
- if (static_cast<bool>(DataKind & CGDataKind::FunctionOutlinedHashTree))
- Header.DataKind |=
- static_cast<uint32_t>(CGDataKind::FunctionOutlinedHashTree);
-
- Header.OutlinedHashTreeOffset = 0;
-
- // Only write up to the CGDataKind. We need to remember the offset of the
- // remaining fields to allow back-patching later.
- COS.write(Header.Magic);
- COS.write32(Header.Version);
- COS.write32(Header.DataKind);
-
- // Save the location of Header.OutlinedHashTreeOffset field in \c COS.
- OutlinedHashTreeOffset = COS.tell();
-
- // Reserve the space for OutlinedHashTreeOffset field.
- COS.write(0);
-
- return Error::success();
-}
-
-Error CodeGenDataWriter::writeImpl(CGDataOStream &COS) {
- if (Error E = writeHeader(COS))
- return E;
-
- uint64_t OutlinedHashTreeFieldStart = COS.tell();
- if (hasOutlinedHashTree())
- HashTreeRecord.serialize(COS.OS);
-
- // Back patch the offsets.
- CGDataPatchItem PatchItems[] = {
- {OutlinedHashTreeOffset, &OutlinedHashTreeFieldStart, 1}};
- COS.patch(PatchItems);
-
- return Error::success();
-}
-
-Error CodeGenDataWriter::writeHeaderText(raw_fd_ostream &OS) {
- if (hasOutlinedHashTree())
- OS << "# Outlined stable hash tree\n:outlined_hash_tree\n";
-
- // TODO: Add more data types in this header
-
- return Error::success();
-}
-
-Error CodeGenDataWriter::writeText(raw_fd_ostream &OS) {
- if (Error E = writeHeaderText(OS))
- return E;
-
- yaml::Output YOS(OS);
- if (hasOutlinedHashTree())
- HashTreeRecord.serializeYAML(YOS);
-
- // TODO: Write more yaml cgdata in order
-
- return Error::success();
-}