diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2024-08-25 11:12:58 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2024-10-23 18:27:07 +0000 |
| commit | 62987288060ff68c817b7056815aa9fb8ba8ecd7 (patch) | |
| tree | d7953c9488f71e79d26c924169988f16e9ba9cee /contrib/llvm-project/llvm/lib/CodeGenData | |
| parent | 52418fc2be8efa5172b90a3a9e617017173612c4 (diff) | |
| parent | adf62863f35c84e4c5708f3dc5a1589ce958a238 (diff) | |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGenData')
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(); -} |
