17#include "llvm/ADT/SmallString.h"
18#include "llvm/Support/Compiler.h"
19#include "llvm/Support/DataTypes.h"
20#include "llvm/Support/Debug.h"
21#include "llvm/Support/MathExtras.h"
22#include "llvm/Support/MemoryBuffer.h"
23#include "llvm/Support/SwapByteOrder.h"
24#include "llvm/Support/SystemZ/zOSSupport.h"
35 const char *S = Str.begin(), *End = Str.end();
54 unsigned FileSize = FE.
getSize();
55 if (FileSize <=
sizeof(
HMapHeader))
return nullptr;
58 if (!FileBuffer || !*FileBuffer)
63 return std::unique_ptr<HeaderMap>(
new HeaderMap(std::move(*FileBuffer), NeedsByteSwap));
67 bool &NeedsByteSwap) {
70 const char *FileStart =
File.getBufferStart();
79 NeedsByteSwap =
false;
92 NeedsByteSwap ? llvm::byteswap(Header->
NumBuckets) : Header->NumBuckets;
93 if (!llvm::isPowerOf2_32(NumBuckets))
95 if (
File.getBufferSize() <
110 return FileBuffer->getBufferIdentifier();
113unsigned HeaderMapImpl::getEndianAdjustedWord(
unsigned X)
const {
114 if (!NeedsBSwap)
return X;
115 return llvm::byteswap<uint32_t>(
X);
120const HMapHeader &HeaderMapImpl::getHeader()
const {
122 return *
reinterpret_cast<const HMapHeader*
>(FileBuffer->getBufferStart());
128HMapBucket HeaderMapImpl::getBucket(
unsigned BucketNo)
const {
129 assert(FileBuffer->getBufferSize() >=
131 "Expected bucket to be in range");
137 reinterpret_cast<const HMapBucket*
>(FileBuffer->getBufferStart() +
139 const HMapBucket *BucketPtr = BucketArray+BucketNo;
142 Result.Key = getEndianAdjustedWord(BucketPtr->
Key);
143 Result.Prefix = getEndianAdjustedWord(BucketPtr->
Prefix);
144 Result.Suffix = getEndianAdjustedWord(BucketPtr->
Suffix);
148std::optional<StringRef> HeaderMapImpl::getString(
unsigned StrTabIdx)
const {
150 StrTabIdx += getEndianAdjustedWord(getHeader().StringsOffset);
153 if (StrTabIdx >= FileBuffer->getBufferSize())
156 const char *
Data = FileBuffer->getBufferStart() + StrTabIdx;
157 unsigned MaxLen = FileBuffer->getBufferSize() - StrTabIdx;
158 unsigned Len = strnlen(
Data, MaxLen);
161 if (Len == MaxLen &&
Data[Len - 1])
164 return StringRef(
Data, Len);
174 unsigned NumBuckets = getEndianAdjustedWord(Hdr.
NumBuckets);
176 llvm::dbgs() <<
"Header Map " <<
getFileName() <<
":\n " << NumBuckets
177 <<
", " << getEndianAdjustedWord(Hdr.
NumEntries) <<
"\n";
179 auto getStringOrInvalid = [
this](
unsigned Id) -> StringRef {
180 if (std::optional<StringRef> S = getString(
Id))
185 for (
unsigned i = 0; i != NumBuckets; ++i) {
189 StringRef Key = getStringOrInvalid(B.
Key);
190 StringRef Prefix = getStringOrInvalid(B.
Prefix);
191 StringRef Suffix = getStringOrInvalid(B.
Suffix);
192 llvm::dbgs() <<
" " << i <<
". " << Key <<
" -> '" << Prefix <<
"' '"
200 unsigned NumBuckets = getEndianAdjustedWord(Hdr.
NumBuckets);
203 assert(llvm::isPowerOf2_32(NumBuckets) &&
"Expected power of 2");
207 HMapBucket B = getBucket(Bucket & (NumBuckets-1));
211 std::optional<StringRef> Key = getString(B.
Key);
212 if (LLVM_UNLIKELY(!Key))
214 if (!
Filename.equals_insensitive(*Key))
219 std::optional<StringRef> Prefix = getString(B.
Prefix);
220 std::optional<StringRef> Suffix = getString(B.
Suffix);
223 if (LLVM_LIKELY(Prefix && Suffix)) {
224 DestPath.append(Prefix->begin(), Prefix->end());
225 DestPath.append(Suffix->begin(), Suffix->end());
227 return StringRef(DestPath.begin(), DestPath.size());
232 if (!ReverseMap.empty())
233 return ReverseMap.lookup(DestPath);
236 unsigned NumBuckets = getEndianAdjustedWord(Hdr.
NumBuckets);
238 for (
unsigned i = 0; i != NumBuckets; ++i) {
243 std::optional<StringRef> Key = getString(B.
Key);
244 std::optional<StringRef> Prefix = getString(B.
Prefix);
245 std::optional<StringRef> Suffix = getString(B.
Suffix);
246 if (LLVM_LIKELY(Key && Prefix && Suffix)) {
248 Buf.append(Prefix->begin(), Prefix->end());
249 Buf.append(Suffix->begin(), Suffix->end());
250 StringRef
Value(Buf.begin(), Buf.size());
251 ReverseMap[
Value] = *Key;
253 if (DestPath ==
Value)
Defines the clang::FileManager interface and associated types.
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
Implements support for file system lookup, file system caching, and directory search management.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(FileEntryRef Entry, bool isVolatile=false, bool RequiresNullTerminator=true, std::optional< int64_t > MaybeLimit=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
The JSON file list parser is used to communicate input to InstallAPI.
LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
@ Result
The result type of a method or function.