69 const char *FileStart =
File.getBufferStart();
78 NeedsByteSwap =
false;
91 NeedsByteSwap ? llvm::byteswap(Header->
NumBuckets) : Header->NumBuckets;
92 if (!llvm::isPowerOf2_32(NumBuckets))
94 if (
File.getBufferSize() <
109 return FileBuffer->getBufferIdentifier();
112unsigned HeaderMapImpl::getEndianAdjustedWord(
unsigned X)
const {
113 if (!NeedsBSwap)
return X;
114 return llvm::byteswap<uint32_t>(
X);
119const HMapHeader &HeaderMapImpl::getHeader()
const {
121 return *
reinterpret_cast<const HMapHeader*
>(FileBuffer->getBufferStart());
127HMapBucket HeaderMapImpl::getBucket(
unsigned BucketNo)
const {
128 assert(FileBuffer->getBufferSize() >=
129 sizeof(HMapHeader) +
sizeof(HMapBucket) * BucketNo &&
130 "Expected bucket to be in range");
135 const HMapBucket *BucketArray =
136 reinterpret_cast<const HMapBucket*
>(FileBuffer->getBufferStart() +
138 const HMapBucket *BucketPtr = BucketArray+BucketNo;
141 Result.Key = getEndianAdjustedWord(BucketPtr->
Key);
142 Result.Prefix = getEndianAdjustedWord(BucketPtr->
Prefix);
143 Result.Suffix = getEndianAdjustedWord(BucketPtr->
Suffix);
147std::optional<StringRef> HeaderMapImpl::getString(
unsigned StrTabIdx)
const {
149 StrTabIdx += getEndianAdjustedWord(getHeader().StringsOffset);
152 if (StrTabIdx >= FileBuffer->getBufferSize())
155 const char *
Data = FileBuffer->getBufferStart() + StrTabIdx;
156 unsigned MaxLen = FileBuffer->getBufferSize() - StrTabIdx;
161 unsigned Len = strnlen(
Data, MaxLen);
164 if (Len == MaxLen &&
Data[Len - 1])
167 return StringRef(
Data, Len);
177 unsigned NumBuckets = getEndianAdjustedWord(Hdr.
NumBuckets);
179 llvm::dbgs() <<
"Header Map " <<
getFileName() <<
":\n " << NumBuckets
180 <<
", " << getEndianAdjustedWord(Hdr.
NumEntries) <<
"\n";
182 auto getStringOrInvalid = [
this](
unsigned Id) -> StringRef {
183 if (std::optional<StringRef> S = getString(Id))
188 for (
unsigned i = 0; i != NumBuckets; ++i) {
192 StringRef Key = getStringOrInvalid(B.
Key);
193 StringRef Prefix = getStringOrInvalid(B.
Prefix);
194 StringRef Suffix = getStringOrInvalid(B.
Suffix);
195 llvm::dbgs() <<
" " << i <<
". " << Key <<
" -> '" << Prefix <<
"' '"
203 unsigned NumBuckets = getEndianAdjustedWord(Hdr.
NumBuckets);
206 assert(llvm::isPowerOf2_32(NumBuckets) &&
"Expected power of 2");
209 for (
unsigned Bucket =
HashHMapKey(Filename);; ++Bucket) {
210 HMapBucket B = getBucket(Bucket & (NumBuckets-1));
214 std::optional<StringRef> Key = getString(B.
Key);
215 if (LLVM_UNLIKELY(!Key))
217 if (!Filename.equals_insensitive(*Key))
222 std::optional<StringRef> Prefix = getString(B.
Prefix);
223 std::optional<StringRef> Suffix = getString(B.
Suffix);
226 if (LLVM_LIKELY(Prefix && Suffix)) {
227 DestPath.append(Prefix->begin(), Prefix->end());
228 DestPath.append(Suffix->begin(), Suffix->end());
230 return StringRef(DestPath.begin(), DestPath.size());
235 if (!ReverseMap.empty())
236 return ReverseMap.lookup(DestPath);
239 unsigned NumBuckets = getEndianAdjustedWord(Hdr.
NumBuckets);
241 for (
unsigned i = 0; i != NumBuckets; ++i) {
246 std::optional<StringRef> Key = getString(B.
Key);
247 std::optional<StringRef> Prefix = getString(B.
Prefix);
248 std::optional<StringRef> Suffix = getString(B.
Suffix);
249 if (LLVM_LIKELY(Key && Prefix && Suffix)) {
251 Buf.append(Prefix->begin(), Prefix->end());
252 Buf.append(Suffix->begin(), Suffix->end());
253 StringRef
Value(Buf.begin(), Buf.size());
254 ReverseMap[
Value] = *Key;
256 if (DestPath ==
Value)