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