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