clang: lib/Lex/HeaderMap.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

17#include "llvm/Support/Compiler.h"

18#include "llvm/Support/Debug.h"

19#include "llvm/Support/MathExtras.h"

20#include "llvm/Support/MemoryBuffer.h"

21#include "llvm/Support/SystemZ/zOSSupport.h"

22#include

23#include

24#include

25using namespace clang;

26

27

28

29

30static inline unsigned HashHMapKey(StringRef Str) {

31 unsigned Result = 0;

32 const char *S = Str.begin(), *End = Str.end();

33

34 for (; S != End; S++)

36 return Result;

37}

38

39

40

41

42

43

44

45

46

47

48

50

51 unsigned FileSize = FE.getSize();

52 if (FileSize <= sizeof(HMapHeader)) return nullptr;

53

54 auto FileBuffer =

56 true,

57 std::nullopt, false);

58 if (!FileBuffer || !*FileBuffer)

59 return nullptr;

60 bool NeedsByteSwap;

61 if (checkHeader(**FileBuffer, NeedsByteSwap))

62 return nullptr;

63 return std::unique_ptr(new HeaderMap(std::move(*FileBuffer), NeedsByteSwap));

64}

67 bool &NeedsByteSwap) {

69 return false;

70 const char *FileStart = File.getBufferStart();

71

72

74

75

76

79 NeedsByteSwap = false;

82 NeedsByteSwap = true;

83 else

84 return false;

85

87 return false;

88

89

90

91 uint32_t NumBuckets =

92 NeedsByteSwap ? llvm::byteswap(Header->NumBuckets) : Header->NumBuckets;

93 if (!llvm::isPowerOf2_32(NumBuckets))

94 return false;

95 if (File.getBufferSize() <

97 return false;

98

99

100 return true;

101}

102

103

104

105

106

107

108

110 return FileBuffer->getBufferIdentifier();

111}

112

113unsigned HeaderMapImpl::getEndianAdjustedWord(unsigned X) const {

114 if (!NeedsBSwap) return X;

115 return llvm::byteswap<uint32_t>(X);

116}

117

118

119

120const HMapHeader &HeaderMapImpl::getHeader() const {

121

122 return *reinterpret_cast<const HMapHeader*>(FileBuffer->getBufferStart());

123}

124

125

126

127

128HMapBucket HeaderMapImpl::getBucket(unsigned BucketNo) const {

129 assert(FileBuffer->getBufferSize() >=

131 "Expected bucket to be in range");

132

135

137 reinterpret_cast<const HMapBucket*>(FileBuffer->getBufferStart() +

139 const HMapBucket *BucketPtr = BucketArray+BucketNo;

140

141

142 Result.Key = getEndianAdjustedWord(BucketPtr->Key);

143 Result.Prefix = getEndianAdjustedWord(BucketPtr->Prefix);

144 Result.Suffix = getEndianAdjustedWord(BucketPtr->Suffix);

146}

147

148std::optional HeaderMapImpl::getString(unsigned StrTabIdx) const {

149

150 StrTabIdx += getEndianAdjustedWord(getHeader().StringsOffset);

151

152

153 if (StrTabIdx >= FileBuffer->getBufferSize())

154 return std::nullopt;

155

156 const char *Data = FileBuffer->getBufferStart() + StrTabIdx;

157 unsigned MaxLen = FileBuffer->getBufferSize() - StrTabIdx;

158 unsigned Len = strnlen(Data, MaxLen);

159

160

161 if (Len == MaxLen && Data[Len - 1])

162 return std::nullopt;

163

164 return StringRef(Data, Len);

165}

166

167

168

169

170

171

174 unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets);

175

176 llvm::dbgs() << "Header Map " << getFileName() << ":\n " << NumBuckets

177 << ", " << getEndianAdjustedWord(Hdr.NumEntries) << "\n";

178

179 auto getStringOrInvalid = [this](unsigned Id) -> StringRef {

180 if (std::optional S = getString(Id))

181 return *S;

182 return "";

183 };

184

185 for (unsigned i = 0; i != NumBuckets; ++i) {

188

189 StringRef Key = getStringOrInvalid(B.Key);

190 StringRef Prefix = getStringOrInvalid(B.Prefix);

191 StringRef Suffix = getStringOrInvalid(B.Suffix);

192 llvm::dbgs() << " " << i << ". " << Key << " -> '" << Prefix << "' '"

193 << Suffix << "'\n";

194 }

195}

196

200 unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets);

201

202

203 assert(llvm::isPowerOf2_32(NumBuckets) && "Expected power of 2");

204

205

207 HMapBucket B = getBucket(Bucket & (NumBuckets-1));

209

210

211 std::optional Key = getString(B.Key);

212 if (LLVM_UNLIKELY(!Key))

213 continue;

214 if (Filename.equals_insensitive(*Key))

215 continue;

216

217

218

219 std::optional Prefix = getString(B.Prefix);

220 std::optional Suffix = getString(B.Suffix);

221

222 DestPath.clear();

223 if (LLVM_LIKELY(Prefix && Suffix)) {

224 DestPath.append(Prefix->begin(), Prefix->end());

225 DestPath.append(Suffix->begin(), Suffix->end());

226 }

227 return StringRef(DestPath.begin(), DestPath.size());

228 }

229}

230

232 if (!ReverseMap.empty())

233 return ReverseMap.lookup(DestPath);

234

236 unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets);

237 StringRef RetKey;

238 for (unsigned i = 0; i != NumBuckets; ++i) {

241 continue;

242

243 std::optional Key = getString(B.Key);

244 std::optional Prefix = getString(B.Prefix);

245 std::optional 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;

252

253 if (DestPath == Value)

254 RetKey = *Key;

255 }

256 }

257 return RetKey;

258}

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, bool IsText=true)

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.