1 //===- CodeGenDataReader.h --------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains support for reading codegen data. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CGDATA_CODEGENDATAREADER_H 14 #define LLVM_CGDATA_CODEGENDATAREADER_H 15 16 #include "llvm/CGData/CodeGenData.h" 17 #include "llvm/CGData/OutlinedHashTreeRecord.h" 18 #include "llvm/CGData/StableFunctionMapRecord.h" 19 #include "llvm/Support/Compiler.h" 20 #include "llvm/Support/LineIterator.h" 21 #include "llvm/Support/VirtualFileSystem.h" 22 23 namespace llvm { 24 25 class CodeGenDataReader { 26 cgdata_error LastError = cgdata_error::success; 27 std::string LastErrorMsg; 28 29 public: 30 CodeGenDataReader() = default; 31 virtual ~CodeGenDataReader() = default; 32 33 /// Read the header. Required before reading first record. 34 virtual Error read() = 0; 35 /// Return the codegen data version. 36 virtual uint32_t getVersion() const = 0; 37 /// Return the codegen data kind. 38 virtual CGDataKind getDataKind() const = 0; 39 /// Return true if the data has an outlined hash tree. 40 virtual bool hasOutlinedHashTree() const = 0; 41 /// Return true if the data has a stable function map. 42 virtual bool hasStableFunctionMap() const = 0; 43 /// Return the outlined hash tree that is released from the reader. releaseOutlinedHashTree()44 std::unique_ptr<OutlinedHashTree> releaseOutlinedHashTree() { 45 return std::move(HashTreeRecord.HashTree); 46 } releaseStableFunctionMap()47 std::unique_ptr<StableFunctionMap> releaseStableFunctionMap() { 48 return std::move(FunctionMapRecord.FunctionMap); 49 } 50 51 /// Factory method to create an appropriately typed reader for the given 52 /// codegen data file path and file system. 53 LLVM_ABI static Expected<std::unique_ptr<CodeGenDataReader>> 54 create(const Twine &Path, vfs::FileSystem &FS); 55 56 /// Factory method to create an appropriately typed reader for the given 57 /// memory buffer. 58 LLVM_ABI static Expected<std::unique_ptr<CodeGenDataReader>> 59 create(std::unique_ptr<MemoryBuffer> Buffer); 60 61 /// Extract the cgdata embedded in sections from the given object file and 62 /// merge them into the GlobalOutlineRecord. This is a static helper that 63 /// is used by `llvm-cgdata --merge` or ThinLTO's two-codegen rounds. 64 /// Optionally, \p CombinedHash can be used to compuate the combined hash of 65 /// the merged data. 66 LLVM_ABI static Error 67 mergeFromObjectFile(const object::ObjectFile *Obj, 68 OutlinedHashTreeRecord &GlobalOutlineRecord, 69 StableFunctionMapRecord &GlobalFunctionMapRecord, 70 stable_hash *CombinedHash = nullptr); 71 72 protected: 73 /// The outlined hash tree that has been read. When it's released by 74 /// releaseOutlinedHashTree(), it's no longer valid. 75 OutlinedHashTreeRecord HashTreeRecord; 76 77 /// The stable function map that has been read. When it's released by 78 // releaseStableFunctionMap(), it's no longer valid. 79 StableFunctionMapRecord FunctionMapRecord; 80 81 /// Set the current error and return same. 82 Error error(cgdata_error Err, const std::string &ErrMsg = "") { 83 LastError = Err; 84 LastErrorMsg = ErrMsg; 85 if (Err == cgdata_error::success) 86 return Error::success(); 87 return make_error<CGDataError>(Err, ErrMsg); 88 } 89 error(Error && E)90 Error error(Error &&E) { 91 handleAllErrors(std::move(E), [&](const CGDataError &IPE) { 92 LastError = IPE.get(); 93 LastErrorMsg = IPE.getMessage(); 94 }); 95 return make_error<CGDataError>(LastError, LastErrorMsg); 96 } 97 98 /// Clear the current error and return a successful one. success()99 Error success() { return error(cgdata_error::success); } 100 }; 101 102 class LLVM_ABI IndexedCodeGenDataReader : public CodeGenDataReader { 103 /// The codegen data file contents. 104 std::unique_ptr<MemoryBuffer> DataBuffer; 105 /// The header 106 IndexedCGData::Header Header; 107 108 public: IndexedCodeGenDataReader(std::unique_ptr<MemoryBuffer> DataBuffer)109 IndexedCodeGenDataReader(std::unique_ptr<MemoryBuffer> DataBuffer) 110 : DataBuffer(std::move(DataBuffer)) {} 111 IndexedCodeGenDataReader(const IndexedCodeGenDataReader &) = delete; 112 IndexedCodeGenDataReader & 113 operator=(const IndexedCodeGenDataReader &) = delete; 114 115 /// Return true if the given buffer is in binary codegen data format. 116 static bool hasFormat(const MemoryBuffer &Buffer); 117 /// Read the contents including the header. 118 Error read() override; 119 /// Return the codegen data version. getVersion()120 uint32_t getVersion() const override { return Header.Version; } 121 /// Return the codegen data kind. getDataKind()122 CGDataKind getDataKind() const override { 123 return static_cast<CGDataKind>(Header.DataKind); 124 } 125 /// Return true if the header indicates the data has an outlined hash tree. 126 /// This does not mean that the data is still available. hasOutlinedHashTree()127 bool hasOutlinedHashTree() const override { 128 return Header.DataKind & 129 static_cast<uint32_t>(CGDataKind::FunctionOutlinedHashTree); 130 } 131 /// Return true if the header indicates the data has a stable function map. hasStableFunctionMap()132 bool hasStableFunctionMap() const override { 133 return Header.DataKind & 134 static_cast<uint32_t>(CGDataKind::StableFunctionMergingMap); 135 } 136 }; 137 138 /// This format is a simple text format that's suitable for test data. 139 /// The header is a custom format starting with `:` per line to indicate which 140 /// codegen data is recorded. `#` is used to indicate a comment. 141 /// The subsequent data is a YAML format per each codegen data in order. 142 /// Currently, it only has a function outlined hash tree. 143 class LLVM_ABI TextCodeGenDataReader : public CodeGenDataReader { 144 /// The codegen data file contents. 145 std::unique_ptr<MemoryBuffer> DataBuffer; 146 /// Iterator over the profile data. 147 line_iterator Line; 148 /// Describe the kind of the codegen data. 149 CGDataKind DataKind = CGDataKind::Unknown; 150 151 public: TextCodeGenDataReader(std::unique_ptr<MemoryBuffer> DataBuffer_)152 TextCodeGenDataReader(std::unique_ptr<MemoryBuffer> DataBuffer_) 153 : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} 154 TextCodeGenDataReader(const TextCodeGenDataReader &) = delete; 155 TextCodeGenDataReader &operator=(const TextCodeGenDataReader &) = delete; 156 157 /// Return true if the given buffer is in text codegen data format. 158 static bool hasFormat(const MemoryBuffer &Buffer); 159 /// Read the contents including the header. 160 Error read() override; 161 /// Text format does not have version, so return 0. getVersion()162 uint32_t getVersion() const override { return 0; } 163 /// Return the codegen data kind. getDataKind()164 CGDataKind getDataKind() const override { return DataKind; } 165 /// Return true if the header indicates the data has an outlined hash tree. 166 /// This does not mean that the data is still available. hasOutlinedHashTree()167 bool hasOutlinedHashTree() const override { 168 return static_cast<uint32_t>(DataKind) & 169 static_cast<uint32_t>(CGDataKind::FunctionOutlinedHashTree); 170 } 171 /// Return true if the header indicates the data has a stable function map. 172 /// This does not mean that the data is still available. hasStableFunctionMap()173 bool hasStableFunctionMap() const override { 174 return static_cast<uint32_t>(DataKind) & 175 static_cast<uint32_t>(CGDataKind::StableFunctionMergingMap); 176 } 177 }; 178 179 } // end namespace llvm 180 181 #endif // LLVM_CGDATA_CODEGENDATAREADER_H 182