LLVM 20.0.0git
CodeGenDataReader.cpp
Go to the documentation of this file.
1//===- CodeGenDataReader.cpp ----------------------------------------------===//
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
17
18#define DEBUG_TYPE "cg-data-reader"
19
20using namespace llvm;
21
22namespace llvm {
23
26 auto BufferOrErr = Filename.str() == "-" ? MemoryBuffer::getSTDIN()
27 : FS.getBufferForFile(Filename);
28 if (std::error_code EC = BufferOrErr.getError())
29 return errorCodeToError(EC);
30 return std::move(BufferOrErr.get());
31}
32
34 const object::ObjectFile *Obj,
35 OutlinedHashTreeRecord &GlobalOutlineRecord) {
36 Triple TT = Obj->makeTriple();
37 auto CGOutLineName =
38 getCodeGenDataSectionName(CG_outline, TT.getObjectFormat(), false);
39
40 for (auto &Section : Obj->sections()) {
41 Expected<StringRef> NameOrErr = Section.getName();
42 if (!NameOrErr)
43 return NameOrErr.takeError();
44 Expected<StringRef> ContentsOrErr = Section.getContents();
45 if (!ContentsOrErr)
46 return ContentsOrErr.takeError();
47 auto *Data = reinterpret_cast<const unsigned char *>(ContentsOrErr->data());
48 auto *EndData = Data + ContentsOrErr->size();
49
50 if (*NameOrErr == CGOutLineName) {
51 // In case dealing with an executable that has concatenated cgdata,
52 // we want to merge them into a single cgdata.
53 // Although it's not a typical workflow, we support this scenario.
54 while (Data != EndData) {
55 OutlinedHashTreeRecord LocalOutlineRecord;
56 LocalOutlineRecord.deserialize(Data);
57 GlobalOutlineRecord.merge(LocalOutlineRecord);
58 }
59 }
60 // TODO: Add support for other cgdata sections.
61 }
62
63 return Error::success();
64}
65
67 using namespace support;
68
69 // The smallest header with the version 1 is 24 bytes
70 const unsigned MinHeaderSize = 24;
71 if (DataBuffer->getBufferSize() < MinHeaderSize)
73
74 auto *Start =
75 reinterpret_cast<const unsigned char *>(DataBuffer->getBufferStart());
76 auto *End =
77 reinterpret_cast<const unsigned char *>(DataBuffer->getBufferEnd());
78 if (auto E = IndexedCGData::Header::readFromBuffer(Start).moveInto(Header))
79 return E;
80
81 if (hasOutlinedHashTree()) {
82 const unsigned char *Ptr = Start + Header.OutlinedHashTreeOffset;
83 if (Ptr >= End)
86 }
87
88 return success();
89}
90
93 // Set up the buffer to read.
94 auto BufferOrError = setupMemoryBuffer(Path, FS);
95 if (Error E = BufferOrError.takeError())
96 return std::move(E);
97 return CodeGenDataReader::create(std::move(BufferOrError.get()));
98}
99
101CodeGenDataReader::create(std::unique_ptr<MemoryBuffer> Buffer) {
102 if (Buffer->getBufferSize() == 0)
103 return make_error<CGDataError>(cgdata_error::empty_cgdata);
104
105 std::unique_ptr<CodeGenDataReader> Reader;
106 // Create the reader.
108 Reader = std::make_unique<IndexedCodeGenDataReader>(std::move(Buffer));
109 else if (TextCodeGenDataReader::hasFormat(*Buffer))
110 Reader = std::make_unique<TextCodeGenDataReader>(std::move(Buffer));
111 else
112 return make_error<CGDataError>(cgdata_error::malformed);
113
114 // Initialize the reader and return the result.
115 if (Error E = Reader->read())
116 return std::move(E);
117
118 return std::move(Reader);
119}
120
122 using namespace support;
123 if (DataBuffer.getBufferSize() < sizeof(IndexedCGData::Magic))
124 return false;
125
126 uint64_t Magic = endian::read<uint64_t, llvm::endianness::little, aligned>(
127 DataBuffer.getBufferStart());
128 // Verify that it's magical.
129 return Magic == IndexedCGData::Magic;
130}
131
133 // Verify that this really looks like plain ASCII text by checking a
134 // 'reasonable' number of characters (up to the magic size).
135 StringRef Prefix = Buffer.getBuffer().take_front(sizeof(uint64_t));
136 return llvm::all_of(Prefix, [](char c) { return isPrint(c) || isSpace(c); });
137}
139 using namespace support;
140
141 // Parse the custom header line by line.
142 for (; !Line.is_at_eof(); ++Line) {
143 // Skip empty or whitespace-only lines
144 if (Line->trim().empty())
145 continue;
146
147 if (!Line->starts_with(":"))
148 break;
149 StringRef Str = Line->drop_front().rtrim();
150 if (Str.equals_insensitive("outlined_hash_tree"))
152 else
154 }
155
156 // We treat an empty header (that is a comment # only) as a valid header.
157 if (Line.is_at_eof()) {
158 if (DataKind == CGDataKind::Unknown)
159 return Error::success();
161 }
162
163 // The YAML docs follow after the header.
164 const char *Pos = Line->data();
165 size_t Size = reinterpret_cast<size_t>(DataBuffer->getBufferEnd()) -
166 reinterpret_cast<size_t>(Pos);
167 yaml::Input YOS(StringRef(Pos, Size));
170
171 // TODO: Add more yaml cgdata in order
172
173 return Error::success();
174}
175} // end namespace llvm
uint64_t Size
bool End
Definition: ELF_riscv.cpp:480
#define error(X)
Error success()
Clear the current error and return a successful one.
OutlinedHashTreeRecord HashTreeRecord
The outlined hash tree that has been read.
static Expected< std::unique_ptr< CodeGenDataReader > > create(const Twine &Path, vfs::FileSystem &FS)
Factory method to create an appropriately typed reader for the given codegen data file path and file ...
static Error mergeFromObjectFile(const object::ObjectFile *Obj, OutlinedHashTreeRecord &GlobalOutlineRecord)
Extract the cgdata embedded in sections from the given object file and merge them into the GlobalOutl...
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
Error takeError()
Take ownership of the stored error.
Definition: Error.h:608
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if the given buffer is in binary codegen data format.
Error read() override
Read the contents including the header.
bool hasOutlinedHashTree() const override
Return true if the header indicates the data has an outlined hash tree.
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:51
size_t getBufferSize() const
Definition: MemoryBuffer.h:68
StringRef getBuffer() const
Definition: MemoryBuffer.h:70
static ErrorOr< std::unique_ptr< MemoryBuffer > > getSTDIN()
Read all of stdin into a file buffer, and return it.
const char * getBufferStart() const
Definition: MemoryBuffer.h:66
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:250
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition: StringRef.h:594
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:131
StringRef rtrim(char Char) const
Return string with consecutive Char characters starting from the right removed.
Definition: StringRef.h:788
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Definition: StringRef.h:565
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
Definition: StringRef.h:800
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if the given buffer is in text codegen data format.
bool hasOutlinedHashTree() const override
Return true if the header indicates the data has an outlined hash tree.
Error read() override
Read the contents including the header.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
bool is_at_eof() const
Return true if we've reached EOF or are an "end" iterator.
Definition: LineIterator.h:60
This class is the base class for all object file types.
Definition: ObjectFile.h:229
Triple makeTriple() const
Create a triple from the data in this object file.
Definition: ObjectFile.cpp:109
section_iterator_range sections() const
Definition: ObjectFile.h:329
The virtual file system interface.
const uint64_t Magic
Definition: CodeGenData.h:176
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
static Expected< std::unique_ptr< MemoryBuffer > > setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1722
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:111
std::string getCodeGenDataSectionName(CGDataSectKind CGSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
static Expected< Header > readFromBuffer(const unsigned char *Curr)
void deserializeYAML(yaml::Input &YIS)
Deserialize the outlined hash tree from a YAML stream.
void deserialize(const unsigned char *&Ptr)
Deserialize the outlined hash tree from a raw_ostream.
void merge(const OutlinedHashTreeRecord &Other)
Merge the other outlined hash tree into this one.