//===- CodeGenDataReader.h --------------------------------------*- C++ -*-===// // // 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. // //===----------------------------------------------------------------------===// #ifndef LLVM_CGDATA_CODEGENDATAREADER_H #define LLVM_CGDATA_CODEGENDATAREADER_H #include "llvm/CGData/CodeGenData.h" #include "llvm/CGData/OutlinedHashTreeRecord.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/VirtualFileSystem.h" namespace llvm { class CodeGenDataReader { cgdata_error LastError = cgdata_error::success; std::string LastErrorMsg; public: CodeGenDataReader() = default; virtual ~CodeGenDataReader() = default; /// Read the header. Required before reading first record. virtual Error read() = 0; /// Return the codegen data version. virtual uint32_t getVersion() const = 0; /// Return the codegen data kind. virtual CGDataKind getDataKind() const = 0; /// Return true if the data has an outlined hash tree. virtual bool hasOutlinedHashTree() const = 0; /// Return the outlined hash tree that is released from the reader. std::unique_ptr releaseOutlinedHashTree() { return std::move(HashTreeRecord.HashTree); } /// Factory method to create an appropriately typed reader for the given /// codegen data file path and file system. static Expected> create(const Twine &Path, vfs::FileSystem &FS); /// Factory method to create an appropriately typed reader for the given /// memory buffer. static Expected> create(std::unique_ptr Buffer); /// Extract the cgdata embedded in sections from the given object file and /// merge them into the GlobalOutlineRecord. This is a static helper that /// is used by `llvm-cgdata --merge` or ThinLTO's two-codegen rounds. static Error mergeFromObjectFile(const object::ObjectFile *Obj, OutlinedHashTreeRecord &GlobalOutlineRecord); protected: /// The outlined hash tree that has been read. When it's released by /// releaseOutlinedHashTree(), it's no longer valid. OutlinedHashTreeRecord HashTreeRecord; /// Set the current error and return same. Error error(cgdata_error Err, const std::string &ErrMsg = "") { LastError = Err; LastErrorMsg = ErrMsg; if (Err == cgdata_error::success) return Error::success(); return make_error(Err, ErrMsg); } Error error(Error &&E) { handleAllErrors(std::move(E), [&](const CGDataError &IPE) { LastError = IPE.get(); LastErrorMsg = IPE.getMessage(); }); return make_error(LastError, LastErrorMsg); } /// Clear the current error and return a successful one. Error success() { return error(cgdata_error::success); } }; class IndexedCodeGenDataReader : public CodeGenDataReader { /// The codegen data file contents. std::unique_ptr DataBuffer; /// The header IndexedCGData::Header Header; public: IndexedCodeGenDataReader(std::unique_ptr DataBuffer) : DataBuffer(std::move(DataBuffer)) {} IndexedCodeGenDataReader(const IndexedCodeGenDataReader &) = delete; IndexedCodeGenDataReader & operator=(const IndexedCodeGenDataReader &) = delete; /// Return true if the given buffer is in binary codegen data format. static bool hasFormat(const MemoryBuffer &Buffer); /// Read the contents including the header. Error read() override; /// Return the codegen data version. uint32_t getVersion() const override { return Header.Version; } /// Return the codegen data kind. CGDataKind getDataKind() const override { return static_cast(Header.DataKind); } /// Return true if the header indicates the data has an outlined hash tree. /// This does not mean that the data is still available. bool hasOutlinedHashTree() const override { return Header.DataKind & static_cast(CGDataKind::FunctionOutlinedHashTree); } }; /// This format is a simple text format that's suitable for test data. /// The header is a custom format starting with `:` per line to indicate which /// codegen data is recorded. `#` is used to indicate a comment. /// The subsequent data is a YAML format per each codegen data in order. /// Currently, it only has a function outlined hash tree. class TextCodeGenDataReader : public CodeGenDataReader { /// The codegen data file contents. std::unique_ptr DataBuffer; /// Iterator over the profile data. line_iterator Line; /// Describe the kind of the codegen data. CGDataKind DataKind = CGDataKind::Unknown; public: TextCodeGenDataReader(std::unique_ptr DataBuffer_) : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} TextCodeGenDataReader(const TextCodeGenDataReader &) = delete; TextCodeGenDataReader &operator=(const TextCodeGenDataReader &) = delete; /// Return true if the given buffer is in text codegen data format. static bool hasFormat(const MemoryBuffer &Buffer); /// Read the contents including the header. Error read() override; /// Text format does not have version, so return 0. uint32_t getVersion() const override { return 0; } /// Return the codegen data kind. CGDataKind getDataKind() const override { return DataKind; } /// Return true if the header indicates the data has an outlined hash tree. /// This does not mean that the data is still available. bool hasOutlinedHashTree() const override { return static_cast(DataKind) & static_cast(CGDataKind::FunctionOutlinedHashTree); } }; } // end namespace llvm #endif // LLVM_CGDATA_CODEGENDATAREADER_H